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.assertFalse;
22 import static org.junit.Assert.assertNotNull;
23 import static org.junit.Assert.assertTrue;
24
25 import java.util.Arrays;
26 import java.util.List;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.hadoop.conf.Configuration;
31 import org.apache.hadoop.hbase.HBaseTestingUtility;
32 import org.apache.hadoop.hbase.HColumnDescriptor;
33 import org.apache.hadoop.hbase.HTableDescriptor;
34 import org.apache.hadoop.hbase.NamespaceDescriptor;
35 import org.apache.hadoop.hbase.TableName;
36 import org.apache.hadoop.hbase.client.Admin;
37 import org.apache.hadoop.hbase.client.Connection;
38 import org.apache.hadoop.hbase.client.ConnectionFactory;
39 import org.apache.hadoop.hbase.client.Put;
40 import org.apache.hadoop.hbase.client.Result;
41 import org.apache.hadoop.hbase.client.ResultScanner;
42 import org.apache.hadoop.hbase.client.Scan;
43 import org.apache.hadoop.hbase.client.Table;
44 import org.apache.hadoop.hbase.security.User;
45 import org.apache.hadoop.hbase.security.access.Permission.Action;
46 import org.apache.hadoop.hbase.testclassification.LargeTests;
47 import org.apache.hadoop.hbase.util.Bytes;
48 import org.apache.hadoop.hbase.util.TestTableName;
49 import org.apache.hadoop.hbase.zookeeper.ZKUtil;
50 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
51 import org.junit.After;
52 import org.junit.AfterClass;
53 import org.junit.Before;
54 import org.junit.BeforeClass;
55 import org.junit.Rule;
56 import org.junit.Test;
57 import org.junit.experimental.categories.Category;
58
59 @Category(LargeTests.class)
60 public class TestAccessController2 extends SecureTestUtil {
61 private static final Log LOG = LogFactory.getLog(TestAccessController2.class);
62
63 private static final byte[] TEST_ROW = Bytes.toBytes("test");
64 private static final byte[] TEST_FAMILY = Bytes.toBytes("f");
65 private static final byte[] TEST_QUALIFIER = Bytes.toBytes("q");
66 private static final byte[] TEST_VALUE = Bytes.toBytes("value");
67
68 private static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
69 private static Configuration conf;
70
71
72
73
74 private static Connection systemUserConnection;
75
76 private final static byte[] Q1 = Bytes.toBytes("q1");
77 private final static byte[] value1 = Bytes.toBytes("value1");
78
79 private static byte[] TEST_FAMILY_2 = Bytes.toBytes("f2");
80 private static byte[] TEST_ROW_2 = Bytes.toBytes("r2");
81 private final static byte[] Q2 = Bytes.toBytes("q2");
82 private final static byte[] value2 = Bytes.toBytes("value2");
83
84 private static byte[] TEST_ROW_3 = Bytes.toBytes("r3");
85
86 private static final String TESTGROUP_1 = "testgroup_1";
87 private static final String TESTGROUP_2 = "testgroup_2";
88
89 private static User TESTGROUP1_USER1;
90 private static User TESTGROUP2_USER1;
91
92 @Rule
93 public TestTableName TEST_TABLE = new TestTableName();
94 private String namespace = "testNamespace";
95 private String tname = namespace + ":testtable1";
96 private TableName tableName = TableName.valueOf(tname);
97
98 @BeforeClass
99 public static void setupBeforeClass() throws Exception {
100 conf = TEST_UTIL.getConfiguration();
101
102 enableSecurity(conf);
103
104 verifyConfiguration(conf);
105 TEST_UTIL.startMiniCluster();
106
107 TEST_UTIL.waitUntilAllRegionsAssigned(AccessControlLists.ACL_TABLE_NAME);
108
109 TESTGROUP1_USER1 =
110 User.createUserForTesting(conf, "testgroup1_user1", new String[] { TESTGROUP_1 });
111 TESTGROUP2_USER1 =
112 User.createUserForTesting(conf, "testgroup2_user2", new String[] { TESTGROUP_2 });
113
114 systemUserConnection = ConnectionFactory.createConnection(conf);
115 }
116
117 @Before
118 public void setUp() throws Exception {
119 TEST_UTIL.getHBaseAdmin().createNamespace(NamespaceDescriptor.create(namespace).build());
120 try (Table table = TEST_UTIL.createTable(tableName,
121 new String[] { Bytes.toString(TEST_FAMILY), Bytes.toString(TEST_FAMILY_2) })) {
122 TEST_UTIL.waitUntilAllRegionsAssigned(tableName);
123
124
125 table.put(Arrays.asList(new Put(TEST_ROW).addColumn(TEST_FAMILY, Q1, value1),
126 new Put(TEST_ROW_2).addColumn(TEST_FAMILY, Q2, value2),
127 new Put(TEST_ROW_3).addColumn(TEST_FAMILY_2, Q1, value1)));
128 }
129
130 assertEquals(1, AccessControlLists.getTablePermissions(conf, tableName).size());
131 try {
132 assertEquals(1, AccessControlClient.getUserPermissions(systemUserConnection,
133 tableName.toString()).size());
134 } catch (Throwable e) {
135 LOG.error("Error during call of AccessControlClient.getUserPermissions. ", e);
136 }
137
138 }
139
140 @AfterClass
141 public static void tearDownAfterClass() throws Exception {
142 systemUserConnection.close();
143 TEST_UTIL.shutdownMiniCluster();
144 }
145
146 @After
147 public void tearDown() throws Exception {
148
149 TEST_UTIL.deleteTable(tableName);
150 TEST_UTIL.getHBaseAdmin().deleteNamespace(namespace);
151
152 assertEquals(0, AccessControlLists.getTablePermissions(conf, tableName).size());
153 assertEquals(0, AccessControlLists.getNamespacePermissions(conf, namespace).size());
154 }
155
156 @Test
157 public void testCreateWithCorrectOwner() throws Exception {
158
159 final User testUser = User.createUserForTesting(TEST_UTIL.getConfiguration(), "TestUser",
160 new String[0]);
161
162 SecureTestUtil.grantGlobal(TEST_UTIL, testUser.getShortName(), Action.CREATE);
163 verifyAllowed(new AccessTestAction() {
164 @Override
165 public Object run() throws Exception {
166 HTableDescriptor desc = new HTableDescriptor(TEST_TABLE.getTableName());
167 desc.addFamily(new HColumnDescriptor(TEST_FAMILY));
168 try (Connection connection =
169 ConnectionFactory.createConnection(TEST_UTIL.getConfiguration(), testUser)) {
170 try (Admin admin = connection.getAdmin()) {
171 admin.createTable(desc);
172 }
173 }
174 return null;
175 }
176 }, testUser);
177 TEST_UTIL.waitTableEnabled(TEST_TABLE.getTableName());
178
179
180 List<TablePermission> perms =
181 AccessControlLists.getTablePermissions(conf, TEST_TABLE.getTableName())
182 .get(testUser.getShortName());
183 assertNotNull(perms);
184 assertFalse(perms.isEmpty());
185
186 assertTrue(perms.get(0).implies(Permission.Action.READ));
187 assertTrue(perms.get(0).implies(Permission.Action.WRITE));
188 assertTrue(perms.get(0).implies(Permission.Action.EXEC));
189 assertTrue(perms.get(0).implies(Permission.Action.CREATE));
190 assertTrue(perms.get(0).implies(Permission.Action.ADMIN));
191 }
192
193 @Test
194 public void testACLTableAccess() throws Exception {
195 final Configuration conf = TEST_UTIL.getConfiguration();
196
197
198 User superUser = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
199
200
201 User globalRead = User.createUserForTesting(conf, "globalRead", new String[0]);
202 User globalWrite = User.createUserForTesting(conf, "globalWrite", new String[0]);
203 User globalCreate = User.createUserForTesting(conf, "globalCreate", new String[0]);
204 User globalAdmin = User.createUserForTesting(conf, "globalAdmin", new String[0]);
205 SecureTestUtil.grantGlobal(TEST_UTIL, globalRead.getShortName(), Action.READ);
206 SecureTestUtil.grantGlobal(TEST_UTIL, globalWrite.getShortName(), Action.WRITE);
207 SecureTestUtil.grantGlobal(TEST_UTIL, globalCreate.getShortName(), Action.CREATE);
208 SecureTestUtil.grantGlobal(TEST_UTIL, globalAdmin.getShortName(), Action.ADMIN);
209
210
211 User nsRead = User.createUserForTesting(conf, "nsRead", new String[0]);
212 User nsWrite = User.createUserForTesting(conf, "nsWrite", new String[0]);
213 User nsCreate = User.createUserForTesting(conf, "nsCreate", new String[0]);
214 User nsAdmin = User.createUserForTesting(conf, "nsAdmin", new String[0]);
215 SecureTestUtil.grantOnNamespace(TEST_UTIL, nsRead.getShortName(),
216 TEST_TABLE.getTableName().getNamespaceAsString(), Action.READ);
217 SecureTestUtil.grantOnNamespace(TEST_UTIL, nsWrite.getShortName(),
218 TEST_TABLE.getTableName().getNamespaceAsString(), Action.WRITE);
219 SecureTestUtil.grantOnNamespace(TEST_UTIL, nsCreate.getShortName(),
220 TEST_TABLE.getTableName().getNamespaceAsString(), Action.CREATE);
221 SecureTestUtil.grantOnNamespace(TEST_UTIL, nsAdmin.getShortName(),
222 TEST_TABLE.getTableName().getNamespaceAsString(), Action.ADMIN);
223
224
225 User tableRead = User.createUserForTesting(conf, "tableRead", new String[0]);
226 User tableWrite = User.createUserForTesting(conf, "tableWrite", new String[0]);
227 User tableCreate = User.createUserForTesting(conf, "tableCreate", new String[0]);
228 User tableAdmin = User.createUserForTesting(conf, "tableAdmin", new String[0]);
229 SecureTestUtil.grantOnTable(TEST_UTIL, tableRead.getShortName(),
230 TEST_TABLE.getTableName(), null, null, Action.READ);
231 SecureTestUtil.grantOnTable(TEST_UTIL, tableWrite.getShortName(),
232 TEST_TABLE.getTableName(), null, null, Action.WRITE);
233 SecureTestUtil.grantOnTable(TEST_UTIL, tableCreate.getShortName(),
234 TEST_TABLE.getTableName(), null, null, Action.CREATE);
235 SecureTestUtil.grantOnTable(TEST_UTIL, tableAdmin.getShortName(),
236 TEST_TABLE.getTableName(), null, null, Action.ADMIN);
237
238
239
240 AccessTestAction writeAction = new AccessTestAction() {
241 @Override
242 public Object run() throws Exception {
243 try(Connection conn = ConnectionFactory.createConnection(conf);
244 Table t = conn.getTable(AccessControlLists.ACL_TABLE_NAME)) {
245 t.put(new Put(TEST_ROW).add(AccessControlLists.ACL_LIST_FAMILY, TEST_QUALIFIER,
246 TEST_VALUE));
247 return null;
248 } finally {
249 }
250 }
251 };
252
253
254
255 verifyDenied(writeAction, globalAdmin, globalCreate, globalRead);
256 verifyDenied(writeAction, nsAdmin, nsCreate, nsRead, nsWrite);
257 verifyDenied(writeAction, tableAdmin, tableCreate, tableRead, tableWrite);
258 verifyAllowed(writeAction, superUser, globalWrite);
259
260
261
262 AccessTestAction scanAction = new AccessTestAction() {
263 @Override
264 public Object run() throws Exception {
265 try(Connection conn = ConnectionFactory.createConnection(conf);
266 Table t = conn.getTable(AccessControlLists.ACL_TABLE_NAME)) {
267 ResultScanner s = t.getScanner(new Scan());
268 try {
269 for (Result r = s.next(); r != null; r = s.next()) {
270
271 }
272 } finally {
273 s.close();
274 }
275 return null;
276 }
277 }
278 };
279
280
281
282 verifyDenied(scanAction, globalAdmin, globalCreate, globalWrite);
283 verifyDenied(scanAction, nsCreate, nsAdmin, nsRead, nsWrite);
284 verifyDenied(scanAction, tableCreate, tableAdmin, tableRead, tableWrite);
285 verifyAllowed(scanAction, superUser, globalRead);
286 }
287
288
289
290
291 @Test(timeout = 300000)
292 public void testPostGrantAndRevokeScanAction() throws Exception {
293 AccessTestAction scanTableActionForGroupWithTableLevelAccess = new AccessTestAction() {
294 @Override
295 public Void run() throws Exception {
296 try (Connection connection = ConnectionFactory.createConnection(conf);
297 Table table = connection.getTable(tableName);) {
298 Scan s1 = new Scan();
299 try (ResultScanner scanner1 = table.getScanner(s1);) {
300 Result[] next1 = scanner1.next(5);
301 assertTrue("User having table level access should be able to scan all "
302 + "the data in the table.", next1.length == 3);
303 }
304 }
305 return null;
306 }
307 };
308
309 AccessTestAction scanTableActionForGroupWithFamilyLevelAccess = new AccessTestAction() {
310 @Override
311 public Void run() throws Exception {
312 try (Connection connection = ConnectionFactory.createConnection(conf);
313 Table table = connection.getTable(tableName);) {
314 Scan s1 = new Scan();
315 try (ResultScanner scanner1 = table.getScanner(s1);) {
316 Result[] next1 = scanner1.next(5);
317 assertTrue("User having column family level access should be able to scan all "
318 + "the data belonging to that family.", next1.length == 2);
319 }
320 }
321 return null;
322 }
323 };
324
325 AccessTestAction scanFamilyActionForGroupWithFamilyLevelAccess = new AccessTestAction() {
326 @Override
327 public Void run() throws Exception {
328 try (Connection connection = ConnectionFactory.createConnection(conf);
329 Table table = connection.getTable(tableName);) {
330 Scan s1 = new Scan();
331 s1.addFamily(TEST_FAMILY_2);
332 try (ResultScanner scanner1 = table.getScanner(s1);) {
333 }
334 }
335 return null;
336 }
337 };
338
339 AccessTestAction scanTableActionForGroupWithQualifierLevelAccess = new AccessTestAction() {
340 @Override
341 public Void run() throws Exception {
342 try (Connection connection = ConnectionFactory.createConnection(conf);
343 Table table = connection.getTable(tableName);) {
344 Scan s1 = new Scan();
345 try (ResultScanner scanner1 = table.getScanner(s1);) {
346 Result[] next1 = scanner1.next(5);
347 assertTrue("User having column qualifier level access should be able to scan "
348 + "that column family qualifier data.", next1.length == 1);
349 }
350 }
351 return null;
352 }
353 };
354
355 AccessTestAction scanFamilyActionForGroupWithQualifierLevelAccess = new AccessTestAction() {
356 @Override
357 public Void run() throws Exception {
358 try (Connection connection = ConnectionFactory.createConnection(conf);
359 Table table = connection.getTable(tableName);) {
360 Scan s1 = new Scan();
361 s1.addFamily(TEST_FAMILY_2);
362 try (ResultScanner scanner1 = table.getScanner(s1);) {
363 }
364 }
365 return null;
366 }
367 };
368
369 AccessTestAction scanQualifierActionForGroupWithQualifierLevelAccess = new AccessTestAction() {
370 @Override
371 public Void run() throws Exception {
372 try (Connection connection = ConnectionFactory.createConnection(conf);
373 Table table = connection.getTable(tableName);) {
374 Scan s1 = new Scan();
375 s1.addColumn(TEST_FAMILY, Q2);
376 try (ResultScanner scanner1 = table.getScanner(s1);) {
377 }
378 }
379 return null;
380 }
381 };
382
383
384
385 grantOnTable(TEST_UTIL, convertToGroup(TESTGROUP_1), tableName, null, null, Action.READ);
386 verifyAllowed(TESTGROUP1_USER1, scanTableActionForGroupWithTableLevelAccess);
387 verifyDenied(TESTGROUP2_USER1, scanTableActionForGroupWithTableLevelAccess);
388
389
390 revokeFromTable(TEST_UTIL, convertToGroup(TESTGROUP_1), tableName, null, null);
391 verifyDenied(TESTGROUP1_USER1, scanTableActionForGroupWithTableLevelAccess);
392
393
394
395 grantOnTable(TEST_UTIL, convertToGroup(TESTGROUP_1), tableName, TEST_FAMILY, null,
396 Permission.Action.READ);
397 verifyAllowed(TESTGROUP1_USER1, scanTableActionForGroupWithFamilyLevelAccess);
398 verifyDenied(TESTGROUP1_USER1, scanFamilyActionForGroupWithFamilyLevelAccess);
399 verifyDenied(TESTGROUP2_USER1, scanTableActionForGroupWithFamilyLevelAccess);
400 verifyDenied(TESTGROUP2_USER1, scanFamilyActionForGroupWithFamilyLevelAccess);
401
402
403
404 revokeFromTable(TEST_UTIL, convertToGroup(TESTGROUP_1), tableName, TEST_FAMILY, null);
405 verifyDenied(TESTGROUP1_USER1, scanTableActionForGroupWithFamilyLevelAccess);
406
407
408
409 grantOnTable(TEST_UTIL, convertToGroup(TESTGROUP_1), tableName, TEST_FAMILY, Q1, Action.READ);
410 verifyAllowed(TESTGROUP1_USER1, scanTableActionForGroupWithQualifierLevelAccess);
411 verifyDenied(TESTGROUP1_USER1, scanFamilyActionForGroupWithQualifierLevelAccess);
412 verifyDenied(TESTGROUP1_USER1, scanQualifierActionForGroupWithQualifierLevelAccess);
413 verifyDenied(TESTGROUP2_USER1, scanTableActionForGroupWithQualifierLevelAccess);
414 verifyDenied(TESTGROUP2_USER1, scanFamilyActionForGroupWithQualifierLevelAccess);
415 verifyDenied(TESTGROUP2_USER1, scanQualifierActionForGroupWithQualifierLevelAccess);
416
417
418
419 revokeFromTable(TEST_UTIL, convertToGroup(TESTGROUP_1), tableName, TEST_FAMILY, Q1);
420 verifyDenied(TESTGROUP1_USER1, scanTableActionForGroupWithQualifierLevelAccess);
421 }
422
423 @Test
424 public void testACLZNodeDeletion() throws Exception {
425 String baseAclZNode = "/hbase/acl/";
426 String ns = "testACLZNodeDeletionNamespace";
427 NamespaceDescriptor desc = NamespaceDescriptor.create(ns).build();
428 createNamespace(TEST_UTIL, desc);
429
430 final TableName table = TableName.valueOf(ns, "testACLZNodeDeletionTable");
431 final byte[] family = Bytes.toBytes("f1");
432 HTableDescriptor htd = new HTableDescriptor(table);
433 htd.addFamily(new HColumnDescriptor(family));
434 TEST_UTIL.getHBaseAdmin().createTable(htd);
435
436
437 grantOnNamespace(TEST_UTIL, TESTGROUP1_USER1.getShortName(), ns, Action.ADMIN);
438 ZooKeeperWatcher zkw = TEST_UTIL.getMiniHBaseCluster().getMaster().getZooKeeper();
439 assertTrue("The acl znode for table should exist", ZKUtil.checkExists(zkw, baseAclZNode +
440 table.getNameAsString()) != -1);
441 assertTrue("The acl znode for namespace should exist", ZKUtil.checkExists(zkw, baseAclZNode +
442 convertToNamespace(ns)) != -1);
443
444 revokeFromNamespace(TEST_UTIL, TESTGROUP1_USER1.getShortName(), ns, Action.ADMIN);
445 TEST_UTIL.deleteTable(table);
446 deleteNamespace(TEST_UTIL, ns);
447
448 assertTrue("The acl znode for table should have been deleted",
449 ZKUtil.checkExists(zkw, baseAclZNode + table.getNameAsString()) == -1);
450 assertTrue( "The acl znode for namespace should have been deleted",
451 ZKUtil.checkExists(zkw, baseAclZNode + convertToNamespace(ns)) == -1);
452 }
453 }