1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.security.access;
19
20 import static org.junit.Assert.*;
21
22 import java.util.UUID;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.apache.hadoop.conf.Configuration;
27 import org.apache.hadoop.hbase.Coprocessor;
28 import org.apache.hadoop.hbase.HBaseTestingUtility;
29 import org.apache.hadoop.hbase.HColumnDescriptor;
30 import org.apache.hadoop.hbase.HConstants;
31 import org.apache.hadoop.hbase.HTableDescriptor;
32 import org.apache.hadoop.hbase.testclassification.MediumTests;
33 import org.apache.hadoop.hbase.TableNotFoundException;
34 import org.apache.hadoop.hbase.client.Admin;
35 import org.apache.hadoop.hbase.client.HTable;
36 import org.apache.hadoop.hbase.client.Put;
37 import org.apache.hadoop.hbase.client.Result;
38 import org.apache.hadoop.hbase.client.Scan;
39 import org.apache.hadoop.hbase.client.Table;
40 import org.apache.hadoop.hbase.master.MasterCoprocessorHost;
41 import org.apache.hadoop.hbase.regionserver.RegionServerCoprocessorHost;
42 import org.apache.hadoop.hbase.security.User;
43 import org.apache.hadoop.hbase.security.access.Permission.Action;
44 import org.apache.hadoop.hbase.util.Bytes;
45 import org.apache.hadoop.hbase.util.TestTableName;
46 import org.apache.log4j.Level;
47 import org.apache.log4j.Logger;
48 import org.junit.After;
49 import org.junit.AfterClass;
50 import org.junit.Before;
51 import org.junit.BeforeClass;
52 import org.junit.Rule;
53 import org.junit.Test;
54 import org.junit.experimental.categories.Category;
55
56 @Category(MediumTests.class)
57 public class TestScanEarlyTermination extends SecureTestUtil {
58 private static final Log LOG = LogFactory.getLog(TestScanEarlyTermination.class);
59
60 static {
61 Logger.getLogger(AccessController.class).setLevel(Level.TRACE);
62 Logger.getLogger(AccessControlFilter.class).setLevel(Level.TRACE);
63 Logger.getLogger(TableAuthManager.class).setLevel(Level.TRACE);
64 }
65
66 @Rule
67 public TestTableName TEST_TABLE = new TestTableName();
68 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
69 private static final byte[] TEST_FAMILY1 = Bytes.toBytes("f1");
70 private static final byte[] TEST_FAMILY2 = Bytes.toBytes("f2");
71 private static final byte[] TEST_ROW = Bytes.toBytes("testrow");
72 private static final byte[] TEST_Q1 = Bytes.toBytes("q1");
73 private static final byte[] TEST_Q2 = Bytes.toBytes("q2");
74 private static final byte[] ZERO = Bytes.toBytes(0L);
75
76 private static Configuration conf;
77
78 private static User USER_OWNER;
79 private static User USER_OTHER;
80
81 @BeforeClass
82 public static void setupBeforeClass() throws Exception {
83
84 conf = TEST_UTIL.getConfiguration();
85 conf.setInt(HConstants.REGION_SERVER_HIGH_PRIORITY_HANDLER_COUNT, 10);
86
87 enableSecurity(conf);
88
89 verifyConfiguration(conf);
90
91 TEST_UTIL.startMiniCluster();
92 MasterCoprocessorHost cpHost = TEST_UTIL.getMiniHBaseCluster().getMaster()
93 .getMasterCoprocessorHost();
94 cpHost.load(AccessController.class, Coprocessor.PRIORITY_HIGHEST, conf);
95 AccessController ac = (AccessController)
96 cpHost.findCoprocessor(AccessController.class.getName());
97 cpHost.createEnvironment(AccessController.class, ac, Coprocessor.PRIORITY_HIGHEST, 1, conf);
98 RegionServerCoprocessorHost rsHost = TEST_UTIL.getMiniHBaseCluster().getRegionServer(0)
99 .getRegionServerCoprocessorHost();
100 rsHost.createEnvironment(AccessController.class, ac, Coprocessor.PRIORITY_HIGHEST, 1, conf);
101
102
103 TEST_UTIL.waitTableEnabled(AccessControlLists.ACL_TABLE_NAME);
104
105
106 USER_OWNER = User.createUserForTesting(conf, "owner", new String[0]);
107 USER_OTHER = User.createUserForTesting(conf, "other", new String[0]);
108 }
109
110 @AfterClass
111 public static void tearDownAfterClass() throws Exception {
112 TEST_UTIL.shutdownMiniCluster();
113 }
114
115 @Before
116 public void setUp() throws Exception {
117 Admin admin = TEST_UTIL.getHBaseAdmin();
118 HTableDescriptor htd = new HTableDescriptor(TEST_TABLE.getTableName());
119 htd.setOwner(USER_OWNER);
120 HColumnDescriptor hcd = new HColumnDescriptor(TEST_FAMILY1);
121 hcd.setMaxVersions(10);
122 htd.addFamily(hcd);
123 hcd = new HColumnDescriptor(TEST_FAMILY2);
124 hcd.setMaxVersions(10);
125 htd.addFamily(hcd);
126
127
128
129 htd.setConfiguration(AccessControlConstants.CF_ATTRIBUTE_EARLY_OUT, "true");
130
131 admin.createTable(htd);
132 TEST_UTIL.waitUntilAllRegionsAssigned(TEST_TABLE.getTableName());
133 }
134
135 @After
136 public void tearDown() throws Exception {
137
138 try {
139 TEST_UTIL.deleteTable(TEST_TABLE.getTableName());
140 } catch (TableNotFoundException ex) {
141
142 LOG.info("Test deleted table " + TEST_TABLE.getTableName());
143 }
144 assertEquals(0, AccessControlLists.getTablePermissions(conf, TEST_TABLE.getTableName()).size());
145 }
146
147 @Test
148 public void testEarlyScanTermination() throws Exception {
149
150 grantOnTable(TEST_UTIL, USER_OTHER.getShortName(), TEST_TABLE.getTableName(), TEST_FAMILY1,
151 null, Action.READ);
152
153
154 verifyAllowed(new AccessTestAction() {
155 @Override
156 public Object run() throws Exception {
157
158 conf.set("testkey", UUID.randomUUID().toString());
159 Table t = new HTable(conf, TEST_TABLE.getTableName());
160 try {
161 Put put = new Put(TEST_ROW).add(TEST_FAMILY1, TEST_Q1, ZERO);
162 t.put(put);
163
164 put = new Put(TEST_ROW).add(TEST_FAMILY2, TEST_Q1, ZERO);
165 put.setACL(USER_OTHER.getShortName(), new Permission(Action.READ));
166 t.put(put);
167
168 put = new Put(TEST_ROW).add(TEST_FAMILY2, TEST_Q2, ZERO);
169 put.setACL(USER_OTHER.getShortName(), new Permission());
170 t.put(put);
171 } finally {
172 t.close();
173 }
174 return null;
175 }
176 }, USER_OWNER);
177
178
179 verifyAllowed(new AccessTestAction() {
180 @Override
181 public Object run() throws Exception {
182
183 conf.set("testkey", UUID.randomUUID().toString());
184 Table t = new HTable(conf, TEST_TABLE.getTableName());
185 try {
186 Scan scan = new Scan().addFamily(TEST_FAMILY1);
187 Result result = t.getScanner(scan).next();
188 if (result != null) {
189 assertTrue("Improper exclusion", result.containsColumn(TEST_FAMILY1, TEST_Q1));
190 assertFalse("Improper inclusion", result.containsColumn(TEST_FAMILY2, TEST_Q1));
191 return result.listCells();
192 }
193 return null;
194 } finally {
195 t.close();
196 }
197 }
198 }, USER_OTHER);
199
200
201
202
203 verifyAllowed(new AccessTestAction() {
204 @Override
205 public Object run() throws Exception {
206
207 conf.set("testkey", UUID.randomUUID().toString());
208 Table t = new HTable(conf, TEST_TABLE.getTableName());
209 try {
210 Scan scan = new Scan();
211 Result result = t.getScanner(scan).next();
212 if (result != null) {
213 assertTrue("Improper exclusion", result.containsColumn(TEST_FAMILY1, TEST_Q1));
214 assertFalse("Improper inclusion", result.containsColumn(TEST_FAMILY2, TEST_Q1));
215 return result.listCells();
216 }
217 return null;
218 } finally {
219 t.close();
220 }
221 }
222 }, USER_OTHER);
223
224
225 verifyDenied(new AccessTestAction() {
226 @Override
227 public Object run() throws Exception {
228
229 conf.set("testkey", UUID.randomUUID().toString());
230 Table t = new HTable(conf, TEST_TABLE.getTableName());
231 try {
232 Scan scan = new Scan().addFamily(TEST_FAMILY2);
233 Result result = t.getScanner(scan).next();
234 if (result != null) {
235 return result.listCells();
236 }
237 return null;
238 } finally {
239 t.close();
240 }
241 }
242 }, USER_OTHER);
243
244
245 grantOnTable(TEST_UTIL, USER_OTHER.getShortName(), TEST_TABLE.getTableName(), TEST_FAMILY2,
246 TEST_Q2, Action.READ);
247
248
249
250
251 verifyAllowed(new AccessTestAction() {
252 @Override
253 public Object run() throws Exception {
254
255 conf.set("testkey", UUID.randomUUID().toString());
256 Table t = new HTable(conf, TEST_TABLE.getTableName());
257 try {
258 Scan scan = new Scan();
259 Result result = t.getScanner(scan).next();
260 if (result != null) {
261 assertTrue("Improper exclusion", result.containsColumn(TEST_FAMILY1, TEST_Q1));
262 assertFalse("Improper inclusion", result.containsColumn(TEST_FAMILY2, TEST_Q1));
263 assertTrue("Improper exclusion", result.containsColumn(TEST_FAMILY2, TEST_Q2));
264 return result.listCells();
265 }
266 return null;
267 } finally {
268 t.close();
269 }
270 }
271 }, USER_OTHER);
272 }
273 }