1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.security.access;
20
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertFalse;
23 import static org.junit.Assert.assertNotNull;
24 import static org.junit.Assert.assertNull;
25 import static org.junit.Assert.assertTrue;
26 import static org.junit.Assert.fail;
27
28 import java.io.ByteArrayOutputStream;
29 import java.io.DataOutput;
30 import java.io.DataOutputStream;
31 import java.io.IOException;
32 import java.util.Arrays;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Set;
36 import java.util.concurrent.atomic.AtomicBoolean;
37
38 import org.apache.commons.logging.Log;
39 import org.apache.commons.logging.LogFactory;
40 import org.apache.hadoop.conf.Configuration;
41 import org.apache.hadoop.hbase.Abortable;
42 import org.apache.hadoop.hbase.HConstants;
43 import org.apache.hadoop.hbase.TableName;
44 import org.apache.hadoop.hbase.exceptions.DeserializationException;
45 import org.apache.hadoop.hbase.HBaseTestingUtility;
46 import org.apache.hadoop.hbase.testclassification.LargeTests;
47 import org.apache.hadoop.hbase.client.HBaseAdmin;
48 import org.apache.hadoop.hbase.client.HTable;
49 import org.apache.hadoop.hbase.client.Put;
50 import org.apache.hadoop.hbase.security.User;
51 import org.apache.hadoop.hbase.util.Bytes;
52 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
53 import org.apache.hadoop.io.Text;
54 import org.junit.After;
55 import org.junit.AfterClass;
56 import org.junit.BeforeClass;
57 import org.junit.Test;
58 import org.junit.experimental.categories.Category;
59
60 import com.google.common.collect.ArrayListMultimap;
61 import com.google.common.collect.ListMultimap;
62
63
64
65
66 @Category(LargeTests.class)
67 public class TestTablePermissions {
68 private static final Log LOG = LogFactory.getLog(TestTablePermissions.class);
69 private static final HBaseTestingUtility UTIL = new HBaseTestingUtility();
70 private static ZooKeeperWatcher ZKW;
71 private final static Abortable ABORTABLE = new Abortable() {
72 private final AtomicBoolean abort = new AtomicBoolean(false);
73
74 @Override
75 public void abort(String why, Throwable e) {
76 LOG.info(why, e);
77 abort.set(true);
78 }
79
80 @Override
81 public boolean isAborted() {
82 return abort.get();
83 }
84 };
85
86 private static TableName TEST_TABLE =
87 TableName.valueOf("perms_test");
88 private static TableName TEST_TABLE2 =
89 TableName.valueOf("perms_test2");
90 private static byte[] TEST_FAMILY = Bytes.toBytes("f1");
91 private static byte[] TEST_QUALIFIER = Bytes.toBytes("col1");
92
93 @BeforeClass
94 public static void beforeClass() throws Exception {
95
96 Configuration conf = UTIL.getConfiguration();
97 SecureTestUtil.enableSecurity(conf);
98
99 UTIL.startMiniCluster();
100
101
102 UTIL.waitTableEnabled(AccessControlLists.ACL_TABLE_NAME.getName());
103
104 ZKW = new ZooKeeperWatcher(UTIL.getConfiguration(),
105 "TestTablePermissions", ABORTABLE);
106
107 UTIL.createTable(TEST_TABLE, TEST_FAMILY);
108 UTIL.createTable(TEST_TABLE2, TEST_FAMILY);
109 }
110
111 @AfterClass
112 public static void afterClass() throws Exception {
113 UTIL.shutdownMiniCluster();
114 }
115
116 @After
117 public void tearDown() throws Exception {
118 Configuration conf = UTIL.getConfiguration();
119 AccessControlLists.removeTablePermissions(conf, TEST_TABLE);
120 AccessControlLists.removeTablePermissions(conf, TEST_TABLE2);
121 AccessControlLists.removeTablePermissions(conf, AccessControlLists.ACL_TABLE_NAME);
122 }
123
124
125
126
127
128 @Test
129 public void testMigration() throws DeserializationException {
130 Configuration conf = new Configuration(UTIL.getConfiguration());
131 conf.setBoolean(HConstants.ALLOW_LEGACY_OBJECT_SERIALIZATION_KEY, true);
132 ListMultimap<String,TablePermission> permissions = createPermissions();
133 byte [] bytes = writePermissionsAsLegacyBytes(permissions, conf);
134 AccessControlLists.readPermissions(bytes, conf);
135 }
136
137
138
139
140
141
142 public static byte[] writePermissionsAsLegacyBytes(ListMultimap<String,? extends Permission> perms,
143 Configuration conf) {
144 try {
145 ByteArrayOutputStream bos = new ByteArrayOutputStream();
146 writeLegacyPermissions(new DataOutputStream(bos), perms, conf);
147 return bos.toByteArray();
148 } catch (IOException ioe) {
149
150 throw new RuntimeException("Error serializing permissions", ioe);
151 }
152 }
153
154
155
156
157
158
159
160
161
162 public static void writeLegacyPermissions(DataOutput out,
163 ListMultimap<String,? extends Permission> perms, Configuration conf)
164 throws IOException {
165 Set<String> keys = perms.keySet();
166 out.writeInt(keys.size());
167 for (String key : keys) {
168 Text.writeString(out, key);
169 HbaseObjectWritableFor96Migration.writeObject(out, perms.get(key), List.class, conf);
170 }
171 }
172
173
174 @Test
175 public void testBasicWrite() throws Exception {
176 Configuration conf = UTIL.getConfiguration();
177
178 AccessControlLists.addUserPermission(conf,
179 new UserPermission(Bytes.toBytes("george"), TEST_TABLE, null, (byte[])null,
180 UserPermission.Action.READ, UserPermission.Action.WRITE));
181 AccessControlLists.addUserPermission(conf,
182 new UserPermission(Bytes.toBytes("hubert"), TEST_TABLE, null, (byte[])null,
183 UserPermission.Action.READ));
184 AccessControlLists.addUserPermission(conf,
185 new UserPermission(Bytes.toBytes("humphrey"),
186 TEST_TABLE, TEST_FAMILY, TEST_QUALIFIER,
187 UserPermission.Action.READ));
188
189
190 ListMultimap<String,TablePermission> perms =
191 AccessControlLists.getTablePermissions(conf, TEST_TABLE);
192 List<TablePermission> userPerms = perms.get("george");
193 assertNotNull("Should have permissions for george", userPerms);
194 assertEquals("Should have 1 permission for george", 1, userPerms.size());
195 TablePermission permission = userPerms.get(0);
196 assertEquals("Permission should be for " + TEST_TABLE,
197 TEST_TABLE, permission.getTableName());
198 assertNull("Column family should be empty", permission.getFamily());
199
200
201 assertNotNull(permission.getActions());
202 assertEquals(2, permission.getActions().length);
203 List<TablePermission.Action> actions = Arrays.asList(permission.getActions());
204 assertTrue(actions.contains(TablePermission.Action.READ));
205 assertTrue(actions.contains(TablePermission.Action.WRITE));
206
207 userPerms = perms.get("hubert");
208 assertNotNull("Should have permissions for hubert", userPerms);
209 assertEquals("Should have 1 permission for hubert", 1, userPerms.size());
210 permission = userPerms.get(0);
211 assertEquals("Permission should be for " + TEST_TABLE,
212 TEST_TABLE, permission.getTableName());
213 assertNull("Column family should be empty", permission.getFamily());
214
215
216 assertNotNull(permission.getActions());
217 assertEquals(1, permission.getActions().length);
218 actions = Arrays.asList(permission.getActions());
219 assertTrue(actions.contains(TablePermission.Action.READ));
220 assertFalse(actions.contains(TablePermission.Action.WRITE));
221
222 userPerms = perms.get("humphrey");
223 assertNotNull("Should have permissions for humphrey", userPerms);
224 assertEquals("Should have 1 permission for humphrey", 1, userPerms.size());
225 permission = userPerms.get(0);
226 assertEquals("Permission should be for " + TEST_TABLE,
227 TEST_TABLE, permission.getTableName());
228 assertTrue("Permission should be for family " + TEST_FAMILY,
229 Bytes.equals(TEST_FAMILY, permission.getFamily()));
230 assertTrue("Permission should be for qualifier " + TEST_QUALIFIER,
231 Bytes.equals(TEST_QUALIFIER, permission.getQualifier()));
232
233
234 assertNotNull(permission.getActions());
235 assertEquals(1, permission.getActions().length);
236 actions = Arrays.asList(permission.getActions());
237 assertTrue(actions.contains(TablePermission.Action.READ));
238 assertFalse(actions.contains(TablePermission.Action.WRITE));
239
240
241 AccessControlLists.addUserPermission(conf,
242 new UserPermission(Bytes.toBytes("hubert"), TEST_TABLE2, null, (byte[])null,
243 TablePermission.Action.READ, TablePermission.Action.WRITE));
244
245
246 Map<byte[], ListMultimap<String,TablePermission>> allPerms =
247 AccessControlLists.loadAll(conf);
248 assertEquals("Full permission map should have entries for both test tables",
249 2, allPerms.size());
250
251 userPerms = allPerms.get(TEST_TABLE.getName()).get("hubert");
252 assertNotNull(userPerms);
253 assertEquals(1, userPerms.size());
254 permission = userPerms.get(0);
255 assertEquals(TEST_TABLE, permission.getTableName());
256 assertEquals(1, permission.getActions().length);
257 assertEquals(TablePermission.Action.READ, permission.getActions()[0]);
258
259 userPerms = allPerms.get(TEST_TABLE2.getName()).get("hubert");
260 assertNotNull(userPerms);
261 assertEquals(1, userPerms.size());
262 permission = userPerms.get(0);
263 assertEquals(TEST_TABLE2, permission.getTableName());
264 assertEquals(2, permission.getActions().length);
265 actions = Arrays.asList(permission.getActions());
266 assertTrue(actions.contains(TablePermission.Action.READ));
267 assertTrue(actions.contains(TablePermission.Action.WRITE));
268 }
269
270 @Test
271 public void testPersistence() throws Exception {
272 Configuration conf = UTIL.getConfiguration();
273 AccessControlLists.addUserPermission(conf,
274 new UserPermission(Bytes.toBytes("albert"), TEST_TABLE, null,
275 (byte[])null, TablePermission.Action.READ));
276 AccessControlLists.addUserPermission(conf,
277 new UserPermission(Bytes.toBytes("betty"), TEST_TABLE, null,
278 (byte[])null, TablePermission.Action.READ,
279 TablePermission.Action.WRITE));
280 AccessControlLists.addUserPermission(conf,
281 new UserPermission(Bytes.toBytes("clark"),
282 TEST_TABLE, TEST_FAMILY,
283 TablePermission.Action.READ));
284 AccessControlLists.addUserPermission(conf,
285 new UserPermission(Bytes.toBytes("dwight"),
286 TEST_TABLE, TEST_FAMILY, TEST_QUALIFIER,
287 TablePermission.Action.WRITE));
288
289
290 ListMultimap<String,TablePermission> preperms =
291 AccessControlLists.getTablePermissions(conf, TEST_TABLE);
292
293 HTable table = new HTable(conf, TEST_TABLE);
294 table.put(new Put(Bytes.toBytes("row1"))
295 .add(TEST_FAMILY, TEST_QUALIFIER, Bytes.toBytes("v1")));
296 table.put(new Put(Bytes.toBytes("row2"))
297 .add(TEST_FAMILY, TEST_QUALIFIER, Bytes.toBytes("v2")));
298 HBaseAdmin admin = UTIL.getHBaseAdmin();
299 admin.split(TEST_TABLE.getName());
300
301
302 Thread.sleep(10000);
303
304 ListMultimap<String,TablePermission> postperms =
305 AccessControlLists.getTablePermissions(conf, TEST_TABLE);
306
307 checkMultimapEqual(preperms, postperms);
308 }
309
310 @Test
311 public void testSerialization() throws Exception {
312 Configuration conf = UTIL.getConfiguration();
313 ListMultimap<String,TablePermission> permissions = createPermissions();
314 byte[] permsData = AccessControlLists.writePermissionsAsBytes(permissions, conf);
315
316 ListMultimap<String, TablePermission> copy =
317 AccessControlLists.readPermissions(permsData, conf);
318
319 checkMultimapEqual(permissions, copy);
320 }
321
322 private ListMultimap<String,TablePermission> createPermissions() {
323 ListMultimap<String,TablePermission> permissions = ArrayListMultimap.create();
324 permissions.put("george", new TablePermission(TEST_TABLE, null,
325 TablePermission.Action.READ));
326 permissions.put("george", new TablePermission(TEST_TABLE, TEST_FAMILY,
327 TablePermission.Action.WRITE));
328 permissions.put("george", new TablePermission(TEST_TABLE2, null,
329 TablePermission.Action.READ));
330 permissions.put("hubert", new TablePermission(TEST_TABLE2, null,
331 TablePermission.Action.READ, TablePermission.Action.WRITE));
332 return permissions;
333 }
334
335 public void checkMultimapEqual(ListMultimap<String,TablePermission> first,
336 ListMultimap<String,TablePermission> second) {
337 assertEquals(first.size(), second.size());
338 for (String key : first.keySet()) {
339 List<TablePermission> firstPerms = first.get(key);
340 List<TablePermission> secondPerms = second.get(key);
341 assertNotNull(secondPerms);
342 assertEquals(firstPerms.size(), secondPerms.size());
343 LOG.info("First permissions: "+firstPerms.toString());
344 LOG.info("Second permissions: "+secondPerms.toString());
345 for (TablePermission p : firstPerms) {
346 assertTrue("Permission "+p.toString()+" not found", secondPerms.contains(p));
347 }
348 }
349 }
350
351 @Test
352 public void testEquals() throws Exception {
353 TablePermission p1 = new TablePermission(TEST_TABLE, null, TablePermission.Action.READ);
354 TablePermission p2 = new TablePermission(TEST_TABLE, null, TablePermission.Action.READ);
355 assertTrue(p1.equals(p2));
356 assertTrue(p2.equals(p1));
357
358 p1 = new TablePermission(TEST_TABLE, null, TablePermission.Action.READ, TablePermission.Action.WRITE);
359 p2 = new TablePermission(TEST_TABLE, null, TablePermission.Action.WRITE, TablePermission.Action.READ);
360 assertTrue(p1.equals(p2));
361 assertTrue(p2.equals(p1));
362
363 p1 = new TablePermission(TEST_TABLE, TEST_FAMILY, TablePermission.Action.READ, TablePermission.Action.WRITE);
364 p2 = new TablePermission(TEST_TABLE, TEST_FAMILY, TablePermission.Action.WRITE, TablePermission.Action.READ);
365 assertTrue(p1.equals(p2));
366 assertTrue(p2.equals(p1));
367
368 p1 = new TablePermission(TEST_TABLE, TEST_FAMILY, TEST_QUALIFIER, TablePermission.Action.READ, TablePermission.Action.WRITE);
369 p2 = new TablePermission(TEST_TABLE, TEST_FAMILY, TEST_QUALIFIER, TablePermission.Action.WRITE, TablePermission.Action.READ);
370 assertTrue(p1.equals(p2));
371 assertTrue(p2.equals(p1));
372
373 p1 = new TablePermission(TEST_TABLE, null, TablePermission.Action.READ);
374 p2 = new TablePermission(TEST_TABLE, TEST_FAMILY, TablePermission.Action.READ);
375 assertFalse(p1.equals(p2));
376 assertFalse(p2.equals(p1));
377
378 p1 = new TablePermission(TEST_TABLE, null, TablePermission.Action.READ);
379 p2 = new TablePermission(TEST_TABLE, null, TablePermission.Action.WRITE);
380 assertFalse(p1.equals(p2));
381 assertFalse(p2.equals(p1));
382 p2 = new TablePermission(TEST_TABLE, null, TablePermission.Action.READ, TablePermission.Action.WRITE);
383 assertFalse(p1.equals(p2));
384 assertFalse(p2.equals(p1));
385
386 p1 = new TablePermission(TEST_TABLE, null, TablePermission.Action.READ);
387 p2 = new TablePermission(TEST_TABLE2, null, TablePermission.Action.READ);
388 assertFalse(p1.equals(p2));
389 assertFalse(p2.equals(p1));
390
391 p2 = new TablePermission(TEST_TABLE, null);
392 assertFalse(p1.equals(p2));
393 assertFalse(p2.equals(p1));
394 }
395
396 @Test
397 public void testGlobalPermission() throws Exception {
398 Configuration conf = UTIL.getConfiguration();
399
400
401 AccessControlLists.addUserPermission(conf,
402 new UserPermission(Bytes.toBytes("user1"),
403 Permission.Action.READ, Permission.Action.WRITE));
404 AccessControlLists.addUserPermission(conf,
405 new UserPermission(Bytes.toBytes("user2"),
406 Permission.Action.CREATE));
407 AccessControlLists.addUserPermission(conf,
408 new UserPermission(Bytes.toBytes("user3"),
409 Permission.Action.ADMIN, Permission.Action.READ, Permission.Action.CREATE));
410
411 ListMultimap<String,TablePermission> perms = AccessControlLists.getTablePermissions(conf, null);
412 List<TablePermission> user1Perms = perms.get("user1");
413 assertEquals("Should have 1 permission for user1", 1, user1Perms.size());
414 assertEquals("user1 should have WRITE permission",
415 new Permission.Action[] { Permission.Action.READ, Permission.Action.WRITE },
416 user1Perms.get(0).getActions());
417
418 List<TablePermission> user2Perms = perms.get("user2");
419 assertEquals("Should have 1 permission for user2", 1, user2Perms.size());
420 assertEquals("user2 should have CREATE permission",
421 new Permission.Action[] { Permission.Action.CREATE },
422 user2Perms.get(0).getActions());
423
424 List<TablePermission> user3Perms = perms.get("user3");
425 assertEquals("Should have 1 permission for user3", 1, user3Perms.size());
426 assertEquals("user3 should have ADMIN, READ, CREATE permission",
427 new Permission.Action[] {
428 Permission.Action.ADMIN, Permission.Action.READ, Permission.Action.CREATE
429 },
430 user3Perms.get(0).getActions());
431 }
432
433 @Test
434 public void testAuthManager() throws Exception {
435 Configuration conf = UTIL.getConfiguration();
436
437
438
439 TableAuthManager authManager = TableAuthManager.getOrCreate(ZKW, conf);
440
441 User currentUser = User.getCurrent();
442 assertTrue(authManager.authorize(currentUser, Permission.Action.ADMIN));
443 for (int i=1; i<=50; i++) {
444 AccessControlLists.addUserPermission(conf, new UserPermission(Bytes.toBytes("testauth"+i),
445 Permission.Action.ADMIN, Permission.Action.READ, Permission.Action.WRITE));
446
447 assertTrue("Failed current user auth check on iter "+i,
448 authManager.authorize(currentUser, Permission.Action.ADMIN));
449 }
450 }
451 }