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 static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertTrue;
22
23 import java.util.List;
24 import java.util.Arrays;
25
26 import org.apache.hadoop.conf.Configuration;
27 import org.apache.hadoop.hbase.HBaseTestingUtility;
28 import org.apache.hadoop.hbase.HColumnDescriptor;
29 import org.apache.hadoop.hbase.HConstants;
30 import org.apache.hadoop.hbase.HTableDescriptor;
31 import org.apache.hadoop.hbase.NamespaceDescriptor;
32 import org.apache.hadoop.hbase.testclassification.MediumTests;
33 import org.apache.hadoop.hbase.TableName;
34 import org.apache.hadoop.hbase.client.Admin;
35 import org.apache.hadoop.hbase.client.Connection;
36 import org.apache.hadoop.hbase.client.ConnectionFactory;
37 import org.apache.hadoop.hbase.client.Get;
38 import org.apache.hadoop.hbase.client.HTable;
39 import org.apache.hadoop.hbase.client.Result;
40 import org.apache.hadoop.hbase.client.Table;
41 import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
42 import org.apache.hadoop.hbase.coprocessor.ObserverContext;
43 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
44 import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService;
45 import org.apache.hadoop.hbase.security.User;
46 import org.apache.hadoop.hbase.security.access.Permission.Action;
47 import org.apache.hadoop.hbase.util.Bytes;
48 import org.junit.AfterClass;
49 import org.junit.BeforeClass;
50 import org.junit.Test;
51 import org.junit.experimental.categories.Category;
52
53 import com.google.common.collect.ListMultimap;
54 import com.google.protobuf.BlockingRpcChannel;
55
56 @Category(MediumTests.class)
57 public class TestNamespaceCommands extends SecureTestUtil {
58 private static HBaseTestingUtility UTIL = new HBaseTestingUtility();
59 private static String TEST_NAMESPACE = "ns1";
60 private static String TEST_NAMESPACE2 = "ns2";
61 private static Configuration conf;
62 private static MasterCoprocessorEnvironment CP_ENV;
63 private static AccessController ACCESS_CONTROLLER;
64
65
66 private static User SUPERUSER;
67
68
69 private static User USER_GLOBAL_ADMIN;
70
71 private static User USER_GLOBAL_CREATE;
72
73 private static User USER_GLOBAL_WRITE;
74
75 private static User USER_GLOBAL_READ;
76
77 private static User USER_GLOBAL_EXEC;
78
79
80 private static User USER_NS_ADMIN;
81
82 private static User USER_NS_CREATE;
83
84 private static User USER_NS_WRITE;
85
86 private static User USER_NS_READ;
87
88 private static User USER_NS_EXEC;
89
90
91 private static User USER_TABLE_WRITE;
92
93 private static User USER_TABLE_CREATE;
94
95 private static String TEST_TABLE = TEST_NAMESPACE + ":testtable";
96 private static byte[] TEST_FAMILY = Bytes.toBytes("f1");
97
98 @BeforeClass
99 public static void beforeClass() throws Exception {
100 conf = UTIL.getConfiguration();
101 enableSecurity(conf);
102
103 SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
104
105 USER_GLOBAL_ADMIN = User.createUserForTesting(conf, "global_admin", new String[0]);
106 USER_GLOBAL_CREATE = User.createUserForTesting(conf, "global_create", new String[0]);
107 USER_GLOBAL_WRITE = User.createUserForTesting(conf, "global_write", new String[0]);
108 USER_GLOBAL_READ = User.createUserForTesting(conf, "global_read", new String[0]);
109 USER_GLOBAL_EXEC = User.createUserForTesting(conf, "global_exec", new String[0]);
110
111 USER_NS_ADMIN = User.createUserForTesting(conf, "namespace_admin", new String[0]);
112 USER_NS_CREATE = User.createUserForTesting(conf, "namespace_create", new String[0]);
113 USER_NS_WRITE = User.createUserForTesting(conf, "namespace_write", new String[0]);
114 USER_NS_READ = User.createUserForTesting(conf, "namespace_read", new String[0]);
115 USER_NS_EXEC = User.createUserForTesting(conf, "namespace_exec", new String[0]);
116
117 USER_TABLE_CREATE = User.createUserForTesting(conf, "table_create", new String[0]);
118 USER_TABLE_WRITE = User.createUserForTesting(conf, "table_write", new String[0]);
119
120
121 UTIL.startMiniCluster();
122
123 UTIL.waitTableAvailable(AccessControlLists.ACL_TABLE_NAME.getName(), 30 * 1000);
124
125 ACCESS_CONTROLLER = (AccessController) UTIL.getMiniHBaseCluster().getMaster()
126 .getMasterCoprocessorHost()
127 .findCoprocessor(AccessController.class.getName());
128
129 UTIL.getHBaseAdmin().createNamespace(NamespaceDescriptor.create(TEST_NAMESPACE).build());
130 UTIL.getHBaseAdmin().createNamespace(NamespaceDescriptor.create(TEST_NAMESPACE2).build());
131
132
133 grantGlobal(UTIL, USER_GLOBAL_ADMIN.getShortName(), Permission.Action.ADMIN);
134 grantGlobal(UTIL, USER_GLOBAL_CREATE.getShortName(), Permission.Action.CREATE);
135 grantGlobal(UTIL, USER_GLOBAL_WRITE.getShortName(), Permission.Action.WRITE);
136 grantGlobal(UTIL, USER_GLOBAL_READ.getShortName(), Permission.Action.READ);
137 grantGlobal(UTIL, USER_GLOBAL_EXEC.getShortName(), Permission.Action.EXEC);
138
139
140 grantOnNamespace(UTIL, USER_NS_ADMIN.getShortName(), TEST_NAMESPACE, Permission.Action.ADMIN);
141 grantOnNamespace(UTIL, USER_NS_CREATE.getShortName(), TEST_NAMESPACE, Permission.Action.CREATE);
142 grantOnNamespace(UTIL, USER_NS_WRITE.getShortName(), TEST_NAMESPACE, Permission.Action.WRITE);
143 grantOnNamespace(UTIL, USER_NS_READ.getShortName(), TEST_NAMESPACE, Permission.Action.READ);
144 grantOnNamespace(UTIL, USER_NS_EXEC.getShortName(), TEST_NAMESPACE, Permission.Action.EXEC);
145
146 grantOnNamespace(UTIL, USER_NS_ADMIN.getShortName(), TEST_NAMESPACE2, Permission.Action.ADMIN);
147 }
148
149 @AfterClass
150 public static void afterClass() throws Exception {
151 UTIL.getHBaseAdmin().deleteNamespace(TEST_NAMESPACE);
152 UTIL.getHBaseAdmin().deleteNamespace(TEST_NAMESPACE2);
153 UTIL.shutdownMiniCluster();
154 }
155
156 @Test
157 public void testAclTableEntries() throws Exception {
158 String userTestNamespace = "userTestNsp";
159 Table acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
160 try {
161 ListMultimap<String, TablePermission> perms =
162 AccessControlLists.getNamespacePermissions(conf, TEST_NAMESPACE);
163
164 perms = AccessControlLists.getNamespacePermissions(conf, TEST_NAMESPACE);
165 assertEquals(5, perms.size());
166
167
168 grantOnNamespace(UTIL, userTestNamespace, TEST_NAMESPACE,
169 Permission.Action.WRITE);
170
171 Result result = acl.get(new Get(Bytes.toBytes(userTestNamespace)));
172 assertTrue(result != null);
173 perms = AccessControlLists.getNamespacePermissions(conf, TEST_NAMESPACE);
174 assertEquals(6, perms.size());
175 List<TablePermission> namespacePerms = perms.get(userTestNamespace);
176 assertTrue(perms.containsKey(userTestNamespace));
177 assertEquals(1, namespacePerms.size());
178 assertEquals(TEST_NAMESPACE,
179 namespacePerms.get(0).getNamespace());
180 assertEquals(null, namespacePerms.get(0).getFamily());
181 assertEquals(null, namespacePerms.get(0).getQualifier());
182 assertEquals(1, namespacePerms.get(0).getActions().length);
183 assertEquals(Permission.Action.WRITE, namespacePerms.get(0).getActions()[0]);
184
185
186 revokeFromNamespace(UTIL, userTestNamespace, TEST_NAMESPACE,
187 Permission.Action.WRITE);
188
189 perms = AccessControlLists.getNamespacePermissions(conf, TEST_NAMESPACE);
190 assertEquals(5, perms.size());
191 } finally {
192 acl.close();
193 }
194 }
195
196 @Test
197 public void testModifyNamespace() throws Exception {
198 AccessTestAction modifyNamespace = new AccessTestAction() {
199 public Object run() throws Exception {
200 ACCESS_CONTROLLER.preModifyNamespace(ObserverContext.createAndPrepare(CP_ENV, null),
201 NamespaceDescriptor.create(TEST_NAMESPACE).addConfiguration("abc", "156").build());
202 return null;
203 }
204 };
205
206
207 verifyAllowed(modifyNamespace,
208 SUPERUSER,
209 USER_GLOBAL_ADMIN);
210
211 verifyDeniedWithException(modifyNamespace,
212 USER_GLOBAL_CREATE,
213 USER_GLOBAL_WRITE,
214 USER_GLOBAL_READ,
215 USER_GLOBAL_EXEC,
216 USER_NS_ADMIN,
217 USER_NS_CREATE,
218 USER_NS_WRITE,
219 USER_NS_READ,
220 USER_NS_EXEC);
221 }
222
223 @Test
224 public void testCreateAndDeleteNamespace() throws Exception {
225 AccessTestAction createNamespace = new AccessTestAction() {
226 @Override
227 public Object run() throws Exception {
228 ACCESS_CONTROLLER.preCreateNamespace(ObserverContext.createAndPrepare(CP_ENV, null),
229 NamespaceDescriptor.create(TEST_NAMESPACE2).build());
230 return null;
231 }
232 };
233
234 AccessTestAction deleteNamespace = new AccessTestAction() {
235 @Override
236 public Object run() throws Exception {
237 ACCESS_CONTROLLER.preDeleteNamespace(ObserverContext.createAndPrepare(CP_ENV, null),
238 TEST_NAMESPACE2);
239 return null;
240 }
241 };
242
243
244 verifyAllowed(createNamespace,
245 SUPERUSER,
246 USER_GLOBAL_ADMIN);
247
248
249 verifyDeniedWithException(createNamespace,
250 USER_GLOBAL_CREATE,
251 USER_GLOBAL_WRITE,
252 USER_GLOBAL_READ,
253 USER_GLOBAL_EXEC,
254 USER_NS_ADMIN,
255 USER_NS_CREATE,
256 USER_NS_WRITE,
257 USER_NS_READ,
258 USER_NS_EXEC,
259 USER_TABLE_CREATE,
260 USER_TABLE_WRITE);
261
262
263 verifyAllowed(deleteNamespace,
264 SUPERUSER,
265 USER_GLOBAL_ADMIN);
266
267 verifyDeniedWithException(deleteNamespace,
268 USER_GLOBAL_CREATE,
269 USER_GLOBAL_WRITE,
270 USER_GLOBAL_READ,
271 USER_GLOBAL_EXEC,
272 USER_NS_ADMIN,
273 USER_NS_CREATE,
274 USER_NS_WRITE,
275 USER_NS_READ,
276 USER_NS_EXEC,
277 USER_TABLE_CREATE,
278 USER_TABLE_WRITE);
279 }
280
281 @Test
282 public void testGetNamespaceDescriptor() throws Exception {
283 AccessTestAction getNamespaceAction = new AccessTestAction() {
284 @Override
285 public Object run() throws Exception {
286 ACCESS_CONTROLLER.preGetNamespaceDescriptor(ObserverContext.createAndPrepare(CP_ENV, null),
287 TEST_NAMESPACE);
288 return null;
289 }
290 };
291
292 verifyAllowed(getNamespaceAction,
293 SUPERUSER,
294 USER_GLOBAL_ADMIN,
295 USER_NS_ADMIN);
296
297 verifyDeniedWithException(getNamespaceAction,
298 USER_GLOBAL_CREATE,
299 USER_GLOBAL_WRITE,
300 USER_GLOBAL_READ,
301 USER_GLOBAL_EXEC,
302 USER_NS_CREATE,
303 USER_NS_WRITE,
304 USER_NS_READ,
305 USER_NS_EXEC,
306 USER_TABLE_CREATE,
307 USER_TABLE_WRITE);
308 }
309
310 @Test
311 public void testListNamespaces() throws Exception {
312 AccessTestAction listAction = new AccessTestAction() {
313 @Override
314 public Object run() throws Exception {
315 Connection unmanagedConnection =
316 ConnectionFactory.createConnection(UTIL.getConfiguration());
317 Admin admin = unmanagedConnection.getAdmin();
318 try {
319 return Arrays.asList(admin.listNamespaceDescriptors());
320 } finally {
321 admin.close();
322 unmanagedConnection.close();
323 }
324 }
325 };
326
327
328
329
330 verifyAllowed(listAction,
331 SUPERUSER,
332 USER_GLOBAL_ADMIN,
333 USER_NS_ADMIN);
334
335
336 assertEquals(4, ((List)SUPERUSER.runAs(listAction)).size());
337 assertEquals(4, ((List)USER_GLOBAL_ADMIN.runAs(listAction)).size());
338
339 assertEquals(2, ((List)USER_NS_ADMIN.runAs(listAction)).size());
340
341 assertEquals(0, ((List)USER_GLOBAL_CREATE.runAs(listAction)).size());
342 assertEquals(0, ((List)USER_GLOBAL_WRITE.runAs(listAction)).size());
343 assertEquals(0, ((List)USER_GLOBAL_READ.runAs(listAction)).size());
344 assertEquals(0, ((List)USER_GLOBAL_EXEC.runAs(listAction)).size());
345 assertEquals(0, ((List)USER_NS_CREATE.runAs(listAction)).size());
346 assertEquals(0, ((List)USER_NS_WRITE.runAs(listAction)).size());
347 assertEquals(0, ((List)USER_NS_READ.runAs(listAction)).size());
348 assertEquals(0, ((List)USER_NS_EXEC.runAs(listAction)).size());
349 assertEquals(0, ((List)USER_TABLE_CREATE.runAs(listAction)).size());
350 assertEquals(0, ((List)USER_TABLE_WRITE.runAs(listAction)).size());
351 }
352
353 @Test
354 public void testGrantRevoke() throws Exception{
355 final String testUser = "testUser";
356
357
358
359 AccessTestAction grantAction = new AccessTestAction() {
360 @Override
361 public Object run() throws Exception {
362 Table acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
363 try {
364 BlockingRpcChannel service =
365 acl.coprocessorService(HConstants.EMPTY_START_ROW);
366 AccessControlService.BlockingInterface protocol =
367 AccessControlService.newBlockingStub(service);
368 ProtobufUtil.grant(protocol, testUser, TEST_NAMESPACE, Action.WRITE);
369 } finally {
370 acl.close();
371 }
372 return null;
373 }
374 };
375
376 AccessTestAction revokeAction = new AccessTestAction() {
377 public Object run() throws Exception {
378 Table acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
379 try {
380 BlockingRpcChannel service =
381 acl.coprocessorService(HConstants.EMPTY_START_ROW);
382 AccessControlService.BlockingInterface protocol =
383 AccessControlService.newBlockingStub(service);
384 ProtobufUtil.revoke(protocol, testUser, TEST_NAMESPACE, Action.WRITE);
385 } finally {
386 acl.close();
387 }
388 return null;
389 }
390 };
391
392 AccessTestAction getPermissionsAction = new AccessTestAction() {
393 @Override
394 public Object run() throws Exception {
395 Table acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
396 try {
397 BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW);
398 AccessControlService.BlockingInterface protocol =
399 AccessControlService.newBlockingStub(service);
400 ProtobufUtil.getUserPermissions(protocol, Bytes.toBytes(TEST_NAMESPACE));
401 } finally {
402 acl.close();
403 }
404 return null;
405 }
406 };
407
408 verifyAllowed(grantAction,
409 SUPERUSER,
410 USER_GLOBAL_ADMIN);
411
412 verifyDeniedWithException(grantAction,
413 USER_GLOBAL_CREATE,
414 USER_GLOBAL_WRITE,
415 USER_GLOBAL_READ,
416 USER_GLOBAL_EXEC,
417 USER_NS_ADMIN,
418 USER_NS_CREATE,
419 USER_NS_WRITE,
420 USER_NS_READ,
421 USER_NS_EXEC,
422 USER_TABLE_CREATE,
423 USER_TABLE_WRITE);
424
425 verifyAllowed(revokeAction,
426 SUPERUSER,
427 USER_GLOBAL_ADMIN);
428
429 verifyDeniedWithException(revokeAction,
430 USER_GLOBAL_CREATE,
431 USER_GLOBAL_WRITE,
432 USER_GLOBAL_READ,
433 USER_GLOBAL_EXEC,
434 USER_NS_ADMIN,
435 USER_NS_CREATE,
436 USER_NS_WRITE,
437 USER_NS_READ,
438 USER_NS_EXEC,
439 USER_TABLE_CREATE,
440 USER_TABLE_WRITE);
441
442 verifyAllowed(getPermissionsAction,
443 SUPERUSER,
444 USER_GLOBAL_ADMIN,
445 USER_NS_ADMIN);
446
447 verifyDeniedWithException(getPermissionsAction,
448 USER_GLOBAL_CREATE,
449 USER_GLOBAL_WRITE,
450 USER_GLOBAL_READ,
451 USER_GLOBAL_EXEC,
452 USER_NS_CREATE,
453 USER_NS_WRITE,
454 USER_NS_READ,
455 USER_NS_EXEC,
456 USER_TABLE_CREATE,
457 USER_TABLE_WRITE);
458 }
459
460 @Test
461 public void testCreateTableWithNamespace() throws Exception {
462 AccessTestAction createTable = new AccessTestAction() {
463 @Override
464 public Object run() throws Exception {
465 HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(TEST_TABLE));
466 htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
467 ACCESS_CONTROLLER.preCreateTable(ObserverContext.createAndPrepare(CP_ENV, null), htd, null);
468 return null;
469 }
470 };
471
472
473 verifyAllowed(createTable,
474 SUPERUSER,
475 USER_GLOBAL_CREATE,
476 USER_NS_CREATE);
477
478 verifyDeniedWithException(createTable,
479 USER_GLOBAL_ADMIN,
480 USER_GLOBAL_WRITE,
481 USER_GLOBAL_READ,
482 USER_GLOBAL_EXEC,
483 USER_NS_ADMIN,
484 USER_NS_WRITE,
485 USER_NS_READ,
486 USER_NS_EXEC,
487 USER_TABLE_CREATE,
488 USER_TABLE_WRITE);
489 }
490 }