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.net.InetAddress;
23 import java.util.Collection;
24 import java.util.Map;
25
26 import org.apache.hadoop.conf.Configuration;
27 import org.apache.hadoop.hbase.TableName;
28 import org.apache.hadoop.hbase.classification.InterfaceAudience;
29 import org.apache.hadoop.hbase.ipc.RpcServer;
30 import org.apache.hadoop.hbase.security.AccessDeniedException;
31 import org.apache.hadoop.hbase.security.User;
32 import org.apache.hadoop.hbase.security.access.Permission.Action;
33 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 @InterfaceAudience.Private
38 public final class AccessChecker {
39 private static final Logger AUDITLOG =
40 LoggerFactory.getLogger("SecurityLogger." + AccessChecker.class.getName());
41 private TableAuthManager authManager;
42
43
44
45
46 private boolean authorizationEnabled;
47
48 public static boolean isAuthorizationSupported(Configuration conf) {
49 return conf.getBoolean(User.HBASE_SECURITY_AUTHORIZATION_CONF_KEY, false);
50 }
51
52
53
54
55
56
57
58 public AccessChecker(final Configuration conf, final ZooKeeperWatcher zkw)
59 throws RuntimeException {
60
61
62 if (zkw != null) {
63 try {
64 this.authManager = TableAuthManager.getOrCreate(zkw, conf);
65 } catch (IOException ioe) {
66 throw new RuntimeException("Error obtaining AccessChecker", ioe);
67 }
68 } else {
69 throw new NullPointerException("Error obtaining AccessChecker, zk found null.");
70 }
71 authorizationEnabled = isAuthorizationSupported(conf);
72 }
73
74 public TableAuthManager getAuthManager() {
75 return authManager;
76 }
77
78 public void logResult(AuthResult result) {
79 if (AUDITLOG.isTraceEnabled()) {
80 InetAddress remoteAddr = RpcServer.getRemoteAddress();
81 AUDITLOG.trace("Access " + (result.isAllowed() ? "allowed" : "denied") +
82 " for user " + (result.getUser() != null ? result.getUser().getShortName() : "UNKNOWN") +
83 "; reason: " + result.getReason() +
84 "; remote address: " + (remoteAddr != null ? remoteAddr : "") +
85 "; request: " + result.getRequest() +
86 "; context: " + result.toContextString());
87 }
88 }
89
90
91
92
93
94
95
96
97
98
99 public void requirePermission(User user, String request, TableName tableName, byte[] family,
100 byte[] qualifier, Action... permissions) throws IOException {
101 AuthResult result = null;
102
103 for (Action permission : permissions) {
104 if (authManager.authorize(user, tableName, family, qualifier, permission)) {
105 result = AuthResult.allow(request, "Table permission granted", user,
106 permission, tableName, family, qualifier);
107 break;
108 } else {
109
110 result = AuthResult.deny(request, "Insufficient permissions", user,
111 permission, tableName, family, qualifier);
112 }
113 }
114 logResult(result);
115 if (authorizationEnabled && !result.isAllowed()) {
116 throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
117 }
118 }
119
120
121
122
123
124
125
126
127
128
129 public void requireTablePermission(User user, String request, TableName tableName, byte[] family,
130 byte[] qualifier, Action... permissions) throws IOException {
131 AuthResult result = null;
132
133 for (Action permission : permissions) {
134 if (authManager.authorize(user, tableName, null, null, permission)) {
135 result = AuthResult.allow(request, "Table permission granted", user,
136 permission, tableName, null, null);
137 result.getParams().setFamily(family).setQualifier(qualifier);
138 break;
139 } else {
140
141 result = AuthResult.deny(request, "Insufficient permissions", user,
142 permission, tableName, family, qualifier);
143 result.getParams().setFamily(family).setQualifier(qualifier);
144 }
145 }
146 logResult(result);
147 if (authorizationEnabled && !result.isAllowed()) {
148 throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
149 }
150 }
151
152
153
154
155
156
157
158
159
160 public void requireAccess(User user, String request, TableName tableName,
161 Action... permissions) throws IOException {
162 AuthResult result = null;
163
164 for (Action permission : permissions) {
165 if (authManager.hasAccess(user, tableName, permission)) {
166 result = AuthResult.allow(request, "Table permission granted", user,
167 permission, tableName, null, null);
168 break;
169 } else {
170
171 result = AuthResult.deny(request, "Insufficient permissions", user,
172 permission, tableName, null, null);
173 }
174 }
175 logResult(result);
176 if (authorizationEnabled && !result.isAllowed()) {
177 throw new AccessDeniedException("Insufficient permissions " + result.toContextString());
178 }
179 }
180
181
182
183
184
185
186
187 public void requirePermission(User user, String request, Action perm) throws IOException {
188 requireGlobalPermission(user, request, perm, null, null);
189 }
190
191
192
193
194
195
196
197
198
199 public void requireGlobalPermission(User user, String request, Action perm, TableName tableName,
200 Map<byte[], ? extends Collection<byte[]>> familyMap) throws IOException {
201 AuthResult result = null;
202 if (authManager.authorize(user, perm)) {
203 result = AuthResult.allow(request, "Global check allowed", user, perm, tableName, familyMap);
204 result.getParams().setTableName(tableName).setFamilies(familyMap);
205 logResult(result);
206 } else {
207 result = AuthResult.deny(request, "Global check failed", user, perm, tableName, familyMap);
208 result.getParams().setTableName(tableName).setFamilies(familyMap);
209 logResult(result);
210 if (authorizationEnabled) {
211 throw new AccessDeniedException("Insufficient permissions for user '" +
212 (user != null ? user.getShortName() : "null") +"' (global, action=" +
213 perm.toString() + ")");
214 }
215 }
216 }
217
218
219
220
221
222
223
224
225 public void requireGlobalPermission(User user, String request, Action perm,
226 String namespace) throws IOException {
227 AuthResult authResult = null;
228 if (authManager.authorize(user, perm)) {
229 authResult = AuthResult.allow(request, "Global check allowed", user, perm, null);
230 authResult.getParams().setNamespace(namespace);
231 logResult(authResult);
232 } else {
233 authResult = AuthResult.deny(request, "Global check failed", user, perm, null);
234 authResult.getParams().setNamespace(namespace);
235 logResult(authResult);
236 if (authorizationEnabled) {
237 throw new AccessDeniedException("Insufficient permissions for user '" +
238 (user != null ? user.getShortName() : "null") +"' (global, action=" +
239 perm.toString() + ")");
240 }
241 }
242 }
243
244
245
246
247
248
249 public void requireNamespacePermission(User user, String request, String namespace,
250 Action... permissions) throws IOException {
251 AuthResult result = null;
252
253 for (Action permission : permissions) {
254 if (authManager.authorize(user, namespace, permission)) {
255 result = AuthResult.allow(request, "Namespace permission granted",
256 user, permission, namespace);
257 break;
258 } else {
259
260 result = AuthResult.deny(request, "Insufficient permissions", user,
261 permission, namespace);
262 }
263 }
264 logResult(result);
265 if (authorizationEnabled && !result.isAllowed()) {
266 throw new AccessDeniedException("Insufficient permissions "
267 + result.toContextString());
268 }
269 }
270
271
272
273
274
275
276 public void requireNamespacePermission(User user, String request, String namespace, TableName tableName,
277 Map<byte[], ? extends Collection<byte[]>> familyMap, Action... permissions)
278 throws IOException {
279 AuthResult result = null;
280
281 for (Action permission : permissions) {
282 if (authManager.authorize(user, namespace, permission)) {
283 result = AuthResult.allow(request, "Namespace permission granted",
284 user, permission, namespace);
285 result.getParams().setTableName(tableName).setFamilies(familyMap);
286 break;
287 } else {
288
289 result = AuthResult.deny(request, "Insufficient permissions", user,
290 permission, namespace);
291 result.getParams().setTableName(tableName).setFamilies(familyMap);
292 }
293 }
294 logResult(result);
295 if (authorizationEnabled && !result.isAllowed()) {
296 throw new AccessDeniedException("Insufficient permissions "
297 + result.toContextString());
298 }
299 }
300 }