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