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, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.security.access;
19  
20  import static org.junit.Assert.assertFalse;
21  import static org.junit.Assert.assertNotNull;
22  import static org.junit.Assert.assertTrue;
23  
24  import java.util.List;
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.HTableDescriptor;
30  import org.apache.hadoop.hbase.testclassification.LargeTests;
31  import org.apache.hadoop.hbase.client.Admin;
32  import org.apache.hadoop.hbase.client.Connection;
33  import org.apache.hadoop.hbase.client.ConnectionFactory;
34  import org.apache.hadoop.hbase.client.HTable;
35  import org.apache.hadoop.hbase.client.Put;
36  import org.apache.hadoop.hbase.client.Result;
37  import org.apache.hadoop.hbase.client.ResultScanner;
38  import org.apache.hadoop.hbase.client.Scan;
39  import org.apache.hadoop.hbase.security.User;
40  import org.apache.hadoop.hbase.security.access.Permission.Action;
41  import org.apache.hadoop.hbase.util.Bytes;
42  import org.apache.hadoop.hbase.util.TestTableName;
43  import org.junit.AfterClass;
44  import org.junit.BeforeClass;
45  import org.junit.Rule;
46  import org.junit.Test;
47  import org.junit.experimental.categories.Category;
48  
49  @Category(LargeTests.class)
50  public class TestAccessController2 extends SecureTestUtil {
51  
52    private static final byte[] TEST_ROW = Bytes.toBytes("test");
53    private static final byte[] TEST_FAMILY = Bytes.toBytes("f");
54    private static final byte[] TEST_QUALIFIER = Bytes.toBytes("q");
55    private static final byte[] TEST_VALUE = Bytes.toBytes("value");
56  
57    private static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
58    private static Configuration conf;
59  
60    @Rule public TestTableName TEST_TABLE = new TestTableName();
61  
62    @BeforeClass
63    public static void setupBeforeClass() throws Exception {
64      conf = TEST_UTIL.getConfiguration();
65      // Enable security
66      enableSecurity(conf);
67      // Verify enableSecurity sets up what we require
68      verifyConfiguration(conf);
69      TEST_UTIL.startMiniCluster();
70      // Wait for the ACL table to become available
71      TEST_UTIL.waitTableEnabled(AccessControlLists.ACL_TABLE_NAME);
72    }
73  
74    @AfterClass
75    public static void tearDownAfterClass() throws Exception {
76      TEST_UTIL.shutdownMiniCluster();
77    }
78  
79    @Test
80    public void testCreateWithCorrectOwner() throws Exception {
81      // Create a test user
82      final User testUser = User.createUserForTesting(TEST_UTIL.getConfiguration(), "TestUser",
83        new String[0]);
84      // Grant the test user the ability to create tables
85      SecureTestUtil.grantGlobal(TEST_UTIL, testUser.getShortName(), Action.CREATE);
86      verifyAllowed(new AccessTestAction() {
87        @Override
88        public Object run() throws Exception {
89          HTableDescriptor desc = new HTableDescriptor(TEST_TABLE.getTableName());
90          desc.addFamily(new HColumnDescriptor(TEST_FAMILY));
91          try (Connection connection =
92              ConnectionFactory.createConnection(TEST_UTIL.getConfiguration(), testUser)) {
93            try (Admin admin = connection.getAdmin()) {
94              admin.createTable(desc);
95            }
96          }
97          return null;
98        }
99      }, testUser);
100     TEST_UTIL.waitTableEnabled(TEST_TABLE.getTableName());
101     // Verify that owner permissions have been granted to the test user on the
102     // table just created
103     List<TablePermission> perms =
104       AccessControlLists.getTablePermissions(conf, TEST_TABLE.getTableName())
105        .get(testUser.getShortName());
106     assertNotNull(perms);
107     assertFalse(perms.isEmpty());
108     // Should be RWXCA
109     assertTrue(perms.get(0).implies(Permission.Action.READ));
110     assertTrue(perms.get(0).implies(Permission.Action.WRITE));
111     assertTrue(perms.get(0).implies(Permission.Action.EXEC));
112     assertTrue(perms.get(0).implies(Permission.Action.CREATE));
113     assertTrue(perms.get(0).implies(Permission.Action.ADMIN));
114   }
115 
116   @Test
117   public void testACLTableAccess() throws Exception {
118     final Configuration conf = TEST_UTIL.getConfiguration();
119 
120     // Superuser
121     User superUser = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
122 
123     // Global users
124     User globalRead = User.createUserForTesting(conf, "globalRead", new String[0]);
125     User globalWrite = User.createUserForTesting(conf, "globalWrite", new String[0]);
126     User globalCreate = User.createUserForTesting(conf, "globalCreate", new String[0]);
127     User globalAdmin = User.createUserForTesting(conf, "globalAdmin", new String[0]);
128     SecureTestUtil.grantGlobal(TEST_UTIL, globalRead.getShortName(), Action.READ);
129     SecureTestUtil.grantGlobal(TEST_UTIL, globalWrite.getShortName(), Action.WRITE);
130     SecureTestUtil.grantGlobal(TEST_UTIL, globalCreate.getShortName(), Action.CREATE);
131     SecureTestUtil.grantGlobal(TEST_UTIL, globalAdmin.getShortName(), Action.ADMIN);
132 
133     // Namespace users
134     User nsRead = User.createUserForTesting(conf, "nsRead", new String[0]);
135     User nsWrite = User.createUserForTesting(conf, "nsWrite", new String[0]);
136     User nsCreate = User.createUserForTesting(conf, "nsCreate", new String[0]);
137     User nsAdmin = User.createUserForTesting(conf, "nsAdmin", new String[0]);
138     SecureTestUtil.grantOnNamespace(TEST_UTIL, nsRead.getShortName(),
139       TEST_TABLE.getTableName().getNamespaceAsString(), Action.READ);
140     SecureTestUtil.grantOnNamespace(TEST_UTIL, nsWrite.getShortName(),
141       TEST_TABLE.getTableName().getNamespaceAsString(), Action.WRITE);
142     SecureTestUtil.grantOnNamespace(TEST_UTIL, nsCreate.getShortName(),
143       TEST_TABLE.getTableName().getNamespaceAsString(), Action.CREATE);
144     SecureTestUtil.grantOnNamespace(TEST_UTIL, nsAdmin.getShortName(),
145       TEST_TABLE.getTableName().getNamespaceAsString(), Action.ADMIN);
146 
147     // Table users
148     User tableRead = User.createUserForTesting(conf, "tableRead", new String[0]);
149     User tableWrite = User.createUserForTesting(conf, "tableWrite", new String[0]);
150     User tableCreate = User.createUserForTesting(conf, "tableCreate", new String[0]);
151     User tableAdmin = User.createUserForTesting(conf, "tableAdmin", new String[0]);
152     SecureTestUtil.grantOnTable(TEST_UTIL, tableRead.getShortName(),
153       TEST_TABLE.getTableName(), null, null, Action.READ);
154     SecureTestUtil.grantOnTable(TEST_UTIL, tableWrite.getShortName(),
155       TEST_TABLE.getTableName(), null, null, Action.WRITE);
156     SecureTestUtil.grantOnTable(TEST_UTIL, tableCreate.getShortName(),
157       TEST_TABLE.getTableName(), null, null, Action.CREATE);
158     SecureTestUtil.grantOnTable(TEST_UTIL, tableAdmin.getShortName(),
159       TEST_TABLE.getTableName(), null, null, Action.ADMIN);
160 
161     // Write tests
162 
163     AccessTestAction writeAction = new AccessTestAction() {
164       @Override
165       public Object run() throws Exception {
166         HTable t = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
167         try {
168           t.put(new Put(TEST_ROW).add(AccessControlLists.ACL_LIST_FAMILY, TEST_QUALIFIER,
169             TEST_VALUE));
170           return null;
171         } finally {
172           t.close();
173         }
174       }
175     };
176 
177     // All writes to ACL table denied except for GLOBAL WRITE permission and superuser
178 
179     verifyDenied(writeAction, globalAdmin, globalCreate, globalRead);
180     verifyDenied(writeAction, nsAdmin, nsCreate, nsRead, nsWrite);
181     verifyDenied(writeAction, tableAdmin, tableCreate, tableRead, tableWrite);
182     verifyAllowed(writeAction, superUser, globalWrite);
183 
184     // Read tests
185 
186     AccessTestAction scanAction = new AccessTestAction() {
187       @Override
188       public Object run() throws Exception {
189         HTable t = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
190         try {
191           ResultScanner s = t.getScanner(new Scan());
192           try {
193             for (Result r = s.next(); r != null; r = s.next()) {
194               // do nothing
195             }
196           } finally {
197             s.close();
198           }
199           return null;
200         } finally {
201           t.close();
202         }
203       }
204     };
205 
206     // All reads from ACL table denied except for GLOBAL READ and superuser
207 
208     verifyDenied(scanAction, globalAdmin, globalCreate, globalWrite);
209     verifyDenied(scanAction, nsCreate, nsAdmin, nsRead, nsWrite);
210     verifyDenied(scanAction, tableCreate, tableAdmin, tableRead, tableWrite);
211     verifyAllowed(scanAction, superUser, globalRead);
212   }
213 
214 }