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