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.SimpleMutableByteRange;
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 SimpleMutableByteRange();
86 this.prevQual = new SimpleMutableByteRange();
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
142
143 @Override
144 public Cell transformCell(Cell v) {
145 return v;
146 }
147
148 @Override
149 public void reset() throws IOException {
150 this.prevFam.unset();
151 this.prevQual.unset();
152 this.familyMaxVersions = 0;
153 this.currentVersions = 0;
154 }
155
156
157
158
159 public byte [] toByteArray() {
160
161 throw new UnsupportedOperationException(
162 "Serialization not supported. Intended for server-side use only.");
163 }
164
165
166
167
168
169
170
171 public static AccessControlFilter parseFrom(final byte [] pbBytes)
172 throws DeserializationException {
173
174 throw new UnsupportedOperationException(
175 "Serialization not supported. Intended for server-side use only.");
176 }
177 }