View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.security.visibility;
19  
20  import java.io.IOException;
21  import java.util.ArrayList;
22  import java.util.List;
23  import java.util.UUID;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  import org.apache.hadoop.hbase.Cell;
28  import org.apache.hadoop.hbase.KeyValue;
29  import org.apache.hadoop.hbase.Tag;
30  import org.apache.hadoop.hbase.TagType;
31  import org.apache.hadoop.hbase.KeyValue.Type;
32  import org.apache.hadoop.hbase.classification.InterfaceAudience;
33  import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
34  import org.apache.hadoop.hbase.replication.ReplicationEndpoint;
35  import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
36  import org.apache.hadoop.hbase.replication.WALEntryFilter;
37  import org.apache.hadoop.hbase.regionserver.wal.HLog.Entry;
38  
39  import com.google.common.util.concurrent.ListenableFuture;
40  
41  @InterfaceAudience.Private
42  public class VisibilityReplicationEndpoint implements ReplicationEndpoint {
43  
44    private static final Log LOG = LogFactory.getLog(VisibilityReplicationEndpoint.class);
45    private ReplicationEndpoint delegator;
46    private VisibilityLabelService visibilityLabelsService;
47  
48    public VisibilityReplicationEndpoint(ReplicationEndpoint endpoint,
49        VisibilityLabelService visibilityLabelsService) {
50      this.delegator = endpoint;
51      this.visibilityLabelsService = visibilityLabelsService;
52    }
53  
54    @Override
55    public void init(Context context) throws IOException {
56      delegator.init(context);
57    }
58  
59    @Override
60    public boolean replicate(ReplicateContext replicateContext) {
61      if (!delegator.canReplicateToSameCluster()) {
62        // Only when the replication is inter cluster replication we need to covert the visibility tags to
63        // string based tags.  But for intra cluster replication like region replicas it is not needed.
64        List<Entry> entries = replicateContext.getEntries();
65        List<Tag> visTags = new ArrayList<Tag>();
66        List<Tag> nonVisTags = new ArrayList<Tag>();
67        List<Entry> newEntries = new ArrayList<Entry>(entries.size());
68        for (Entry entry : entries) {
69          WALEdit newEdit = new WALEdit();
70          ArrayList<Cell> cells = entry.getEdit().getCells();
71          for (Cell cell : cells) {
72            if (cell.getTagsLengthUnsigned() > 0) {
73              visTags.clear();
74              nonVisTags.clear();
75              Byte serializationFormat = VisibilityUtils.extractAndPartitionTags(cell, visTags,
76                  nonVisTags);
77              if (!visTags.isEmpty()) {
78                try {
79                  byte[] modifiedVisExpression = visibilityLabelsService
80                      .encodeVisibilityForReplication(visTags, serializationFormat);
81                  if (modifiedVisExpression != null) {
82                    nonVisTags.add(new Tag(TagType.STRING_VIS_TAG_TYPE, modifiedVisExpression));
83                  }
84                } catch (Exception ioe) {
85                  LOG.error(
86                      "Exception while reading the visibility labels from the cell. The replication "
87                          + "would happen as per the existing format and not as string type for the cell "
88                          + cell + ".", ioe);
89                  // just return the old entries as it is without applying the string type change
90                  newEdit.add(cell);
91                  continue;
92                }
93                // Recreate the cell with the new tags and the existing tags
94                Cell newCell = new KeyValue(cell.getRowArray(), cell.getRowOffset(),
95                    cell.getRowLength(), cell.getFamilyArray(), cell.getFamilyOffset(),
96                    cell.getFamilyLength(), cell.getQualifierArray(), cell.getQualifierOffset(),
97                    cell.getQualifierLength(), cell.getTimestamp(), Type.codeToType(cell
98                        .getTypeByte()), cell.getValueArray(), cell.getValueOffset(),
99                    cell.getValueLength(), nonVisTags);
100               newEdit.add(newCell);
101             } else {
102               newEdit.add(cell);
103             }
104           } else {
105             newEdit.add(cell);
106           }
107         }
108         newEntries.add(new Entry(entry.getKey(), newEdit));
109       }
110       replicateContext.setEntries(newEntries);
111       return delegator.replicate(replicateContext);
112     } else {
113       return delegator.replicate(replicateContext);
114     }
115   }
116 
117   @Override
118   public synchronized UUID getPeerUUID() {
119     return delegator.getPeerUUID();
120   }
121 
122   @Override
123   public boolean canReplicateToSameCluster() {
124     return delegator.canReplicateToSameCluster();
125   }
126 
127   @Override
128   public WALEntryFilter getWALEntryfilter() {
129     return delegator.getWALEntryfilter();
130   }
131 
132   @Override
133   public boolean isRunning() {
134     return delegator.isRunning();
135   }
136 
137   @Override
138   public ListenableFuture<State> start() {
139     return delegator.start();
140   }
141 
142   @Override
143   public State startAndWait() {
144     return delegator.startAndWait();
145   }
146 
147   @Override
148   public State state() {
149     return delegator.state();
150   }
151 
152   @Override
153   public ListenableFuture<State> stop() {
154     return delegator.stop();
155   }
156 
157   @Override
158   public State stopAndWait() {
159     return delegator.stopAndWait();
160   }
161 
162   @Override
163   public void peerConfigUpdated(ReplicationPeerConfig rpc) {
164 
165   }
166 }