001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.rsgroup; 019 020import static org.apache.hadoop.hbase.AuthUtil.toGroupEntry; 021import static org.junit.Assert.assertEquals; 022import static org.junit.Assert.assertTrue; 023import static org.junit.Assert.fail; 024 025import org.apache.hadoop.conf.Configuration; 026import org.apache.hadoop.hbase.HBaseClassTestRule; 027import org.apache.hadoop.hbase.HBaseTestingUtility; 028import org.apache.hadoop.hbase.HConstants; 029import org.apache.hadoop.hbase.TableName; 030import org.apache.hadoop.hbase.TableNotFoundException; 031import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 032import org.apache.hadoop.hbase.client.Connection; 033import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 034import org.apache.hadoop.hbase.coprocessor.CoprocessorHost; 035import org.apache.hadoop.hbase.security.User; 036import org.apache.hadoop.hbase.security.access.AccessControlClient; 037import org.apache.hadoop.hbase.security.access.AccessControlLists; 038import org.apache.hadoop.hbase.security.access.AuthManager; 039import org.apache.hadoop.hbase.security.access.Permission; 040import org.apache.hadoop.hbase.security.access.SecureTestUtil; 041import org.apache.hadoop.hbase.testclassification.MediumTests; 042import org.apache.hadoop.hbase.testclassification.SecurityTests; 043import org.apache.hadoop.hbase.util.Bytes; 044 045import org.junit.AfterClass; 046import org.junit.BeforeClass; 047import org.junit.ClassRule; 048import org.junit.Test; 049import org.junit.experimental.categories.Category; 050import org.slf4j.Logger; 051import org.slf4j.LoggerFactory; 052 053/** 054 * Performs authorization checks for rsgroup operations, according to different 055 * levels of authorized users. 056 */ 057@Category({SecurityTests.class, MediumTests.class}) 058public class TestRSGroupsWithACL extends SecureTestUtil{ 059 060 @ClassRule 061 public static final HBaseClassTestRule CLASS_RULE = 062 HBaseClassTestRule.forClass(TestRSGroupsWithACL.class); 063 064 private static final Logger LOG = LoggerFactory.getLogger(TestRSGroupsWithACL.class); 065 private static TableName TEST_TABLE = TableName.valueOf("testtable1"); 066 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); 067 private static Configuration conf; 068 069 private static Connection systemUserConnection; 070 // user with all permissions 071 private static User SUPERUSER; 072 // user granted with all global permission 073 private static User USER_ADMIN; 074 // user with rw permissions on column family. 075 private static User USER_RW; 076 // user with read-only permissions 077 private static User USER_RO; 078 // user is table owner. will have all permissions on table 079 private static User USER_OWNER; 080 // user with create table permissions alone 081 private static User USER_CREATE; 082 // user with no permissions 083 private static User USER_NONE; 084 085 private static final String GROUP_ADMIN = "group_admin"; 086 private static final String GROUP_CREATE = "group_create"; 087 private static final String GROUP_READ = "group_read"; 088 private static final String GROUP_WRITE = "group_write"; 089 090 private static User USER_GROUP_ADMIN; 091 private static User USER_GROUP_CREATE; 092 private static User USER_GROUP_READ; 093 private static User USER_GROUP_WRITE; 094 095 private static byte[] TEST_FAMILY = Bytes.toBytes("f1"); 096 097 private static RSGroupAdminEndpoint rsGroupAdminEndpoint; 098 099 @BeforeClass 100 public static void setupBeforeClass() throws Exception { 101 // setup configuration 102 conf = TEST_UTIL.getConfiguration(); 103 conf.set(HConstants.HBASE_MASTER_LOADBALANCER_CLASS, 104 RSGroupBasedLoadBalancer.class.getName()); 105 // Enable security 106 enableSecurity(conf); 107 // Verify enableSecurity sets up what we require 108 verifyConfiguration(conf); 109 // Enable rsgroup 110 configureRSGroupAdminEndpoint(conf); 111 112 TEST_UTIL.startMiniCluster(); 113 rsGroupAdminEndpoint = (RSGroupAdminEndpoint) TEST_UTIL.getMiniHBaseCluster().getMaster(). 114 getMasterCoprocessorHost().findCoprocessor(RSGroupAdminEndpoint.class.getName()); 115 // Wait for the ACL table to become available 116 TEST_UTIL.waitUntilAllRegionsAssigned(AccessControlLists.ACL_TABLE_NAME); 117 118 // create a set of test users 119 SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" }); 120 USER_ADMIN = User.createUserForTesting(conf, "admin2", new String[0]); 121 USER_RW = User.createUserForTesting(conf, "rwuser", new String[0]); 122 USER_RO = User.createUserForTesting(conf, "rouser", new String[0]); 123 USER_OWNER = User.createUserForTesting(conf, "owner", new String[0]); 124 USER_CREATE = User.createUserForTesting(conf, "tbl_create", new String[0]); 125 USER_NONE = User.createUserForTesting(conf, "nouser", new String[0]); 126 127 USER_GROUP_ADMIN = 128 User.createUserForTesting(conf, "user_group_admin", new String[] { GROUP_ADMIN }); 129 USER_GROUP_CREATE = 130 User.createUserForTesting(conf, "user_group_create", new String[] { GROUP_CREATE }); 131 USER_GROUP_READ = 132 User.createUserForTesting(conf, "user_group_read", new String[] { GROUP_READ }); 133 USER_GROUP_WRITE = 134 User.createUserForTesting(conf, "user_group_write", new String[] { GROUP_WRITE }); 135 136 systemUserConnection = TEST_UTIL.getConnection(); 137 setUpTableAndUserPermissions(); 138 } 139 140 private static void setUpTableAndUserPermissions() throws Exception { 141 TableDescriptorBuilder tableBuilder = TableDescriptorBuilder.newBuilder(TEST_TABLE); 142 ColumnFamilyDescriptorBuilder cfd = ColumnFamilyDescriptorBuilder.newBuilder(TEST_FAMILY); 143 cfd.setMaxVersions(100); 144 tableBuilder.setColumnFamily(cfd.build()); 145 tableBuilder.setValue(TableDescriptorBuilder.OWNER, USER_OWNER.getShortName()); 146 createTable(TEST_UTIL, tableBuilder.build(), 147 new byte[][] { Bytes.toBytes("s") }); 148 149 // Set up initial grants 150 grantGlobal(TEST_UTIL, USER_ADMIN.getShortName(), 151 Permission.Action.ADMIN, 152 Permission.Action.CREATE, 153 Permission.Action.READ, 154 Permission.Action.WRITE); 155 156 grantOnTable(TEST_UTIL, USER_RW.getShortName(), 157 TEST_TABLE, TEST_FAMILY, null, 158 Permission.Action.READ, 159 Permission.Action.WRITE); 160 161 // USER_CREATE is USER_RW plus CREATE permissions 162 grantOnTable(TEST_UTIL, USER_CREATE.getShortName(), 163 TEST_TABLE, null, null, 164 Permission.Action.CREATE, 165 Permission.Action.READ, 166 Permission.Action.WRITE); 167 168 grantOnTable(TEST_UTIL, USER_RO.getShortName(), 169 TEST_TABLE, TEST_FAMILY, null, 170 Permission.Action.READ); 171 172 grantGlobal(TEST_UTIL, toGroupEntry(GROUP_ADMIN), Permission.Action.ADMIN); 173 grantGlobal(TEST_UTIL, toGroupEntry(GROUP_CREATE), Permission.Action.CREATE); 174 grantGlobal(TEST_UTIL, toGroupEntry(GROUP_READ), Permission.Action.READ); 175 grantGlobal(TEST_UTIL, toGroupEntry(GROUP_WRITE), Permission.Action.WRITE); 176 177 assertEquals(4, AccessControlLists.getTablePermissions(conf, TEST_TABLE).size()); 178 try { 179 assertEquals(4, AccessControlClient.getUserPermissions(systemUserConnection, 180 TEST_TABLE.toString()).size()); 181 } catch (AssertionError e) { 182 fail(e.getMessage()); 183 } catch (Throwable e) { 184 LOG.error("error during call of AccessControlClient.getUserPermissions. ", e); 185 } 186 } 187 188 private static void cleanUp() throws Exception { 189 // Clean the _acl_ table 190 try { 191 deleteTable(TEST_UTIL, TEST_TABLE); 192 } catch (TableNotFoundException ex) { 193 // Test deleted the table, no problem 194 LOG.info("Test deleted table " + TEST_TABLE); 195 } 196 // Verify all table/namespace permissions are erased 197 assertEquals(0, AccessControlLists.getTablePermissions(conf, TEST_TABLE).size()); 198 assertEquals(0, AccessControlLists.getNamespacePermissions(conf, 199 TEST_TABLE.getNamespaceAsString()).size()); 200 } 201 202 @AfterClass 203 public static void tearDownAfterClass() throws Exception { 204 cleanUp(); 205 TEST_UTIL.shutdownMiniCluster(); 206 int total = AuthManager.getTotalRefCount(); 207 assertTrue("Unexpected reference count: " + total, total == 0); 208 } 209 210 private static void configureRSGroupAdminEndpoint(Configuration conf) { 211 String currentCoprocessors = conf.get(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY); 212 String coprocessors = RSGroupAdminEndpoint.class.getName(); 213 if (currentCoprocessors != null) { 214 coprocessors += "," + currentCoprocessors; 215 } 216 conf.set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY, coprocessors); 217 conf.set(HConstants.HBASE_MASTER_LOADBALANCER_CLASS, 218 RSGroupBasedLoadBalancer.class.getName()); 219 } 220 221 @Test 222 public void testGetRSGroupInfo() throws Exception { 223 AccessTestAction action = () -> { 224 rsGroupAdminEndpoint.checkPermission("getRSGroupInfo"); 225 return null; 226 }; 227 228 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 229 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, 230 USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 231 } 232 233 @Test 234 public void testGetRSGroupInfoOfTable() throws Exception { 235 AccessTestAction action = () -> { 236 rsGroupAdminEndpoint.checkPermission("getRSGroupInfoOfTable"); 237 return null; 238 }; 239 240 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 241 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, 242 USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 243 } 244 245 @Test 246 public void testMoveServers() throws Exception { 247 AccessTestAction action = () -> { 248 rsGroupAdminEndpoint.checkPermission("moveServers"); 249 return null; 250 }; 251 252 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 253 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, 254 USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 255 } 256 257 @Test 258 public void testMoveTables() throws Exception { 259 AccessTestAction action = () -> { 260 rsGroupAdminEndpoint.checkPermission("moveTables"); 261 return null; 262 }; 263 264 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 265 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, 266 USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 267 } 268 269 @Test 270 public void testAddRSGroup() throws Exception { 271 AccessTestAction action = () -> { 272 rsGroupAdminEndpoint.checkPermission("addRSGroup"); 273 return null; 274 }; 275 276 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 277 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, 278 USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 279 } 280 281 @Test 282 public void testRemoveRSGroup() throws Exception { 283 AccessTestAction action = () -> { 284 rsGroupAdminEndpoint.checkPermission("removeRSGroup"); 285 return null; 286 }; 287 288 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 289 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, 290 USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 291 } 292 293 @Test 294 public void testBalanceRSGroup() throws Exception { 295 AccessTestAction action = () -> { 296 rsGroupAdminEndpoint.checkPermission("balanceRSGroup"); 297 return null; 298 }; 299 300 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 301 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, 302 USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 303 } 304 305 @Test 306 public void testListRSGroup() throws Exception { 307 AccessTestAction action = () -> { 308 rsGroupAdminEndpoint.checkPermission("listRSGroup"); 309 return null; 310 }; 311 312 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 313 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, 314 USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 315 } 316 317 @Test 318 public void testGetRSGroupInfoOfServer() throws Exception { 319 AccessTestAction action = () -> { 320 rsGroupAdminEndpoint.checkPermission("getRSGroupInfoOfServer"); 321 return null; 322 }; 323 324 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 325 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, 326 USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 327 } 328 329 @Test 330 public void testMoveServersAndTables() throws Exception { 331 AccessTestAction action = () -> { 332 rsGroupAdminEndpoint.checkPermission("moveServersAndTables"); 333 return null; 334 }; 335 336 verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN); 337 verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO, 338 USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE); 339 } 340}