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.visibility;
19  
20  import static org.apache.hadoop.hbase.security.visibility.VisibilityConstants.LABELS_TABLE_NAME;
21  import static org.junit.Assert.assertTrue;
22  
23  import java.io.IOException;
24  import java.security.PrivilegedExceptionAction;
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.HConstants;
30  import org.apache.hadoop.hbase.HTableDescriptor;
31  import org.apache.hadoop.hbase.testclassification.MediumTests;
32  import org.apache.hadoop.hbase.TableName;
33  import org.apache.hadoop.hbase.client.Admin;
34  import org.apache.hadoop.hbase.client.Append;
35  import org.apache.hadoop.hbase.client.Connection;
36  import org.apache.hadoop.hbase.client.ConnectionFactory;
37  import org.apache.hadoop.hbase.client.Put;
38  import org.apache.hadoop.hbase.client.Table;
39  import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsResponse;
40  import org.apache.hadoop.hbase.security.User;
41  import org.apache.hadoop.hbase.util.Bytes;
42  import org.junit.AfterClass;
43  import org.junit.Assert;
44  import org.junit.BeforeClass;
45  import org.junit.Rule;
46  import org.junit.Test;
47  import org.junit.experimental.categories.Category;
48  import org.junit.rules.TestName;
49  
50  @Category(MediumTests.class)
51  /**
52   * Test visibility by setting 'hbase.security.visibility.mutations.checkauths' to true
53   */
54  public class TestVisibilityWithCheckAuths {
55    private static final String TOPSECRET = "TOPSECRET";
56    private static final String PUBLIC = "PUBLIC";
57    public static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
58    private static final byte[] row1 = Bytes.toBytes("row1");
59    private final static byte[] fam = Bytes.toBytes("info");
60    private final static byte[] qual = Bytes.toBytes("qual");
61    private final static byte[] value = Bytes.toBytes("value");
62    public static Configuration conf;
63  
64    @Rule
65    public final TestName TEST_NAME = new TestName();
66    public static User SUPERUSER;
67    public static User USER;
68    @BeforeClass
69    public static void setupBeforeClass() throws Exception {
70      // setup configuration
71      conf = TEST_UTIL.getConfiguration();
72      conf.setBoolean(HConstants.DISTRIBUTED_LOG_REPLAY_KEY, false);
73      VisibilityTestUtil.enableVisiblityLabels(conf);
74      conf.setBoolean(VisibilityConstants.CHECK_AUTHS_FOR_MUTATION, true);
75      conf.setClass(VisibilityUtils.VISIBILITY_LABEL_GENERATOR_CLASS, SimpleScanLabelGenerator.class,
76          ScanLabelGenerator.class);
77      conf.set("hbase.superuser", "admin");
78      TEST_UTIL.startMiniCluster(2);
79      SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
80      USER = User.createUserForTesting(conf, "user", new String[]{});
81      // Wait for the labels table to become available
82      TEST_UTIL.waitTableEnabled(LABELS_TABLE_NAME.getName(), 50000);
83      addLabels();
84    }
85  
86    @AfterClass
87    public static void tearDownAfterClass() throws Exception {
88      TEST_UTIL.shutdownMiniCluster();
89    }
90  
91    public static void addLabels() throws Exception {
92      PrivilegedExceptionAction<VisibilityLabelsResponse> action =
93          new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
94        @Override
95        public VisibilityLabelsResponse run() throws Exception {
96          String[] labels = { TOPSECRET };
97          try {
98            VisibilityClient.addLabels(conf, labels);
99          } catch (Throwable t) {
100           throw new IOException(t);
101         }
102         return null;
103       }
104     };
105     SUPERUSER.runAs(action);
106   }
107 
108   @Test
109   public void testVerifyAccessDeniedForInvalidUserAuths() throws Exception {
110     PrivilegedExceptionAction<VisibilityLabelsResponse> action =
111         new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
112       @Override
113       public VisibilityLabelsResponse run() throws Exception {
114         try {
115           return VisibilityClient.setAuths(conf, new String[] { TOPSECRET },
116               USER.getShortName());
117         } catch (Throwable e) {
118         }
119         return null;
120       }
121     };
122     SUPERUSER.runAs(action);
123     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
124     Admin hBaseAdmin = TEST_UTIL.getHBaseAdmin();
125     HColumnDescriptor colDesc = new HColumnDescriptor(fam);
126     colDesc.setMaxVersions(5);
127     HTableDescriptor desc = new HTableDescriptor(tableName);
128     desc.addFamily(colDesc);
129     hBaseAdmin.createTable(desc);
130     try {
131       TEST_UTIL.getHBaseAdmin().flush(tableName);
132       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
133         @Override
134         public Void run() throws Exception {
135           try (Connection connection = ConnectionFactory.createConnection(conf);
136                Table table = connection.getTable(tableName)) {
137             Put p = new Put(row1);
138             p.setCellVisibility(new CellVisibility(PUBLIC + "&" + TOPSECRET));
139             p.add(fam, qual, 125l, value);
140             table.put(p);
141             Assert.fail("Testcase should fail with AccesDeniedException");
142           } catch (Throwable t) {
143             assertTrue(t.getMessage().contains("AccessDeniedException"));
144           }
145           return null;
146         }
147       };
148       USER.runAs(actiona);
149     } catch (Exception e) {
150       throw new IOException(e);
151     }
152   }
153 
154   @Test
155   public void testLabelsWithAppend() throws Throwable {
156     PrivilegedExceptionAction<VisibilityLabelsResponse> action =
157         new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
158       @Override
159       public VisibilityLabelsResponse run() throws Exception {
160         try {
161           return VisibilityClient.setAuths(conf, new String[] { TOPSECRET },
162               USER.getShortName());
163         } catch (Throwable e) {
164         }
165         return null;
166       }
167     };
168     SUPERUSER.runAs(action);
169     final TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
170     try (Table table = TEST_UTIL.createTable(tableName, fam)) {
171       final byte[] row1 = Bytes.toBytes("row1");
172       final byte[] val = Bytes.toBytes("a");
173       PrivilegedExceptionAction<Void> actiona = new PrivilegedExceptionAction<Void>() {
174         @Override
175         public Void run() throws Exception {
176           try (Connection connection = ConnectionFactory.createConnection(conf);
177                Table table = connection.getTable(tableName)) {
178             Put put = new Put(row1);
179             put.add(fam, qual, HConstants.LATEST_TIMESTAMP, val);
180             put.setCellVisibility(new CellVisibility(TOPSECRET));
181             table.put(put);
182           }
183           return null;
184         }
185       };
186       USER.runAs(actiona);
187       actiona = new PrivilegedExceptionAction<Void>() {
188         @Override
189         public Void run() throws Exception {
190           try (Connection connection = ConnectionFactory.createConnection(conf);
191                Table table = connection.getTable(tableName)) {
192             Append append = new Append(row1);
193             append.add(fam, qual, Bytes.toBytes("b"));
194             table.append(append);
195           }
196           return null;
197         }
198       };
199       USER.runAs(actiona);
200       actiona = new PrivilegedExceptionAction<Void>() {
201         @Override
202         public Void run() throws Exception {
203           try (Connection connection = ConnectionFactory.createConnection(conf);
204                Table table = connection.getTable(tableName)) {
205             Append append = new Append(row1);
206             append.add(fam, qual, Bytes.toBytes("c"));
207             append.setCellVisibility(new CellVisibility(PUBLIC));
208             table.append(append);
209             Assert.fail("Testcase should fail with AccesDeniedException");
210           } catch (Throwable t) {
211             assertTrue(t.getMessage().contains("AccessDeniedException"));
212           }
213           return null;
214         }
215       };
216       USER.runAs(actiona);
217     }
218   }
219 }