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