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  
19  package org.apache.hadoop.hbase.client;
20  
21  import org.apache.hadoop.conf.Configuration;
22  import org.apache.hadoop.hbase.Coprocessor;
23  import org.apache.hadoop.hbase.HBaseTestingUtility;
24  import org.apache.hadoop.hbase.HColumnDescriptor;
25  import org.apache.hadoop.hbase.HTableDescriptor;
26  import org.apache.hadoop.hbase.TableName;
27  import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
28  import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
29  import org.apache.hadoop.hbase.security.User;
30  import org.apache.hadoop.hbase.security.access.AccessControlConstants;
31  import org.apache.hadoop.hbase.security.access.AccessControlLists;
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.SecureTestUtil;
35  import org.apache.hadoop.hbase.testclassification.MediumTests;
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;
42  import org.junit.experimental.categories.Category;
43  
44  import java.io.IOException;
45  import java.util.UUID;
46  
47  @Category(MediumTests.class)
48  public class TestSnapshotWithAcl extends SecureTestUtil {
49  
50    public TableName TEST_TABLE = TableName.valueOf(UUID.randomUUID().toString());
51  
52    private static final int ROW_COUNT = 30000;
53  
54    private static byte[] TEST_FAMILY = Bytes.toBytes("f1");
55    private static byte[] TEST_QUALIFIER = Bytes.toBytes("cq");
56    private static byte[] TEST_ROW = Bytes.toBytes(0);
57    private static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
58    private static Configuration conf;
59    private static HBaseAdmin admin = null;
60  
61    // user is table owner. will have all permissions on table
62    private static User USER_OWNER;
63    // user with rw permissions on column family.
64    private static User USER_RW;
65    // user with read-only permissions
66    private static User USER_RO;
67    // user with none permissions
68    private static User USER_NONE;
69  
70    static class AccessReadAction implements AccessTestAction {
71  
72      private TableName tableName;
73  
74      public AccessReadAction(TableName tableName) {
75        this.tableName = tableName;
76      }
77  
78      @Override
79      public Object run() throws Exception {
80        Get g = new Get(TEST_ROW);
81        g.addFamily(TEST_FAMILY);
82        HTable t = new HTable(conf, tableName);
83        try {
84          t.get(g);
85        } finally {
86          t.close();
87        }
88        return null;
89      }
90    };
91  
92    static class AccessWriteAction implements AccessTestAction {
93      private TableName tableName;
94  
95      public AccessWriteAction(TableName tableName) {
96        this.tableName = tableName;
97      }
98  
99      @Override
100     public Object run() throws Exception {
101       Put p = new Put(TEST_ROW);
102       p.add(TEST_FAMILY, TEST_QUALIFIER, Bytes.toBytes(1));
103       HTable t = new HTable(conf, tableName);
104       try {
105         t.put(p);
106       } finally {
107         t.close();
108       }
109       return null;
110     }
111   }
112 
113   @BeforeClass
114   public static void setupBeforeClass() throws Exception {
115     conf = TEST_UTIL.getConfiguration();
116     // Enable security
117     enableSecurity(conf);
118     conf.set(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY, AccessController.class.getName());
119     // Verify enableSecurity sets up what we require
120     verifyConfiguration(conf);
121     // Enable EXEC permission checking
122     conf.setBoolean(AccessControlConstants.EXEC_PERMISSION_CHECKS_KEY, true);
123     TEST_UTIL.startMiniCluster();
124     TEST_UTIL.waitUntilAllRegionsAssigned(AccessControlLists.ACL_TABLE_NAME);
125     MasterCoprocessorHost cpHost =
126         TEST_UTIL.getMiniHBaseCluster().getMaster().getMasterCoprocessorHost();
127     cpHost.load(AccessController.class, Coprocessor.PRIORITY_HIGHEST, conf);
128 
129     USER_OWNER = User.createUserForTesting(conf, "owner", new String[0]);
130     USER_RW = User.createUserForTesting(conf, "rwuser", new String[0]);
131     USER_RO = User.createUserForTesting(conf, "rouser", new String[0]);
132     USER_NONE = User.createUserForTesting(conf, "usernone", new String[0]);
133   }
134 
135   @Before
136   public void setUp() throws Exception {
137     admin = TEST_UTIL.getHBaseAdmin();
138     HTableDescriptor htd = new HTableDescriptor(TEST_TABLE);
139     HColumnDescriptor hcd = new HColumnDescriptor(TEST_FAMILY);
140     hcd.setMaxVersions(100);
141     htd.addFamily(hcd);
142     htd.setOwner(USER_OWNER);
143     admin.createTable(htd, new byte[][] { Bytes.toBytes("s") });
144     TEST_UTIL.waitTableEnabled(TEST_TABLE);
145 
146     grantOnTable(TEST_UTIL, USER_RW.getShortName(), TEST_TABLE, TEST_FAMILY, null,
147       Permission.Action.READ, Permission.Action.WRITE);
148 
149     grantOnTable(TEST_UTIL, USER_RO.getShortName(), TEST_TABLE, TEST_FAMILY, null,
150       Permission.Action.READ);
151   }
152 
153   private void loadData() throws IOException {
154     HTable hTable = new HTable(conf, TEST_TABLE);
155     try {
156       for (int i = 0; i < ROW_COUNT; i++) {
157         Put put = new Put(Bytes.toBytes(i));
158         put.add(TEST_FAMILY, TEST_QUALIFIER, Bytes.toBytes(i));
159         hTable.put(put);
160       }
161       hTable.flushCommits();
162     } finally {
163       hTable.close();
164     }
165   }
166 
167   @AfterClass
168   public static void tearDownAfterClass() throws Exception {
169     TEST_UTIL.shutdownMiniCluster();
170   }
171 
172   private void verifyRows(TableName tableName) throws IOException {
173     HTable hTable = new HTable(conf, tableName);
174     try {
175       Scan scan = new Scan();
176       ResultScanner scanner = hTable.getScanner(scan);
177       Result result;
178       int rowCount = 0;
179       while ((result = scanner.next()) != null) {
180         byte[] value = result.getValue(TEST_FAMILY, TEST_QUALIFIER);
181         Assert.assertArrayEquals(value, Bytes.toBytes(rowCount++));
182       }
183       Assert.assertEquals(rowCount, ROW_COUNT);
184     } finally {
185       hTable.close();
186     }
187   }
188 
189   @Test
190   public void testRestoreSnapshot() throws Exception {
191     verifyAllowed(new AccessReadAction(TEST_TABLE), USER_OWNER, USER_RO, USER_RW);
192     verifyDenied(new AccessReadAction(TEST_TABLE), USER_NONE);
193     verifyAllowed(new AccessWriteAction(TEST_TABLE), USER_OWNER, USER_RW);
194     verifyDenied(new AccessWriteAction(TEST_TABLE), USER_RO, USER_NONE);
195 
196     loadData();
197     verifyRows(TEST_TABLE);
198 
199     String snapshotName1 = UUID.randomUUID().toString();
200     admin.snapshot(snapshotName1, TEST_TABLE);
201 
202     // clone snapshot with restoreAcl true.
203     TableName tableName1 = TableName.valueOf(UUID.randomUUID().toString());
204     admin.cloneSnapshot(snapshotName1, tableName1, true);
205     verifyRows(tableName1);
206     verifyAllowed(new AccessReadAction(tableName1), USER_OWNER, USER_RO, USER_RW);
207     verifyDenied(new AccessReadAction(tableName1), USER_NONE);
208     verifyAllowed(new AccessWriteAction(tableName1), USER_OWNER, USER_RW);
209     verifyDenied(new AccessWriteAction(tableName1), USER_RO, USER_NONE);
210 
211     // clone snapshot with restoreAcl false.
212     TableName tableName2 = TableName.valueOf(UUID.randomUUID().toString());
213     admin.cloneSnapshot(snapshotName1, tableName2, false);
214     verifyRows(tableName2);
215     verifyAllowed(new AccessReadAction(tableName2), USER_OWNER);
216     verifyDenied(new AccessReadAction(tableName2), USER_NONE, USER_RO, USER_RW);
217     verifyAllowed(new AccessWriteAction(tableName2), USER_OWNER);
218     verifyDenied(new AccessWriteAction(tableName2), USER_RO, USER_RW, USER_NONE);
219 
220     // remove read permission for USER_RO.
221     revokeFromTable(TEST_UTIL, USER_RO.getShortName(), TEST_TABLE, TEST_FAMILY, null,
222       Permission.Action.READ);
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);
227 
228     // restore snapshot with restoreAcl false.
229     admin.disableTable(TEST_TABLE);
230     admin.restoreSnapshot(snapshotName1, false, false);
231     admin.enableTable(TEST_TABLE);
232     verifyAllowed(new AccessReadAction(TEST_TABLE), USER_OWNER, USER_RW);
233     verifyDenied(new AccessReadAction(TEST_TABLE), USER_RO, USER_NONE);
234     verifyAllowed(new AccessWriteAction(TEST_TABLE), USER_OWNER, USER_RW);
235     verifyDenied(new AccessWriteAction(TEST_TABLE), USER_RO, USER_NONE);
236 
237     // restore snapshot with restoreAcl true.
238     admin.disableTable(TEST_TABLE);
239     admin.restoreSnapshot(snapshotName1, false, true);
240     admin.enableTable(TEST_TABLE);
241     verifyAllowed(new AccessReadAction(TEST_TABLE), USER_OWNER, USER_RO, USER_RW);
242     verifyDenied(new AccessReadAction(TEST_TABLE), USER_NONE);
243     verifyAllowed(new AccessWriteAction(TEST_TABLE), USER_OWNER, USER_RW);
244     verifyDenied(new AccessWriteAction(TEST_TABLE), USER_RO, USER_NONE);
245   }
246 }