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.assertEquals;
22  import static org.junit.Assert.assertTrue;
23  import static org.junit.Assert.fail;
24  
25  import java.io.IOException;
26  import java.security.PrivilegedExceptionAction;
27  import java.util.List;
28  import java.util.concurrent.atomic.AtomicBoolean;
29  
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  import org.apache.hadoop.hbase.HConstants;
33  import org.apache.hadoop.hbase.MediumTests;
34  import org.apache.hadoop.hbase.client.HTable;
35  import org.apache.hadoop.hbase.client.Result;
36  import org.apache.hadoop.hbase.client.ResultScanner;
37  import org.apache.hadoop.hbase.client.Scan;
38  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
39  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.RegionActionResult;
40  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ResultOrException;
41  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.NameBytesPair;
42  import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsResponse;
43  import org.apache.hadoop.hbase.security.User;
44  import org.apache.hadoop.hbase.util.Bytes;
45  import org.apache.hadoop.hbase.util.JVMClusterUtil.RegionServerThread;
46  import org.apache.hadoop.hbase.util.Threads;
47  import org.junit.Assert;
48  import org.junit.BeforeClass;
49  import org.junit.Test;
50  import org.junit.experimental.categories.Category;
51  
52  @Category(MediumTests.class)
53  public class TestVisibilityLabelsWithDefaultVisLabelService extends TestVisibilityLabels {
54    final Log LOG = LogFactory.getLog(getClass());
55  
56    @BeforeClass
57    public static void setupBeforeClass() throws Exception {
58      // setup configuration
59      conf = TEST_UTIL.getConfiguration();
60      conf.setBoolean(HConstants.DISTRIBUTED_LOG_REPLAY_KEY, false);
61      conf.setBoolean("hbase.online.schema.update.enable", true);
62      VisibilityTestUtil.enableVisiblityLabels(conf);
63      conf.setClass(VisibilityUtils.VISIBILITY_LABEL_GENERATOR_CLASS, SimpleScanLabelGenerator.class,
64          ScanLabelGenerator.class);
65      conf.set("hbase.superuser", "admin");
66      TEST_UTIL.startMiniCluster(2);
67      SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
68      USER1 = User.createUserForTesting(conf, "user1", new String[] {});
69  
70      // Wait for the labels table to become available
71      TEST_UTIL.waitTableEnabled(LABELS_TABLE_NAME.getName(), 50000);
72      addLabels();
73    }
74  
75    @Test
76    public void testAddLabels() throws Throwable {
77      PrivilegedExceptionAction<VisibilityLabelsResponse> action =
78          new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
79        public VisibilityLabelsResponse run() throws Exception {
80          String[] labels = { "L1", SECRET, "L2", "invalid~", "L3" };
81          VisibilityLabelsResponse response = null;
82          try {
83            response = VisibilityClient.addLabels(conf, labels);
84          } catch (Throwable e) {
85            fail("Should not have thrown exception");
86          }
87          List<RegionActionResult> resultList = response.getResultList();
88          assertEquals(5, resultList.size());
89          assertTrue(resultList.get(0).getException().getValue().isEmpty());
90          assertEquals("org.apache.hadoop.hbase.DoNotRetryIOException", resultList.get(1)
91              .getException().getName());
92          assertTrue(Bytes.toString(resultList.get(1).getException().getValue().toByteArray())
93              .contains(
94                  "org.apache.hadoop.hbase.security.visibility.LabelAlreadyExistsException: "
95                      + "Label 'secret' already exists"));
96          assertTrue(resultList.get(2).getException().getValue().isEmpty());
97          assertTrue(resultList.get(3).getException().getValue().isEmpty());
98          assertTrue(resultList.get(4).getException().getValue().isEmpty());
99          return null;
100       }
101     };
102     SUPERUSER.runAs(action);
103   }
104 
105   @Test(timeout = 60 * 1000)
106   public void testAddVisibilityLabelsOnRSRestart() throws Exception {
107     List<RegionServerThread> regionServerThreads = TEST_UTIL.getHBaseCluster()
108         .getRegionServerThreads();
109     for (RegionServerThread rsThread : regionServerThreads) {
110       rsThread.getRegionServer().abort("Aborting ");
111     }
112     // Start one new RS
113     RegionServerThread rs = TEST_UTIL.getHBaseCluster().startRegionServer();
114     waitForLabelsRegionAvailability(rs.getRegionServer());
115     final AtomicBoolean vcInitialized = new AtomicBoolean(true);
116     do {
117       PrivilegedExceptionAction<VisibilityLabelsResponse> action =
118           new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
119         public VisibilityLabelsResponse run() throws Exception {
120           String[] labels = { SECRET, CONFIDENTIAL, PRIVATE, "ABC", "XYZ" };
121           try {
122             VisibilityLabelsResponse resp = VisibilityClient.addLabels(conf, labels);
123             List<RegionActionResult> results = resp.getResultList();
124             if (results.get(0).hasException()) {
125               NameBytesPair pair = results.get(0).getException();
126               Throwable t = ProtobufUtil.toException(pair);
127               LOG.debug("Got exception writing labels", t);
128               if (t instanceof VisibilityControllerNotReadyException) {
129                 vcInitialized.set(false);
130                 LOG.warn("VisibilityController was not yet initialized");
131                 Threads.sleep(10);
132               }
133             } else LOG.debug("new labels added: " + resp);
134           } catch (Throwable t) {
135             throw new IOException(t);
136           }
137           return null;
138         }
139       };
140       SUPERUSER.runAs(action);
141     } while (!vcInitialized.get());
142     // Scan the visibility label
143     Scan s = new Scan();
144     s.setAuthorizations(new Authorizations(VisibilityUtils.SYSTEM_LABEL));
145     HTable ht = new HTable(conf, LABELS_TABLE_NAME.getName());
146     int i = 0;
147     try {
148       ResultScanner scanner = ht.getScanner(s);
149       while (true) {
150         Result next = scanner.next();
151         if (next == null) {
152           break;
153         }
154         i++;
155       }
156     } finally {
157       if (ht != null) {
158         ht.close();
159       }
160     }
161     // One label is the "system" label.
162     Assert.assertEquals("The count should be 13", 13, i);
163   }
164 }