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