View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.hadoop.hbase.rsgroup;
20  
21  import static org.apache.hadoop.hbase.AuthUtil.toGroupEntry;
22  import static org.junit.Assert.assertEquals;
23  import static org.junit.Assert.assertTrue;
24  
25  import org.apache.hadoop.conf.Configuration;
26  import org.apache.hadoop.hbase.HBaseTestingUtility;
27  import org.apache.hadoop.hbase.HColumnDescriptor;
28  import org.apache.hadoop.hbase.HConstants;
29  import org.apache.hadoop.hbase.HTableDescriptor;
30  import org.apache.hadoop.hbase.TableName;
31  import org.apache.hadoop.hbase.TableNotFoundException;
32  import org.apache.hadoop.hbase.client.Connection;
33  import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
34  import org.apache.hadoop.hbase.security.User;
35  import org.apache.hadoop.hbase.security.access.AccessControlClient;
36  import org.apache.hadoop.hbase.security.access.AccessControlLists;
37  import org.apache.hadoop.hbase.security.access.Permission;
38  import org.apache.hadoop.hbase.security.access.SecureTestUtil;
39  import org.apache.hadoop.hbase.security.access.TableAuthManager;
40  import org.apache.hadoop.hbase.testclassification.MediumTests;
41  import org.apache.hadoop.hbase.testclassification.SecurityTests;
42  import org.apache.hadoop.hbase.util.Bytes;
43  import org.junit.AfterClass;
44  import org.junit.BeforeClass;
45  import org.junit.Test;
46  import org.junit.experimental.categories.Category;
47  import org.slf4j.Logger;
48  import org.slf4j.LoggerFactory;
49  
50  /**
51   * Performs authorization checks for rsgroup operations, according to different
52   * levels of authorized users.
53   */
54  @Category({SecurityTests.class, MediumTests.class})
55  public class TestRSGroupsWithACL extends SecureTestUtil{
56    private static final Logger LOG = LoggerFactory.getLogger(TestRSGroupsWithACL.class);
57    private static TableName TEST_TABLE = TableName.valueOf("testtable1");
58    private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
59    private static Configuration conf;
60  
61    private static Connection systemUserConnection;
62    // user with all permissions
63    private static User SUPERUSER;
64    // user granted with all global permission
65    private static User USER_ADMIN;
66    // user with rw permissions on column family.
67    private static User USER_RW;
68    // user with read-only permissions
69    private static User USER_RO;
70    // user is table owner. will have all permissions on table
71    private static User USER_OWNER;
72    // user with create table permissions alone
73    private static User USER_CREATE;
74    // user with no permissions
75    private static User USER_NONE;
76  
77    private static final String GROUP_ADMIN = "group_admin";
78    private static final String GROUP_CREATE = "group_create";
79    private static final String GROUP_READ = "group_read";
80    private static final String GROUP_WRITE = "group_write";
81  
82    private static User USER_GROUP_ADMIN;
83    private static User USER_GROUP_CREATE;
84    private static User USER_GROUP_READ;
85    private static User USER_GROUP_WRITE;
86  
87    private static byte[] TEST_FAMILY = Bytes.toBytes("f1");
88  
89    private static RSGroupAdminEndpoint rsGroupAdminEndpoint;
90  
91    @BeforeClass
92    public static void setupBeforeClass() throws Exception {
93      // setup configuration
94      conf = TEST_UTIL.getConfiguration();
95      conf.set(HConstants.HBASE_MASTER_LOADBALANCER_CLASS,
96          RSGroupBasedLoadBalancer.class.getName());
97      // Enable security
98      enableSecurity(conf);
99      // Verify enableSecurity sets up what we require
100     verifyConfiguration(conf);
101     // Enable rsgroup
102     configureRSGroupAdminEndpoint(conf);
103 
104     TEST_UTIL.startMiniCluster();
105     rsGroupAdminEndpoint = (RSGroupAdminEndpoint) TEST_UTIL.getMiniHBaseCluster().getMaster().
106         getMasterCoprocessorHost().findCoprocessor(RSGroupAdminEndpoint.class.getName());
107     // Wait for the ACL table to become available
108     TEST_UTIL.waitUntilAllRegionsAssigned(AccessControlLists.ACL_TABLE_NAME);
109 
110     // create a set of test users
111     SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
112     USER_ADMIN = User.createUserForTesting(conf, "admin2", new String[0]);
113     USER_RW = User.createUserForTesting(conf, "rwuser", new String[0]);
114     USER_RO = User.createUserForTesting(conf, "rouser", new String[0]);
115     USER_OWNER = User.createUserForTesting(conf, "owner", new String[0]);
116     USER_CREATE = User.createUserForTesting(conf, "tbl_create", new String[0]);
117     USER_NONE = User.createUserForTesting(conf, "nouser", new String[0]);
118 
119     USER_GROUP_ADMIN =
120         User.createUserForTesting(conf, "user_group_admin", new String[] { GROUP_ADMIN });
121     USER_GROUP_CREATE =
122         User.createUserForTesting(conf, "user_group_create", new String[] { GROUP_CREATE });
123     USER_GROUP_READ =
124         User.createUserForTesting(conf, "user_group_read", new String[] { GROUP_READ });
125     USER_GROUP_WRITE =
126         User.createUserForTesting(conf, "user_group_write", new String[] { GROUP_WRITE });
127 
128     systemUserConnection = TEST_UTIL.getConnection();
129     setUpTableAndUserPermissions();
130   }
131 
132   private static void setUpTableAndUserPermissions() throws Exception {
133     HTableDescriptor htd = new HTableDescriptor(TEST_TABLE);
134     HColumnDescriptor hcd = new HColumnDescriptor(TEST_FAMILY);
135     hcd.setMaxVersions(100);
136     htd.addFamily(hcd);
137     htd.setOwner(USER_OWNER);
138     createTable(TEST_UTIL, htd, new byte[][] { Bytes.toBytes("s") });
139 
140     // Set up initial grants
141     grantGlobal(TEST_UTIL, USER_ADMIN.getShortName(),
142         Permission.Action.ADMIN,
143         Permission.Action.CREATE,
144         Permission.Action.READ,
145         Permission.Action.WRITE);
146 
147     grantOnTable(TEST_UTIL, USER_RW.getShortName(),
148         TEST_TABLE, TEST_FAMILY, null,
149         Permission.Action.READ,
150         Permission.Action.WRITE);
151 
152     // USER_CREATE is USER_RW plus CREATE permissions
153     grantOnTable(TEST_UTIL, USER_CREATE.getShortName(),
154         TEST_TABLE, null, null,
155         Permission.Action.CREATE,
156         Permission.Action.READ,
157         Permission.Action.WRITE);
158 
159     grantOnTable(TEST_UTIL, USER_RO.getShortName(),
160         TEST_TABLE, TEST_FAMILY, null,
161         Permission.Action.READ);
162 
163     grantGlobal(TEST_UTIL, toGroupEntry(GROUP_ADMIN), Permission.Action.ADMIN);
164     grantGlobal(TEST_UTIL, toGroupEntry(GROUP_CREATE), Permission.Action.CREATE);
165     grantGlobal(TEST_UTIL, toGroupEntry(GROUP_READ), Permission.Action.READ);
166     grantGlobal(TEST_UTIL, toGroupEntry(GROUP_WRITE), Permission.Action.WRITE);
167 
168     assertEquals(4, AccessControlLists.getTablePermissions(conf, TEST_TABLE).size());
169     try {
170       assertEquals(4, AccessControlClient.getUserPermissions(systemUserConnection,
171           TEST_TABLE.toString()).size());
172     } catch (Throwable e) {
173       LOG.error("error during call of AccessControlClient.getUserPermissions. ", e);
174     }
175   }
176 
177   private static void cleanUp() throws Exception {
178     // Clean the _acl_ table
179     try {
180       deleteTable(TEST_UTIL, TEST_TABLE);
181     } catch (TableNotFoundException ex) {
182       // Test deleted the table, no problem
183       LOG.info("Test deleted table " + TEST_TABLE);
184     }
185     // Verify all table/namespace permissions are erased
186     assertEquals(0, AccessControlLists.getTablePermissions(conf, TEST_TABLE).size());
187     assertEquals(0, AccessControlLists.getNamespacePermissions(conf,
188             TEST_TABLE.getNamespaceAsString()).size());
189   }
190 
191   @AfterClass
192   public static void tearDownAfterClass() throws Exception {
193     cleanUp();
194     TEST_UTIL.shutdownMiniCluster();
195     int total = TableAuthManager.getTotalRefCount();
196     assertTrue("Unexpected reference count: " + total, total == 0);
197   }
198 
199   private static void configureRSGroupAdminEndpoint(Configuration conf) {
200     String currentCoprocessors = conf.get(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY);
201     String coprocessors = RSGroupAdminEndpoint.class.getName();
202     if (currentCoprocessors != null) {
203       coprocessors += "," + currentCoprocessors;
204     }
205     conf.set(CoprocessorHost.MASTER_COPROCESSOR_CONF_KEY, coprocessors);
206     conf.set(HConstants.HBASE_MASTER_LOADBALANCER_CLASS,
207         RSGroupBasedLoadBalancer.class.getName());
208   }
209 
210   @Test
211   public void testGetRSGroupInfo() throws Exception {
212     AccessTestAction action = new AccessTestAction() {
213       @Override
214       public Object run() throws Exception {
215         rsGroupAdminEndpoint.checkPermission("getRSGroupInfo");
216         return null;
217       }
218     };
219 
220     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
221     verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO,
222         USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
223   }
224 
225   @Test
226   public void testGetRSGroupInfoOfTable() throws Exception {
227     AccessTestAction action = new AccessTestAction() {
228       @Override
229       public Object run() throws Exception {
230         rsGroupAdminEndpoint.checkPermission("getRSGroupInfoOfTable");
231         return null;
232       }
233     };
234 
235     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
236     verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO,
237         USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
238   }
239 
240   @Test
241   public void testMoveServers() throws Exception {
242     AccessTestAction action = new AccessTestAction() {
243       @Override
244       public Object run() throws Exception {
245         rsGroupAdminEndpoint.checkPermission("moveServers");
246         return null;
247       }
248     };
249 
250     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
251     verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO,
252         USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
253   }
254 
255   @Test
256   public void testMoveTables() throws Exception {
257     AccessTestAction action = new AccessTestAction() {
258       @Override
259       public Object run() throws Exception {
260         rsGroupAdminEndpoint.checkPermission("moveTables");
261         return null;
262       }
263     };
264 
265     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
266     verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO,
267         USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
268   }
269 
270   @Test
271   public void testAddRSGroup() throws Exception {
272     AccessTestAction action = new AccessTestAction() {
273       @Override
274       public Object run() throws Exception {
275         rsGroupAdminEndpoint.checkPermission("addRSGroup");
276         return null;
277       }
278     };
279 
280     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
281     verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO,
282         USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
283   }
284 
285   @Test
286   public void testRemoveRSGroup() throws Exception {
287     AccessTestAction action = new AccessTestAction() {
288       @Override
289       public Object run() throws Exception {
290         rsGroupAdminEndpoint.checkPermission("removeRSGroup");
291         return null;
292       }
293     };
294 
295     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
296     verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO,
297         USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
298   }
299 
300   @Test
301   public void testBalanceRSGroup() throws Exception {
302     AccessTestAction action = new AccessTestAction() {
303       @Override
304       public Object run() throws Exception {
305         rsGroupAdminEndpoint.checkPermission("balanceRSGroup");
306         return null;
307       }
308     };
309 
310     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
311     verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO,
312         USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
313   }
314 
315   @Test
316   public void testListRSGroup() throws Exception {
317     AccessTestAction action = new AccessTestAction() {
318       @Override
319       public Object run() throws Exception {
320         rsGroupAdminEndpoint.checkPermission("listRSGroup");
321         return null;
322       }
323     };
324 
325     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
326     verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO,
327         USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
328   }
329 
330   @Test
331   public void testGetRSGroupInfoOfServer() throws Exception {
332     AccessTestAction action = new AccessTestAction() {
333       @Override
334       public Object run() throws Exception {
335         rsGroupAdminEndpoint.checkPermission("getRSGroupInfoOfServer");
336         return null;
337       }
338     };
339 
340     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
341     verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO,
342         USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
343   }
344 
345   @Test
346   public void testMoveServersAndTables() throws Exception {
347     AccessTestAction action = new AccessTestAction() {
348       @Override
349       public Object run() throws Exception {
350         rsGroupAdminEndpoint.checkPermission("moveServersAndTables");
351         return null;
352       }
353     };
354 
355     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
356     verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO,
357         USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
358   }
359 
360   @Test
361   public void testRenameRSGroup() throws Exception {
362     AccessTestAction action = new AccessTestAction() {
363       @Override
364       public Object run() throws Exception {
365         rsGroupAdminEndpoint.checkPermission("renameRSGroup");
366         return null;
367       }
368     };
369 
370     verifyAllowed(action, SUPERUSER, USER_ADMIN, USER_GROUP_ADMIN);
371     verifyDenied(action, USER_CREATE, USER_OWNER, USER_RW, USER_RO,
372       USER_NONE, USER_GROUP_READ, USER_GROUP_WRITE, USER_GROUP_CREATE);
373   }
374 }