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