1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.security.access;
20
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertFalse;
23 import static org.junit.Assert.assertTrue;
24 import static org.junit.Assert.fail;
25
26 import java.io.IOException;
27 import java.security.PrivilegedExceptionAction;
28 import java.util.ArrayList;
29 import java.util.List;
30 import java.util.UUID;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.hadoop.conf.Configuration;
35 import org.apache.hadoop.hbase.HBaseTestingUtility;
36 import org.apache.hadoop.hbase.LargeTests;
37 import org.apache.hadoop.hbase.TableName;
38 import org.apache.hadoop.hbase.client.HTable;
39 import org.apache.hadoop.hbase.client.Put;
40 import org.apache.hadoop.hbase.client.Result;
41 import org.apache.hadoop.hbase.client.ResultScanner;
42 import org.apache.hadoop.hbase.client.Scan;
43 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
44 import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService;
45 import org.apache.hadoop.hbase.security.AccessDeniedException;
46 import org.apache.hadoop.hbase.security.User;
47 import org.apache.hadoop.hbase.util.Bytes;
48 import org.junit.AfterClass;
49 import org.junit.Before;
50 import org.junit.BeforeClass;
51 import org.junit.Rule;
52 import org.junit.Test;
53 import org.junit.experimental.categories.Category;
54 import org.junit.rules.TestName;
55
56 import com.google.protobuf.BlockingRpcChannel;
57
58 @Category(LargeTests.class)
59 public class TestAccessControlFilter {
60 @Rule public TestName name = new TestName();
61 private static Log LOG = LogFactory.getLog(TestAccessControlFilter.class);
62 private static HBaseTestingUtility TEST_UTIL;
63
64 private static User ADMIN;
65 private static User READER;
66 private static User LIMITED;
67 private static User DENIED;
68
69
70 private static TableName TABLE;
71 private static byte[] FAMILY = Bytes.toBytes("f1");
72 private static byte[] PRIVATE_COL = Bytes.toBytes("private");
73 private static byte[] PUBLIC_COL = Bytes.toBytes("public");
74
75 @Before
76 public void setup () {
77 TABLE = TableName.valueOf(name.getMethodName());
78 }
79
80 @BeforeClass
81 public static void setupBeforeClass() throws Exception {
82 TEST_UTIL = new HBaseTestingUtility();
83 Configuration conf = TEST_UTIL.getConfiguration();
84 SecureTestUtil.enableSecurity(conf);
85 String baseuser = User.getCurrent().getShortName();
86 conf.set("hbase.superuser", conf.get("hbase.superuser", "") +
87 String.format(",%s.hfs.0,%s.hfs.1,%s.hfs.2", baseuser, baseuser, baseuser));
88 TEST_UTIL.startMiniCluster();
89 TEST_UTIL.waitTableEnabled(AccessControlLists.ACL_TABLE_NAME.getName());
90
91 ADMIN = User.createUserForTesting(conf, "admin", new String[]{"supergroup"});
92 READER = User.createUserForTesting(conf, "reader", new String[0]);
93 LIMITED = User.createUserForTesting(conf, "limited", new String[0]);
94 DENIED = User.createUserForTesting(conf, "denied", new String[0]);
95 }
96
97 @AfterClass
98 public static void tearDownAfterClass() throws Exception {
99 TEST_UTIL.shutdownMiniCluster();
100 }
101
102 @Test
103 public void testQualifierAccess() throws Exception {
104 final HTable table = TEST_UTIL.createTable(TABLE, FAMILY);
105 try {
106 doQualifierAccess(table);
107 } finally {
108 table.close();
109 }
110 }
111
112 private void doQualifierAccess(final HTable table) throws IOException, InterruptedException {
113
114 ADMIN.runAs(new PrivilegedExceptionAction<Object>() {
115 @Override
116 public Object run() throws Exception {
117 HTable aclmeta = new HTable(TEST_UTIL.getConfiguration(),
118 AccessControlLists.ACL_TABLE_NAME);
119 byte[] table = Bytes.toBytes(name.getMethodName());
120 BlockingRpcChannel service = aclmeta.coprocessorService(table);
121 AccessControlService.BlockingInterface protocol =
122 AccessControlService.newBlockingStub(service);
123 ProtobufUtil.grant(protocol, READER.getShortName(),
124 TABLE, null, null, Permission.Action.READ);
125 ProtobufUtil.grant(protocol, LIMITED.getShortName(),
126 TABLE, FAMILY, PUBLIC_COL, Permission.Action.READ);
127 return null;
128 }
129 });
130
131
132 List<Put> puts = new ArrayList<Put>(100);
133 for (int i=0; i<100; i++) {
134 Put p = new Put(Bytes.toBytes(i));
135 p.add(FAMILY, PRIVATE_COL, Bytes.toBytes("secret "+i));
136 p.add(FAMILY, PUBLIC_COL, Bytes.toBytes("info "+i));
137 puts.add(p);
138 }
139 table.put(puts);
140
141
142 READER.runAs(new PrivilegedExceptionAction<Object>() {
143 public Object run() throws Exception {
144 Configuration conf = new Configuration(TEST_UTIL.getConfiguration());
145
146 conf.set("testkey", UUID.randomUUID().toString());
147 HTable t = new HTable(conf, TABLE);
148 ResultScanner rs = t.getScanner(new Scan());
149 int rowcnt = 0;
150 for (Result r : rs) {
151 rowcnt++;
152 int rownum = Bytes.toInt(r.getRow());
153 assertTrue(r.containsColumn(FAMILY, PRIVATE_COL));
154 assertEquals("secret "+rownum, Bytes.toString(r.getValue(FAMILY, PRIVATE_COL)));
155 assertTrue(r.containsColumn(FAMILY, PUBLIC_COL));
156 assertEquals("info "+rownum, Bytes.toString(r.getValue(FAMILY, PUBLIC_COL)));
157 }
158 assertEquals("Expected 100 rows returned", 100, rowcnt);
159 return null;
160 }
161 });
162
163
164 LIMITED.runAs(new PrivilegedExceptionAction<Object>() {
165 public Object run() throws Exception {
166 Configuration conf = new Configuration(TEST_UTIL.getConfiguration());
167
168 conf.set("testkey", UUID.randomUUID().toString());
169 HTable t = new HTable(conf, TABLE);
170 ResultScanner rs = t.getScanner(new Scan());
171 int rowcnt = 0;
172 for (Result r : rs) {
173 rowcnt++;
174 int rownum = Bytes.toInt(r.getRow());
175 assertFalse(r.containsColumn(FAMILY, PRIVATE_COL));
176 assertTrue(r.containsColumn(FAMILY, PUBLIC_COL));
177 assertEquals("info " + rownum, Bytes.toString(r.getValue(FAMILY, PUBLIC_COL)));
178 }
179 assertEquals("Expected 100 rows returned", 100, rowcnt);
180 return null;
181 }
182 });
183
184
185 DENIED.runAs(new PrivilegedExceptionAction(){
186 public Object run() throws Exception {
187 try {
188 Configuration conf = new Configuration(TEST_UTIL.getConfiguration());
189
190 conf.set("testkey", UUID.randomUUID().toString());
191 HTable t = new HTable(conf, TABLE);
192 ResultScanner rs = t.getScanner(new Scan());
193 fail("Attempt to open scanner should have been denied");
194 } catch (AccessDeniedException ade) {
195
196 }
197 return null;
198 }
199 });
200 }
201 }