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.HTableDescriptor;
31 import org.apache.hadoop.hbase.testclassification.MediumTests;
32 import org.apache.hadoop.hbase.TableNotFoundException;
33 import org.apache.hadoop.hbase.client.Admin;
34 import org.apache.hadoop.hbase.client.Connection;
35 import org.apache.hadoop.hbase.client.ConnectionFactory;
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
86 enableSecurity(conf);
87
88 verifyConfiguration(conf);
89
90 TEST_UTIL.startMiniCluster();
91 MasterCoprocessorHost cpHost = TEST_UTIL.getMiniHBaseCluster().getMaster()
92 .getMasterCoprocessorHost();
93 cpHost.load(AccessController.class, Coprocessor.PRIORITY_HIGHEST, conf);
94 AccessController ac = (AccessController)
95 cpHost.findCoprocessor(AccessController.class.getName());
96 cpHost.createEnvironment(AccessController.class, ac, Coprocessor.PRIORITY_HIGHEST, 1, conf);
97 RegionServerCoprocessorHost rsHost = TEST_UTIL.getMiniHBaseCluster().getRegionServer(0)
98 .getRegionServerCoprocessorHost();
99 rsHost.createEnvironment(AccessController.class, ac, Coprocessor.PRIORITY_HIGHEST, 1, conf);
100
101
102 TEST_UTIL.waitTableEnabled(AccessControlLists.ACL_TABLE_NAME);
103
104
105 USER_OWNER = User.createUserForTesting(conf, "owner", new String[0]);
106 USER_OTHER = User.createUserForTesting(conf, "other", new String[0]);
107 }
108
109 @AfterClass
110 public static void tearDownAfterClass() throws Exception {
111 TEST_UTIL.shutdownMiniCluster();
112 }
113
114 @Before
115 public void setUp() throws Exception {
116 Admin admin = TEST_UTIL.getHBaseAdmin();
117 HTableDescriptor htd = new HTableDescriptor(TEST_TABLE.getTableName());
118 htd.setOwner(USER_OWNER);
119 HColumnDescriptor hcd = new HColumnDescriptor(TEST_FAMILY1);
120 hcd.setMaxVersions(10);
121 htd.addFamily(hcd);
122 hcd = new HColumnDescriptor(TEST_FAMILY2);
123 hcd.setMaxVersions(10);
124 htd.addFamily(hcd);
125
126
127
128 htd.setConfiguration(AccessControlConstants.CF_ATTRIBUTE_EARLY_OUT, "true");
129
130 admin.createTable(htd);
131 TEST_UTIL.waitUntilAllRegionsAssigned(TEST_TABLE.getTableName());
132 }
133
134 @After
135 public void tearDown() throws Exception {
136
137 try {
138 TEST_UTIL.deleteTable(TEST_TABLE.getTableName());
139 } catch (TableNotFoundException ex) {
140
141 LOG.info("Test deleted table " + TEST_TABLE.getTableName());
142 }
143 assertEquals(0, AccessControlLists.getTablePermissions(conf, TEST_TABLE.getTableName()).size());
144 }
145
146 @Test
147 public void testEarlyScanTermination() throws Exception {
148
149 grantOnTable(TEST_UTIL, USER_OTHER.getShortName(), TEST_TABLE.getTableName(), TEST_FAMILY1,
150 null, Action.READ);
151
152
153 verifyAllowed(new AccessTestAction() {
154 @Override
155 public Object run() throws Exception {
156
157 conf.set("testkey", UUID.randomUUID().toString());
158 try (Connection connection = ConnectionFactory.createConnection(conf);
159 Table t = connection.getTable(TEST_TABLE.getTableName())) {
160 Put put = new Put(TEST_ROW).add(TEST_FAMILY1, TEST_Q1, ZERO);
161 t.put(put);
162
163 put = new Put(TEST_ROW).add(TEST_FAMILY2, TEST_Q1, ZERO);
164 put.setACL(USER_OTHER.getShortName(), new Permission(Action.READ));
165 t.put(put);
166
167 put = new Put(TEST_ROW).add(TEST_FAMILY2, TEST_Q2, ZERO);
168 put.setACL(USER_OTHER.getShortName(), new Permission());
169 t.put(put);
170 }
171 return null;
172 }
173 }, USER_OWNER);
174
175
176 verifyAllowed(new AccessTestAction() {
177 @Override
178 public Object run() throws Exception {
179
180 conf.set("testkey", UUID.randomUUID().toString());
181 try (Connection connection = ConnectionFactory.createConnection(conf);
182 Table t = connection.getTable(TEST_TABLE.getTableName())) {
183 Scan scan = new Scan().addFamily(TEST_FAMILY1);
184 Result result = t.getScanner(scan).next();
185 if (result != null) {
186 assertTrue("Improper exclusion", result.containsColumn(TEST_FAMILY1, TEST_Q1));
187 assertFalse("Improper inclusion", result.containsColumn(TEST_FAMILY2, TEST_Q1));
188 return result.listCells();
189 }
190 return null;
191 }
192 }
193 }, USER_OTHER);
194
195
196
197
198 verifyAllowed(new AccessTestAction() {
199 @Override
200 public Object run() throws Exception {
201
202 conf.set("testkey", UUID.randomUUID().toString());
203 try (Connection connection = ConnectionFactory.createConnection(conf);
204 Table t = connection.getTable(TEST_TABLE.getTableName())) {
205 Scan scan = new Scan();
206 Result result = t.getScanner(scan).next();
207 if (result != null) {
208 assertTrue("Improper exclusion", result.containsColumn(TEST_FAMILY1, TEST_Q1));
209 assertFalse("Improper inclusion", result.containsColumn(TEST_FAMILY2, TEST_Q1));
210 return result.listCells();
211 }
212 return null;
213 }
214 }
215 }, USER_OTHER);
216
217
218 verifyDenied(new AccessTestAction() {
219 @Override
220 public Object run() throws Exception {
221
222 conf.set("testkey", UUID.randomUUID().toString());
223 try (Connection connection = ConnectionFactory.createConnection(conf);
224 Table t = connection.getTable(TEST_TABLE.getTableName())) {
225 Scan scan = new Scan().addFamily(TEST_FAMILY2);
226 Result result = t.getScanner(scan).next();
227 if (result != null) {
228 return result.listCells();
229 }
230 return null;
231 }
232 }
233 }, USER_OTHER);
234
235
236 grantOnTable(TEST_UTIL, USER_OTHER.getShortName(), TEST_TABLE.getTableName(), TEST_FAMILY2,
237 TEST_Q2, Action.READ);
238
239
240
241
242 verifyAllowed(new AccessTestAction() {
243 @Override
244 public Object run() throws Exception {
245
246 conf.set("testkey", UUID.randomUUID().toString());
247 try (Connection connection = ConnectionFactory.createConnection(conf);
248 Table t = connection.getTable(TEST_TABLE.getTableName())) {
249 Scan scan = new Scan();
250 Result result = t.getScanner(scan).next();
251 if (result != null) {
252 assertTrue("Improper exclusion", result.containsColumn(TEST_FAMILY1, TEST_Q1));
253 assertFalse("Improper inclusion", result.containsColumn(TEST_FAMILY2, TEST_Q1));
254 assertTrue("Improper exclusion", result.containsColumn(TEST_FAMILY2, TEST_Q2));
255 return result.listCells();
256 }
257 return null;
258 }
259 }
260 }, USER_OTHER);
261 }
262 }