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