1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.security.access;
20
21 import java.io.IOException;
22 import java.util.Map;
23
24 import org.apache.hadoop.hbase.classification.InterfaceAudience;
25 import org.apache.hadoop.hbase.Cell;
26 import org.apache.hadoop.hbase.CellUtil;
27 import org.apache.hadoop.hbase.TableName;
28 import org.apache.hadoop.hbase.exceptions.DeserializationException;
29 import org.apache.hadoop.hbase.filter.FilterBase;
30 import org.apache.hadoop.hbase.security.User;
31 import org.apache.hadoop.hbase.util.ByteRange;
32 import org.apache.hadoop.hbase.util.Bytes;
33 import org.apache.hadoop.hbase.util.SimpleByteRange;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 @InterfaceAudience.Private
51 class AccessControlFilter extends FilterBase {
52
53 public static enum Strategy {
54
55 CHECK_TABLE_AND_CF_ONLY,
56
57 CHECK_CELL_DEFAULT,
58 };
59
60 private TableAuthManager authManager;
61 private TableName table;
62 private User user;
63 private boolean isSystemTable;
64 private Strategy strategy;
65 private Map<ByteRange, Integer> cfVsMaxVersions;
66 private int familyMaxVersions;
67 private int currentVersions;
68 private ByteRange prevFam;
69 private ByteRange prevQual;
70
71
72
73
74 AccessControlFilter() {
75 }
76
77 AccessControlFilter(TableAuthManager mgr, User ugi, TableName tableName,
78 Strategy strategy, Map<ByteRange, Integer> cfVsMaxVersions) {
79 authManager = mgr;
80 table = tableName;
81 user = ugi;
82 isSystemTable = tableName.isSystemTable();
83 this.strategy = strategy;
84 this.cfVsMaxVersions = cfVsMaxVersions;
85 this.prevFam = new SimpleByteRange();
86 this.prevQual = new SimpleByteRange();
87 }
88
89 @Override
90 public ReturnCode filterKeyValue(Cell cell) {
91 if (isSystemTable) {
92 return ReturnCode.INCLUDE;
93 }
94 if (prevFam.getBytes() == null
95 || (Bytes.compareTo(prevFam.getBytes(), prevFam.getOffset(), prevFam.getLength(),
96 cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength()) != 0)) {
97 prevFam.set(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength());
98
99 familyMaxVersions = cfVsMaxVersions.get(prevFam);
100
101 prevQual.unset();
102 }
103 if (prevQual.getBytes() == null
104 || (Bytes.compareTo(prevQual.getBytes(), prevQual.getOffset(),
105 prevQual.getLength(), cell.getQualifierArray(), cell.getQualifierOffset(),
106 cell.getQualifierLength()) != 0)) {
107 prevQual.set(cell.getQualifierArray(), cell.getQualifierOffset(),
108 cell.getQualifierLength());
109 currentVersions = 0;
110 }
111 currentVersions++;
112 if (currentVersions > familyMaxVersions) {
113 return ReturnCode.SKIP;
114 }
115
116 byte[] family = CellUtil.cloneFamily(cell);
117 byte[] qualifier = CellUtil.cloneQualifier(cell);
118 switch (strategy) {
119
120 case CHECK_TABLE_AND_CF_ONLY: {
121 if (authManager.authorize(user, table, family, qualifier, Permission.Action.READ)) {
122 return ReturnCode.INCLUDE;
123 }
124 }
125 break;
126
127 case CHECK_CELL_DEFAULT: {
128 if (authManager.authorize(user, table, family, qualifier, Permission.Action.READ) ||
129 authManager.authorize(user, table, cell, Permission.Action.READ)) {
130 return ReturnCode.INCLUDE;
131 }
132 }
133 break;
134 default:
135 throw new RuntimeException("Unhandled strategy " + strategy);
136 }
137
138 return ReturnCode.SKIP;
139 }
140
141 @Override
142 public void reset() throws IOException {
143 this.prevFam.unset();
144 this.prevQual.unset();
145 this.familyMaxVersions = 0;
146 this.currentVersions = 0;
147 }
148
149
150
151
152 public byte [] toByteArray() {
153
154 throw new UnsupportedOperationException(
155 "Serialization not supported. Intended for server-side use only.");
156 }
157
158
159
160
161
162
163
164 public static AccessControlFilter parseFrom(final byte [] pbBytes)
165 throws DeserializationException {
166
167 throw new UnsupportedOperationException(
168 "Serialization not supported. Intended for server-side use only.");
169 }
170 }