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