1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.security.visibility;
19
20 import java.io.IOException;
21 import java.util.BitSet;
22 import java.util.Iterator;
23 import java.util.Map;
24
25 import org.apache.hadoop.classification.InterfaceAudience;
26 import org.apache.hadoop.hbase.Cell;
27 import org.apache.hadoop.hbase.CellUtil;
28 import org.apache.hadoop.hbase.Tag;
29 import org.apache.hadoop.hbase.filter.FilterBase;
30 import org.apache.hadoop.hbase.io.util.StreamUtils;
31 import org.apache.hadoop.hbase.util.ByteRange;
32 import org.apache.hadoop.hbase.util.Bytes;
33 import org.apache.hadoop.hbase.util.Pair;
34 import org.apache.hadoop.hbase.util.SimpleByteRange;
35
36
37
38
39
40 @InterfaceAudience.Private
41 class VisibilityLabelFilter extends FilterBase {
42
43 private final BitSet authLabels;
44 private final Map<ByteRange, Integer> cfVsMaxVersions;
45 private final ByteRange curFamily;
46 private final ByteRange curQualifier;
47 private int curFamilyMaxVersions;
48 private int curQualMetVersions;
49
50 public VisibilityLabelFilter(BitSet authLabels, Map<ByteRange, Integer> cfVsMaxVersions) {
51 this.authLabels = authLabels;
52 this.cfVsMaxVersions = cfVsMaxVersions;
53 this.curFamily = new SimpleByteRange();
54 this.curQualifier = new SimpleByteRange();
55 }
56
57 @Override
58 public ReturnCode filterKeyValue(Cell cell) throws IOException {
59 if (curFamily.getBytes() == null
60 || (Bytes.compareTo(curFamily.getBytes(), curFamily.getOffset(), curFamily.getLength(),
61 cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength()) != 0)) {
62 curFamily.set(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength());
63
64
65
66 curFamilyMaxVersions = cfVsMaxVersions.get(curFamily);
67
68 curQualifier.unset();
69 }
70 if (curQualifier.getBytes() == null
71 || (Bytes.compareTo(curQualifier.getBytes(), curQualifier.getOffset(),
72 curQualifier.getLength(), cell.getQualifierArray(), cell.getQualifierOffset(),
73 cell.getQualifierLength()) != 0)) {
74 curQualifier.set(cell.getQualifierArray(), cell.getQualifierOffset(),
75 cell.getQualifierLength());
76 curQualMetVersions = 0;
77 }
78 curQualMetVersions++;
79 if (curQualMetVersions > curFamilyMaxVersions) {
80 return ReturnCode.SKIP;
81 }
82
83 Iterator<Tag> tagsItr = CellUtil.tagsIterator(cell.getTagsArray(), cell.getTagsOffset(),
84 cell.getTagsLengthUnsigned());
85 boolean visibilityTagPresent = false;
86 while (tagsItr.hasNext()) {
87 boolean includeKV = true;
88 Tag tag = tagsItr.next();
89 if (tag.getType() == VisibilityUtils.VISIBILITY_TAG_TYPE) {
90 visibilityTagPresent = true;
91 int offset = tag.getTagOffset();
92 int endOffset = offset + tag.getTagLength();
93 while (offset < endOffset) {
94 Pair<Integer, Integer> result = StreamUtils.readRawVarint32(tag.getBuffer(), offset);
95 int currLabelOrdinal = result.getFirst();
96 if (currLabelOrdinal < 0) {
97
98
99 int temp = -currLabelOrdinal;
100 if (this.authLabels.get(temp)) {
101 includeKV = false;
102 break;
103 }
104 } else {
105 if (!this.authLabels.get(currLabelOrdinal)) {
106 includeKV = false;
107 break;
108 }
109 }
110 offset += result.getSecond();
111 }
112 if (includeKV) {
113
114
115 return ReturnCode.INCLUDE;
116 }
117 }
118 }
119 return visibilityTagPresent ? ReturnCode.SKIP : ReturnCode.INCLUDE;
120 }
121
122 @Override
123 public void reset() throws IOException {
124 this.curFamily.unset();
125 this.curQualifier.unset();
126 this.curFamilyMaxVersions = 0;
127 this.curQualMetVersions = 0;
128 }
129 }