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.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertNull;
23 import static org.junit.Assert.assertTrue;
24
25 import java.io.IOException;
26 import java.security.PrivilegedExceptionAction;
27 import java.util.ArrayList;
28 import java.util.List;
29
30 import org.apache.hadoop.conf.Configuration;
31 import org.apache.hadoop.hbase.HBaseTestingUtility;
32 import org.apache.hadoop.hbase.HConstants;
33 import org.apache.hadoop.hbase.testclassification.MediumTests;
34 import org.apache.hadoop.hbase.TableName;
35 import org.apache.hadoop.hbase.client.Get;
36 import org.apache.hadoop.hbase.client.HTable;
37 import org.apache.hadoop.hbase.client.Put;
38 import org.apache.hadoop.hbase.client.Result;
39 import org.apache.hadoop.hbase.client.ResultScanner;
40 import org.apache.hadoop.hbase.client.Scan;
41 import org.apache.hadoop.hbase.client.Table;
42 import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.GetAuthsResponse;
43 import org.apache.hadoop.hbase.protobuf.generated.VisibilityLabelsProtos.VisibilityLabelsResponse;
44 import org.apache.hadoop.hbase.security.User;
45 import org.apache.hadoop.hbase.security.access.AccessControlLists;
46 import org.apache.hadoop.hbase.security.access.AccessController;
47 import org.apache.hadoop.hbase.security.access.Permission;
48 import org.apache.hadoop.hbase.security.access.SecureTestUtil;
49 import org.apache.hadoop.hbase.util.Bytes;
50 import org.junit.AfterClass;
51 import org.junit.BeforeClass;
52 import org.junit.Rule;
53 import org.junit.Test;
54 import org.junit.experimental.categories.Category;
55 import org.junit.rules.TestName;
56
57 import com.google.protobuf.ByteString;
58
59 @Category(MediumTests.class)
60 public class TestVisibilityLabelsWithACL {
61
62 private static final String PRIVATE = "private";
63 private static final String CONFIDENTIAL = "confidential";
64 private static final String SECRET = "secret";
65 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
66 private static final byte[] row1 = Bytes.toBytes("row1");
67 private final static byte[] fam = Bytes.toBytes("info");
68 private final static byte[] qual = Bytes.toBytes("qual");
69 private final static byte[] value = Bytes.toBytes("value");
70 private static Configuration conf;
71
72 @Rule
73 public final TestName TEST_NAME = new TestName();
74 private static User SUPERUSER;
75 private static User NORMAL_USER1;
76 private static User NORMAL_USER2;
77
78 @BeforeClass
79 public static void setupBeforeClass() throws Exception {
80
81 conf = TEST_UTIL.getConfiguration();
82 SecureTestUtil.enableSecurity(conf);
83 conf.set("hbase.coprocessor.master.classes", AccessController.class.getName() + ","
84 + VisibilityController.class.getName());
85 conf.set("hbase.coprocessor.region.classes", AccessController.class.getName() + ","
86 + VisibilityController.class.getName());
87 TEST_UTIL.startMiniCluster(2);
88
89 TEST_UTIL.waitTableEnabled(AccessControlLists.ACL_TABLE_NAME.getName(), 50000);
90
91 TEST_UTIL.waitTableEnabled(LABELS_TABLE_NAME.getName(), 50000);
92 addLabels();
93
94
95 SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
96 NORMAL_USER1 = User.createUserForTesting(conf, "user1", new String[] {});
97 NORMAL_USER2 = User.createUserForTesting(conf, "user2", new String[] {});
98
99
100
101 SecureTestUtil.grantOnTable(TEST_UTIL, NORMAL_USER1.getShortName(), LABELS_TABLE_NAME,
102 null, null, Permission.Action.EXEC);
103 SecureTestUtil.grantOnTable(TEST_UTIL, NORMAL_USER2.getShortName(), LABELS_TABLE_NAME,
104 null, null, Permission.Action.EXEC);
105 }
106
107 @AfterClass
108 public static void tearDownAfterClass() throws Exception {
109 TEST_UTIL.shutdownMiniCluster();
110 }
111
112 @Test
113 public void testScanForUserWithFewerLabelAuthsThanLabelsInScanAuthorizations() throws Throwable {
114 String[] auths = { SECRET };
115 String user = "user2";
116 VisibilityClient.setAuths(conf, auths, user);
117 TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
118 final HTable table = createTableAndWriteDataWithLabels(tableName, SECRET + "&" + CONFIDENTIAL
119 + "&!" + PRIVATE, SECRET + "&!" + PRIVATE);
120 SecureTestUtil.grantOnTable(TEST_UTIL, NORMAL_USER2.getShortName(), tableName,
121 null, null, Permission.Action.READ);
122 PrivilegedExceptionAction<Void> scanAction = new PrivilegedExceptionAction<Void>() {
123 public Void run() throws Exception {
124 Scan s = new Scan();
125 s.setAuthorizations(new Authorizations(SECRET, CONFIDENTIAL));
126 Table t = new HTable(conf, table.getName());
127 try {
128 ResultScanner scanner = t.getScanner(s);
129 Result result = scanner.next();
130 assertTrue(!result.isEmpty());
131 assertTrue(Bytes.equals(Bytes.toBytes("row2"), result.getRow()));
132 result = scanner.next();
133 assertNull(result);
134 } finally {
135 t.close();
136 }
137 return null;
138 }
139 };
140 NORMAL_USER2.runAs(scanAction);
141 }
142
143 @Test
144 public void testScanForSuperUserWithFewerLabelAuths() throws Throwable {
145 String[] auths = { SECRET };
146 String user = "admin";
147 VisibilityClient.setAuths(conf, auths, user);
148 TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
149 final HTable table = createTableAndWriteDataWithLabels(tableName, SECRET + "&" + CONFIDENTIAL
150 + "&!" + PRIVATE, SECRET + "&!" + PRIVATE);
151 PrivilegedExceptionAction<Void> scanAction = new PrivilegedExceptionAction<Void>() {
152 public Void run() throws Exception {
153 Scan s = new Scan();
154 s.setAuthorizations(new Authorizations(SECRET, CONFIDENTIAL));
155 Table t = new HTable(conf, table.getName());
156 try {
157 ResultScanner scanner = t.getScanner(s);
158 Result[] result = scanner.next(5);
159 assertTrue(result.length == 2);
160 } finally {
161 t.close();
162 }
163 return null;
164 }
165 };
166 SUPERUSER.runAs(scanAction);
167 }
168
169 @Test
170 public void testGetForSuperUserWithFewerLabelAuths() throws Throwable {
171 String[] auths = { SECRET };
172 String user = "admin";
173 VisibilityClient.setAuths(conf, auths, user);
174 TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
175 final HTable table = createTableAndWriteDataWithLabels(tableName, SECRET + "&" + CONFIDENTIAL
176 + "&!" + PRIVATE, SECRET + "&!" + PRIVATE);
177 PrivilegedExceptionAction<Void> scanAction = new PrivilegedExceptionAction<Void>() {
178 public Void run() throws Exception {
179 Get g = new Get(row1);
180 g.setAuthorizations(new Authorizations(SECRET, CONFIDENTIAL));
181 Table t = new HTable(conf, table.getName());
182 try {
183 Result result = t.get(g);
184 assertTrue(!result.isEmpty());
185 } finally {
186 t.close();
187 }
188 return null;
189 }
190 };
191 SUPERUSER.runAs(scanAction);
192 }
193
194 @Test
195 public void testVisibilityLabelsForUserWithNoAuths() throws Throwable {
196 String user = "admin";
197 String[] auths = { SECRET };
198 VisibilityClient.clearAuths(conf, auths, user);
199 VisibilityClient.setAuths(conf, auths, "user1");
200 TableName tableName = TableName.valueOf(TEST_NAME.getMethodName());
201 final HTable table = createTableAndWriteDataWithLabels(tableName, SECRET);
202 SecureTestUtil.grantOnTable(TEST_UTIL, NORMAL_USER1.getShortName(), tableName,
203 null, null, Permission.Action.READ);
204 SecureTestUtil.grantOnTable(TEST_UTIL, NORMAL_USER2.getShortName(), tableName,
205 null, null, Permission.Action.READ);
206 PrivilegedExceptionAction<Void> getAction = new PrivilegedExceptionAction<Void>() {
207 public Void run() throws Exception {
208 Get g = new Get(row1);
209 g.setAuthorizations(new Authorizations(SECRET, CONFIDENTIAL));
210 Table t = new HTable(conf, table.getName());
211 try {
212 Result result = t.get(g);
213 assertTrue(result.isEmpty());
214 } finally {
215 t.close();
216 }
217 return null;
218 }
219 };
220 NORMAL_USER2.runAs(getAction);
221 }
222
223 @Test
224 public void testLabelsTableOpsWithDifferentUsers() throws Throwable {
225 PrivilegedExceptionAction<VisibilityLabelsResponse> action =
226 new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
227 public VisibilityLabelsResponse run() throws Exception {
228 try {
229 return VisibilityClient.addLabels(conf, new String[] { "l1", "l2" });
230 } catch (Throwable e) {
231 }
232 return null;
233 }
234 };
235 VisibilityLabelsResponse response = NORMAL_USER1.runAs(action);
236 assertEquals("org.apache.hadoop.hbase.security.AccessDeniedException", response
237 .getResult(0).getException().getName());
238 assertEquals("org.apache.hadoop.hbase.security.AccessDeniedException", response
239 .getResult(1).getException().getName());
240
241 action = new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
242 public VisibilityLabelsResponse run() throws Exception {
243 try {
244 return VisibilityClient.setAuths(conf, new String[] { CONFIDENTIAL, PRIVATE }, "user1");
245 } catch (Throwable e) {
246 }
247 return null;
248 }
249 };
250 response = NORMAL_USER1.runAs(action);
251 assertEquals("org.apache.hadoop.hbase.security.AccessDeniedException", response
252 .getResult(0).getException().getName());
253 assertEquals("org.apache.hadoop.hbase.security.AccessDeniedException", response
254 .getResult(1).getException().getName());
255
256 action = new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
257 public VisibilityLabelsResponse run() throws Exception {
258 try {
259 return VisibilityClient.setAuths(conf, new String[] { CONFIDENTIAL, PRIVATE }, "user1");
260 } catch (Throwable e) {
261 }
262 return null;
263 }
264 };
265 response = SUPERUSER.runAs(action);
266 assertTrue(response.getResult(0).getException().getValue().isEmpty());
267 assertTrue(response.getResult(1).getException().getValue().isEmpty());
268
269 action = new PrivilegedExceptionAction<VisibilityLabelsResponse>() {
270 public VisibilityLabelsResponse run() throws Exception {
271 try {
272 return VisibilityClient.clearAuths(conf, new String[] { CONFIDENTIAL, PRIVATE }, "user1");
273 } catch (Throwable e) {
274 }
275 return null;
276 }
277 };
278 response = NORMAL_USER1.runAs(action);
279 assertEquals("org.apache.hadoop.hbase.security.AccessDeniedException", response.getResult(0)
280 .getException().getName());
281 assertEquals("org.apache.hadoop.hbase.security.AccessDeniedException", response.getResult(1)
282 .getException().getName());
283
284 response = VisibilityClient.clearAuths(conf, new String[] { CONFIDENTIAL, PRIVATE }, "user1");
285 assertTrue(response.getResult(0).getException().getValue().isEmpty());
286 assertTrue(response.getResult(1).getException().getValue().isEmpty());
287
288 VisibilityClient.setAuths(conf, new String[] { CONFIDENTIAL, PRIVATE }, "user3");
289 PrivilegedExceptionAction<GetAuthsResponse> action1 =
290 new PrivilegedExceptionAction<GetAuthsResponse>() {
291 public GetAuthsResponse run() throws Exception {
292 try {
293 return VisibilityClient.getAuths(conf, "user3");
294 } catch (Throwable e) {
295 }
296 return null;
297 }
298 };
299 GetAuthsResponse authsResponse = NORMAL_USER1.runAs(action1);
300 assertNull(authsResponse);
301 authsResponse = SUPERUSER.runAs(action1);
302 List<String> authsList = new ArrayList<String>();
303 for (ByteString authBS : authsResponse.getAuthList()) {
304 authsList.add(Bytes.toString(authBS.toByteArray()));
305 }
306 assertEquals(2, authsList.size());
307 assertTrue(authsList.contains(CONFIDENTIAL));
308 assertTrue(authsList.contains(PRIVATE));
309 }
310
311 private static HTable createTableAndWriteDataWithLabels(TableName tableName, String... labelExps)
312 throws Exception {
313 HTable table = null;
314 try {
315 table = TEST_UTIL.createTable(tableName, fam);
316 int i = 1;
317 List<Put> puts = new ArrayList<Put>();
318 for (String labelExp : labelExps) {
319 Put put = new Put(Bytes.toBytes("row" + i));
320 put.add(fam, qual, HConstants.LATEST_TIMESTAMP, value);
321 put.setCellVisibility(new CellVisibility(labelExp));
322 puts.add(put);
323 i++;
324 }
325 table.put(puts);
326 } finally {
327 if (table != null) {
328 table.close();
329 }
330 }
331 return table;
332 }
333
334 private static void addLabels() throws IOException {
335 String[] labels = { SECRET, CONFIDENTIAL, PRIVATE };
336 try {
337 VisibilityClient.addLabels(conf, labels);
338 } catch (Throwable t) {
339 throw new IOException(t);
340 }
341 }
342 }