1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.security.access;
19
20 import java.io.IOException;
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.regex.Pattern;
25
26 import org.apache.hadoop.conf.Configuration;
27 import org.apache.hadoop.hbase.HConstants;
28 import org.apache.hadoop.hbase.HTableDescriptor;
29 import org.apache.hadoop.hbase.MasterNotRunningException;
30 import org.apache.hadoop.hbase.NamespaceDescriptor;
31 import org.apache.hadoop.hbase.TableName;
32 import org.apache.hadoop.hbase.ZooKeeperConnectionException;
33 import org.apache.hadoop.hbase.classification.InterfaceAudience;
34 import org.apache.hadoop.hbase.classification.InterfaceStability;
35 import org.apache.hadoop.hbase.client.Admin;
36 import org.apache.hadoop.hbase.client.Connection;
37 import org.apache.hadoop.hbase.client.ConnectionFactory;
38 import org.apache.hadoop.hbase.client.HTable;
39 import org.apache.hadoop.hbase.client.Table;
40 import org.apache.hadoop.hbase.client.security.SecurityCapability;
41 import org.apache.hadoop.hbase.client.coprocessor.Batch;
42 import org.apache.hadoop.hbase.ipc.BlockingRpcCallback;
43 import org.apache.hadoop.hbase.ipc.CoprocessorRpcChannel;
44 import org.apache.hadoop.hbase.ipc.ServerRpcController;
45 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
46 import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
47 import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService;
48 import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService.BlockingInterface;
49 import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.GrantRequest;
50 import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.GrantResponse;
51 import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.RevokeRequest;
52 import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.RevokeResponse;
53 import org.apache.hadoop.hbase.util.ByteStringer;
54 import org.apache.hadoop.hbase.util.Bytes;
55
56 import com.google.protobuf.ByteString;
57
58
59
60
61 @InterfaceAudience.Public
62 @InterfaceStability.Evolving
63 public class AccessControlClient {
64 public static final TableName ACL_TABLE_NAME =
65 TableName.valueOf(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR, "acl");
66
67
68
69
70
71
72
73 public static boolean isAuthorizationEnabled(Connection connection) throws IOException {
74 return connection.getAdmin().getSecurityCapabilities()
75 .contains(SecurityCapability.AUTHORIZATION);
76 }
77
78
79
80
81
82
83
84 public static boolean isCellAuthorizationEnabled(Connection connection) throws IOException {
85 return connection.getAdmin().getSecurityCapabilities()
86 .contains(SecurityCapability.CELL_AUTHORIZATION);
87 }
88
89 private static BlockingInterface getAccessControlServiceStub(Table ht)
90 throws IOException {
91 CoprocessorRpcChannel service = ht.coprocessorService(HConstants.EMPTY_START_ROW);
92 BlockingInterface protocol =
93 AccessControlProtos.AccessControlService.newBlockingStub(service);
94 return protocol;
95 }
96
97
98
99
100
101
102
103
104
105
106
107 public static void grant(final Connection connection, final TableName tableName,
108 final String userName, final byte[] family, final byte[] qual,
109 final Permission.Action... actions) throws Throwable {
110 try (Table table = connection.getTable(ACL_TABLE_NAME)) {
111 ProtobufUtil.grant(getAccessControlServiceStub(table), userName, tableName, family, qual,
112 actions);
113 }
114 }
115
116
117
118
119
120
121
122
123
124 public static void grant(final Connection connection, final String namespace,
125 final String userName, final Permission.Action... actions) throws Throwable {
126 try (Table table = connection.getTable(ACL_TABLE_NAME)) {
127 ProtobufUtil.grant(getAccessControlServiceStub(table), userName, namespace, actions);
128 }
129 }
130
131
132
133
134
135 public static void grant(final Connection connection, final String userName,
136 final Permission.Action... actions) throws Throwable {
137 try (Table table = connection.getTable(ACL_TABLE_NAME)) {
138 ProtobufUtil.grant(getAccessControlServiceStub(table), userName, actions);
139 }
140 }
141
142 public static boolean isAccessControllerRunning(final Connection connection)
143 throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
144 try (Admin admin = connection.getAdmin()) {
145 return admin.isTableAvailable(ACL_TABLE_NAME);
146 }
147 }
148
149
150
151
152
153
154
155
156
157
158
159 public static void revoke(final Connection connection, final TableName tableName,
160 final String username, final byte[] family, final byte[] qualifier,
161 final Permission.Action... actions) throws Throwable {
162 try (Table table = connection.getTable(ACL_TABLE_NAME)) {
163 ProtobufUtil.revoke(getAccessControlServiceStub(table), username, tableName, family,
164 qualifier, actions);
165 }
166 }
167
168
169
170
171
172
173
174
175
176 public static void revoke(final Connection connection, final String namespace,
177 final String userName, final Permission.Action... actions) throws Throwable {
178 try (Table table = connection.getTable(ACL_TABLE_NAME)) {
179 ProtobufUtil.revoke(getAccessControlServiceStub(table), userName, namespace, actions);
180 }
181 }
182
183
184
185
186
187 public static void revoke(final Connection connection, final String userName,
188 final Permission.Action... actions) throws Throwable {
189 try (Table table = connection.getTable(ACL_TABLE_NAME)) {
190 ProtobufUtil.revoke(getAccessControlServiceStub(table), userName, actions);
191 }
192
193 }
194
195
196
197
198
199
200
201
202 public static List<UserPermission> getUserPermissions(Connection connection, String tableRegex)
203 throws Throwable {
204 List<UserPermission> permList = new ArrayList<UserPermission>();
205 try (Table table = connection.getTable(ACL_TABLE_NAME)) {
206 try (Admin admin = connection.getAdmin()) {
207 CoprocessorRpcChannel service = table.coprocessorService(HConstants.EMPTY_START_ROW);
208 BlockingInterface protocol =
209 AccessControlProtos.AccessControlService.newBlockingStub(service);
210 HTableDescriptor[] htds = null;
211 if (tableRegex == null || tableRegex.isEmpty()) {
212 permList = ProtobufUtil.getUserPermissions(protocol);
213 } else if (tableRegex.charAt(0) == '@') {
214 String namespace = tableRegex.substring(1);
215 permList = ProtobufUtil.getUserPermissions(protocol, Bytes.toBytes(namespace));
216 } else {
217 htds = admin.listTables(Pattern.compile(tableRegex), true);
218 for (HTableDescriptor hd : htds) {
219 permList.addAll(ProtobufUtil.getUserPermissions(protocol, hd.getTableName()));
220 }
221 }
222 }
223 }
224 return permList;
225 }
226
227
228
229
230
231
232
233
234
235
236
237
238
239 @Deprecated
240 public static void grant(Configuration conf, final TableName tableName,
241 final String userName, final byte[] family, final byte[] qual,
242 final Permission.Action... actions) throws Throwable {
243 try (Connection connection = ConnectionFactory.createConnection(conf)) {
244 grant(connection, tableName, userName, family, qual, actions);
245 }
246 }
247
248
249
250
251
252
253
254
255
256
257
258 @Deprecated
259 public static void grant(Configuration conf, final String namespace,
260 final String userName, final Permission.Action... actions) throws Throwable {
261 try (Connection connection = ConnectionFactory.createConnection(conf)) {
262 grant(connection, namespace, userName, actions);
263 }
264 }
265
266
267
268
269
270 @Deprecated
271 public static void grant(Configuration conf, final String userName,
272 final Permission.Action... actions) throws Throwable {
273 try (Connection connection = ConnectionFactory.createConnection(conf)) {
274 grant(connection, userName, actions);
275 }
276 }
277
278
279
280
281 @Deprecated
282 public static boolean isAccessControllerRunning(Configuration conf)
283 throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
284 try (Connection connection = ConnectionFactory.createConnection(conf)) {
285 return isAccessControllerRunning(connection);
286 }
287 }
288
289
290
291
292
293
294
295
296
297
298
299
300
301 @Deprecated
302 public static GrantResponse grant(Configuration conf, final TableName tableName,
303 final String userName, final byte[] family, final byte[] qual,
304 final AccessControlProtos.Permission.Action... actions) throws Throwable {
305 HTable ht = null;
306 try {
307 TableName aclTableName =
308 TableName.valueOf(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR, "acl");
309 ht = new HTable(conf, aclTableName.getName());
310 Batch.Call<AccessControlService, GrantResponse> callable =
311 new Batch.Call<AccessControlService, GrantResponse>() {
312 ServerRpcController controller = new ServerRpcController();
313 BlockingRpcCallback<GrantResponse> rpcCallback =
314 new BlockingRpcCallback<GrantResponse>();
315 @Override
316 public GrantResponse call(AccessControlService service) throws IOException {
317 GrantRequest.Builder builder = GrantRequest.newBuilder();
318 AccessControlProtos.Permission.Builder ret =
319 AccessControlProtos.Permission.newBuilder();
320 AccessControlProtos.TablePermission.Builder permissionBuilder =
321 AccessControlProtos.TablePermission
322 .newBuilder();
323 for (AccessControlProtos.Permission.Action a : actions) {
324 permissionBuilder.addAction(a);
325 }
326 permissionBuilder.setTableName(ProtobufUtil.toProtoTableName(tableName));
327 if (family != null) {
328 permissionBuilder.setFamily(ByteStringer.wrap(family));
329 }
330 if (qual != null) {
331 permissionBuilder.setQualifier(ByteStringer.wrap(qual));
332 }
333 ret.setType(AccessControlProtos.Permission.Type.Table).setTablePermission(
334 permissionBuilder);
335 builder.setUserPermission(AccessControlProtos.UserPermission.newBuilder()
336 .setUser(ByteString.copyFromUtf8(userName)).setPermission(ret));
337 service.grant(controller, builder.build(), rpcCallback);
338 return rpcCallback.get();
339 }
340 };
341 Map<byte[], GrantResponse> result = ht.coprocessorService(AccessControlService.class,
342 HConstants.EMPTY_BYTE_ARRAY, HConstants.EMPTY_BYTE_ARRAY, callable);
343 return result.values().iterator().next();
344
345
346
347 } finally {
348 if (ht != null) {
349 ht.close();
350 }
351 }
352 }
353
354
355
356
357
358
359
360
361
362
363
364
365
366 @Deprecated
367 public static void revoke(Configuration conf, final TableName tableName,
368 final String username, final byte[] family, final byte[] qualifier,
369 final Permission.Action... actions) throws Throwable {
370 try (Connection connection = ConnectionFactory.createConnection(conf)) {
371 revoke(connection, tableName, username, family, qualifier, actions);
372 }
373 }
374
375
376
377
378
379
380
381
382
383
384 @Deprecated
385 public static void revoke(Configuration conf, final String namespace,
386 final String userName, final Permission.Action... actions) throws Throwable {
387 try (Connection connection = ConnectionFactory.createConnection(conf)) {
388 revoke(connection, namespace, userName, actions);
389 }
390 }
391
392
393
394
395
396 @Deprecated
397 public static void revoke(Configuration conf, final String userName,
398 final Permission.Action... actions) throws Throwable {
399 try (Connection connection = ConnectionFactory.createConnection(conf)) {
400 revoke(connection, userName, actions);
401 }
402 }
403
404
405
406
407
408
409
410
411
412 @Deprecated
413 public static List<UserPermission> getUserPermissions(Configuration conf, String tableRegex)
414 throws Throwable {
415 try (Connection connection = ConnectionFactory.createConnection(conf)) {
416 return getUserPermissions(connection, tableRegex);
417 }
418 }
419
420
421
422
423
424
425
426
427
428
429
430
431
432 @Deprecated
433 public static RevokeResponse revoke(Configuration conf, final String username,
434 final TableName tableName, final byte[] family, final byte[] qualifier,
435 final AccessControlProtos.Permission.Action... actions) throws Throwable {
436 HTable ht = null;
437 try {
438 TableName aclTableName = TableName.valueOf(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR,
439 "acl");
440 ht = new HTable(conf, aclTableName.getName());
441 Batch.Call<AccessControlService, AccessControlProtos.RevokeResponse> callable =
442 new Batch.Call<AccessControlService, AccessControlProtos.RevokeResponse>() {
443 ServerRpcController controller = new ServerRpcController();
444 BlockingRpcCallback<AccessControlProtos.RevokeResponse> rpcCallback =
445 new BlockingRpcCallback<AccessControlProtos.RevokeResponse>();
446 @Override
447 public RevokeResponse call(AccessControlService service) throws IOException {
448 AccessControlProtos.Permission.Builder ret =
449 AccessControlProtos.Permission.newBuilder();
450 AccessControlProtos.TablePermission.Builder permissionBuilder =
451 AccessControlProtos.TablePermission.newBuilder();
452 for (AccessControlProtos.Permission.Action a : actions) {
453 permissionBuilder.addAction(a);
454 }
455 if (tableName != null) {
456 permissionBuilder.setTableName(ProtobufUtil.toProtoTableName(tableName));
457 }
458 if (family != null) {
459 permissionBuilder.setFamily(ByteStringer.wrap(family));
460 }
461 if (qualifier != null) {
462 permissionBuilder.setQualifier(ByteStringer.wrap(qualifier));
463 }
464 ret.setType(AccessControlProtos.Permission.Type.Table).setTablePermission(
465 permissionBuilder);
466 RevokeRequest builder = AccessControlProtos.RevokeRequest
467 .newBuilder()
468 .setUserPermission(
469 AccessControlProtos.UserPermission.newBuilder()
470 .setUser(ByteString.copyFromUtf8(username)).setPermission(ret)).build();
471 service.revoke(controller, builder, rpcCallback);
472 return rpcCallback.get();
473 }
474 };
475 Map<byte[], RevokeResponse> result = ht.coprocessorService(AccessControlService.class,
476 HConstants.EMPTY_BYTE_ARRAY, HConstants.EMPTY_BYTE_ARRAY, callable);
477 return result.values().iterator().next();
478 } finally {
479 if (ht != null) {
480 ht.close();
481 }
482 }
483 }
484 }