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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 package org
.apache
.hadoop
.hbase
.client
;
20 import java
.io
.IOException
;
21 import java
.util
.List
;
22 import java
.util
.regex
.Pattern
;
23 import org
.apache
.hadoop
.conf
.Configuration
;
24 import org
.apache
.hadoop
.hbase
.Coprocessor
;
25 import org
.apache
.hadoop
.hbase
.HBaseCommonTestingUtil
;
26 import org
.apache
.hadoop
.hbase
.HBaseTestingUtil
;
27 import org
.apache
.hadoop
.hbase
.TableName
;
28 import org
.apache
.hadoop
.hbase
.coprocessor
.CoprocessorHost
;
29 import org
.apache
.hadoop
.hbase
.master
.MasterCoprocessorHost
;
30 import org
.apache
.hadoop
.hbase
.security
.User
;
31 import org
.apache
.hadoop
.hbase
.security
.access
.AccessControlConstants
;
32 import org
.apache
.hadoop
.hbase
.security
.access
.AccessController
;
33 import org
.apache
.hadoop
.hbase
.security
.access
.Permission
;
34 import org
.apache
.hadoop
.hbase
.security
.access
.PermissionStorage
;
35 import org
.apache
.hadoop
.hbase
.security
.access
.SecureTestUtil
;
36 import org
.apache
.hadoop
.hbase
.util
.Bytes
;
37 import org
.junit
.AfterClass
;
38 import org
.junit
.Assert
;
39 import org
.junit
.Before
;
40 import org
.junit
.BeforeClass
;
41 import org
.junit
.Test
;
43 public abstract class SnapshotWithAclTestBase
extends SecureTestUtil
{
45 private TableName TEST_TABLE
= TableName
.valueOf(TEST_UTIL
.getRandomUUID().toString());
47 private static final int ROW_COUNT
= 30000;
49 private static byte[] TEST_FAMILY
= Bytes
.toBytes("f1");
50 private static byte[] TEST_QUALIFIER
= Bytes
.toBytes("cq");
51 private static byte[] TEST_ROW
= Bytes
.toBytes(0);
53 protected static HBaseTestingUtil TEST_UTIL
= new HBaseTestingUtil();
55 // user is table owner. will have all permissions on table
56 private static User USER_OWNER
;
57 // user with rw permissions on column family.
58 private static User USER_RW
;
59 // user with read-only permissions
60 private static User USER_RO
;
61 // user with none permissions
62 private static User USER_NONE
;
64 static class AccessReadAction
implements AccessTestAction
{
66 private TableName tableName
;
68 public AccessReadAction(TableName tableName
) {
69 this.tableName
= tableName
;
73 public Object
run() throws Exception
{
74 Get g
= new Get(TEST_ROW
);
75 g
.addFamily(TEST_FAMILY
);
76 try (Connection conn
= ConnectionFactory
.createConnection(TEST_UTIL
.getConfiguration());
77 Table t
= conn
.getTable(tableName
)) {
84 static class AccessWriteAction
implements AccessTestAction
{
85 private TableName tableName
;
87 public AccessWriteAction(TableName tableName
) {
88 this.tableName
= tableName
;
92 public Object
run() throws Exception
{
93 Put p
= new Put(TEST_ROW
);
94 p
.addColumn(TEST_FAMILY
, TEST_QUALIFIER
, Bytes
.toBytes(0));
95 try (Connection conn
= ConnectionFactory
.createConnection(TEST_UTIL
.getConfiguration());
96 Table t
= conn
.getTable(tableName
)) {
104 public static void setupBeforeClass() throws Exception
{
105 Configuration conf
= TEST_UTIL
.getConfiguration();
107 enableSecurity(conf
);
108 conf
.set(CoprocessorHost
.REGION_COPROCESSOR_CONF_KEY
, AccessController
.class.getName());
109 // Verify enableSecurity sets up what we require
110 verifyConfiguration(conf
);
111 // Enable EXEC permission checking
112 conf
.setBoolean(AccessControlConstants
.EXEC_PERMISSION_CHECKS_KEY
, true);
113 TEST_UTIL
.startMiniCluster();
114 TEST_UTIL
.waitUntilAllRegionsAssigned(PermissionStorage
.ACL_TABLE_NAME
);
115 MasterCoprocessorHost cpHost
=
116 TEST_UTIL
.getMiniHBaseCluster().getMaster().getMasterCoprocessorHost();
117 cpHost
.load(AccessController
.class, Coprocessor
.PRIORITY_HIGHEST
, conf
);
119 USER_OWNER
= User
.createUserForTesting(conf
, "owner", new String
[0]);
120 USER_RW
= User
.createUserForTesting(conf
, "rwuser", new String
[0]);
121 USER_RO
= User
.createUserForTesting(conf
, "rouser", new String
[0]);
122 USER_NONE
= User
.createUserForTesting(conf
, "usernone", new String
[0]);
124 // Grant table creation permission to USER_OWNER
125 grantGlobal(TEST_UTIL
, USER_OWNER
.getShortName(), Permission
.Action
.CREATE
);
129 public void setUp() throws Exception
{
130 TableDescriptor tableDescriptor
= TableDescriptorBuilder
.newBuilder(TEST_TABLE
)
132 ColumnFamilyDescriptorBuilder
.newBuilder(TEST_FAMILY
).setMaxVersions(100).build()).build();
133 createTable(TEST_UTIL
, USER_OWNER
, tableDescriptor
, new byte[][] { Bytes
.toBytes("s") });
134 TEST_UTIL
.waitTableEnabled(TEST_TABLE
);
136 grantOnTable(TEST_UTIL
, USER_RW
.getShortName(), TEST_TABLE
, TEST_FAMILY
, null,
137 Permission
.Action
.READ
, Permission
.Action
.WRITE
);
139 grantOnTable(TEST_UTIL
, USER_RO
.getShortName(), TEST_TABLE
, TEST_FAMILY
, null,
140 Permission
.Action
.READ
);
143 private void loadData() throws IOException
{
144 try (Connection conn
= ConnectionFactory
.createConnection(TEST_UTIL
.getConfiguration())) {
145 try (Table t
= conn
.getTable(TEST_TABLE
)) {
146 for (int i
= 0; i
< ROW_COUNT
; i
++) {
147 Put put
= new Put(Bytes
.toBytes(i
));
148 put
.addColumn(TEST_FAMILY
, TEST_QUALIFIER
, Bytes
.toBytes(i
));
156 public static void tearDownAfterClass() throws Exception
{
157 TEST_UTIL
.shutdownMiniCluster();
160 private void verifyRows(TableName tableName
) throws IOException
{
161 try (Connection conn
= ConnectionFactory
.createConnection(TEST_UTIL
.getConfiguration());
162 Table t
= conn
.getTable(tableName
); ResultScanner scanner
= t
.getScanner(new Scan())) {
165 while ((result
= scanner
.next()) != null) {
166 byte[] value
= result
.getValue(TEST_FAMILY
, TEST_QUALIFIER
);
167 Assert
.assertArrayEquals(value
, Bytes
.toBytes(rowCount
++));
169 Assert
.assertEquals(ROW_COUNT
, rowCount
);
173 protected abstract void snapshot(String snapshotName
, TableName tableName
) throws Exception
;
175 protected abstract void cloneSnapshot(String snapshotName
, TableName tableName
,
176 boolean restoreAcl
) throws Exception
;
178 protected abstract void restoreSnapshot(String snapshotName
, boolean restoreAcl
) throws Exception
;
181 public void testRestoreSnapshot() throws Exception
{
182 verifyAllowed(new AccessReadAction(TEST_TABLE
), USER_OWNER
, USER_RO
, USER_RW
);
183 verifyDenied(new AccessReadAction(TEST_TABLE
), USER_NONE
);
184 verifyAllowed(new AccessWriteAction(TEST_TABLE
), USER_OWNER
, USER_RW
);
185 verifyDenied(new AccessWriteAction(TEST_TABLE
), USER_RO
, USER_NONE
);
188 verifyRows(TEST_TABLE
);
190 String snapshotName1
= TEST_UTIL
.getRandomUUID().toString();
191 snapshot(snapshotName1
, TEST_TABLE
);
193 // clone snapshot with restoreAcl true.
194 TableName tableName1
= TableName
.valueOf(TEST_UTIL
.getRandomUUID().toString());
195 cloneSnapshot(snapshotName1
, tableName1
, true);
196 verifyRows(tableName1
);
197 verifyAllowed(new AccessReadAction(tableName1
), USER_OWNER
, USER_RO
, USER_RW
);
198 verifyDenied(new AccessReadAction(tableName1
), USER_NONE
);
199 verifyAllowed(new AccessWriteAction(tableName1
), USER_OWNER
, USER_RW
);
200 verifyDenied(new AccessWriteAction(tableName1
), USER_RO
, USER_NONE
);
202 // clone snapshot with restoreAcl false.
203 TableName tableName2
= TableName
.valueOf(TEST_UTIL
.getRandomUUID().toString());
204 cloneSnapshot(snapshotName1
, tableName2
, false);
205 verifyRows(tableName2
);
206 verifyDenied(new AccessReadAction(tableName2
), USER_OWNER
);
207 verifyDenied(new AccessReadAction(tableName2
), USER_NONE
, USER_RO
, USER_RW
);
208 verifyDenied(new AccessWriteAction(tableName2
), USER_OWNER
);
209 verifyDenied(new AccessWriteAction(tableName2
), USER_RO
, USER_RW
, USER_NONE
);
211 // remove read permission for USER_RO.
212 revokeFromTable(TEST_UTIL
, USER_RO
.getShortName(), TEST_TABLE
, TEST_FAMILY
, null,
213 Permission
.Action
.READ
);
214 verifyAllowed(new AccessReadAction(TEST_TABLE
), USER_OWNER
, USER_RW
);
215 verifyDenied(new AccessReadAction(TEST_TABLE
), USER_RO
, USER_NONE
);
216 verifyAllowed(new AccessWriteAction(TEST_TABLE
), USER_OWNER
, USER_RW
);
217 verifyDenied(new AccessWriteAction(TEST_TABLE
), USER_RO
, USER_NONE
);
219 // restore snapshot with restoreAcl false.
220 TEST_UTIL
.getAdmin().disableTable(TEST_TABLE
);
221 restoreSnapshot(snapshotName1
, false);
222 TEST_UTIL
.getAdmin().enableTable(TEST_TABLE
);
223 verifyAllowed(new AccessReadAction(TEST_TABLE
), USER_OWNER
, USER_RW
);
224 verifyDenied(new AccessReadAction(TEST_TABLE
), USER_RO
, USER_NONE
);
225 verifyAllowed(new AccessWriteAction(TEST_TABLE
), USER_OWNER
, USER_RW
);
226 verifyDenied(new AccessWriteAction(TEST_TABLE
), USER_RO
, USER_NONE
);
228 // restore snapshot with restoreAcl true.
229 TEST_UTIL
.getAdmin().disableTable(TEST_TABLE
);
230 restoreSnapshot(snapshotName1
, true);
231 TEST_UTIL
.getAdmin().enableTable(TEST_TABLE
);
232 verifyAllowed(new AccessReadAction(TEST_TABLE
), USER_OWNER
, USER_RO
, USER_RW
);
233 verifyDenied(new AccessReadAction(TEST_TABLE
), USER_NONE
);
234 verifyAllowed(new AccessWriteAction(TEST_TABLE
), USER_OWNER
, USER_RW
);
235 verifyDenied(new AccessWriteAction(TEST_TABLE
), USER_RO
, USER_NONE
);
239 final class AccessSnapshotAction
implements AccessTestAction
{
240 private String snapshotName
;
241 private AccessSnapshotAction(String snapshotName
) {
242 this.snapshotName
= snapshotName
;
245 public Object
run() throws Exception
{
246 try (Connection conn
= ConnectionFactory
.createConnection(TEST_UTIL
.getConfiguration());
247 Admin admin
= conn
.getAdmin()) {
248 admin
.snapshot(this.snapshotName
, TEST_TABLE
);
255 public void testDeleteSnapshot() throws Exception
{
256 String testSnapshotName
= HBaseCommonTestingUtil
.getRandomUUID().toString();
257 verifyAllowed(new AccessSnapshotAction(testSnapshotName
), USER_OWNER
);
258 verifyDenied(new AccessSnapshotAction(HBaseCommonTestingUtil
.getRandomUUID().toString()),
259 USER_RO
, USER_RW
, USER_NONE
);
260 List
<SnapshotDescription
> snapshotDescriptions
= TEST_UTIL
.getAdmin().listSnapshots(
261 Pattern
.compile(testSnapshotName
));
262 Assert
.assertEquals(1, snapshotDescriptions
.size());
263 Assert
.assertEquals(USER_OWNER
.getShortName(), snapshotDescriptions
.get(0).getOwner());
264 AccessTestAction deleteSnapshotAction
= () -> {
265 try (Connection conn
= ConnectionFactory
.createConnection(TEST_UTIL
.getConfiguration());
266 Admin admin
= conn
.getAdmin()) {
267 admin
.deleteSnapshot(testSnapshotName
);
271 verifyDenied(deleteSnapshotAction
, USER_RO
, USER_RW
, USER_NONE
);
272 verifyAllowed(deleteSnapshotAction
, USER_OWNER
);
274 List
<SnapshotDescription
> snapshotsAfterDelete
= TEST_UTIL
.getAdmin().listSnapshots(
275 Pattern
.compile(testSnapshotName
));
276 Assert
.assertEquals(0, snapshotsAfterDelete
.size());