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.assertEquals;
21 import static org.junit.Assert.assertTrue;
22
23 import java.util.List;
24
25 import org.apache.hadoop.conf.Configuration;
26 import org.apache.hadoop.hbase.HBaseTestingUtility;
27 import org.apache.hadoop.hbase.HColumnDescriptor;
28 import org.apache.hadoop.hbase.HConstants;
29 import org.apache.hadoop.hbase.HTableDescriptor;
30 import org.apache.hadoop.hbase.NamespaceDescriptor;
31 import org.apache.hadoop.hbase.client.HTable;
32 import org.apache.hadoop.hbase.testclassification.MediumTests;
33 import org.apache.hadoop.hbase.TableName;
34 import org.apache.hadoop.hbase.client.Get;
35 import org.apache.hadoop.hbase.client.Result;
36 import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment;
37 import org.apache.hadoop.hbase.coprocessor.ObserverContext;
38 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
39 import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService;
40 import org.apache.hadoop.hbase.security.User;
41 import org.apache.hadoop.hbase.security.access.Permission.Action;
42 import org.apache.hadoop.hbase.util.Bytes;
43 import org.junit.AfterClass;
44 import org.junit.BeforeClass;
45 import org.junit.Test;
46 import org.junit.experimental.categories.Category;
47
48 import com.google.common.collect.ListMultimap;
49 import com.google.protobuf.BlockingRpcChannel;
50
51 @Category(MediumTests.class)
52 public class TestNamespaceCommands extends SecureTestUtil {
53 private static HBaseTestingUtility UTIL = new HBaseTestingUtility();
54 private static String TEST_NAMESPACE = "ns1";
55 private static String TEST_NAMESPACE2 = "ns2";
56 private static Configuration conf;
57 private static MasterCoprocessorEnvironment CP_ENV;
58 private static AccessController ACCESS_CONTROLLER;
59
60
61 private static User SUPERUSER;
62
63 private static User USER_RW;
64
65 private static User USER_CREATE;
66
67 private static User USER_NSP_WRITE;
68
69 private static User USER_NSP_ADMIN;
70
71 private static String TEST_TABLE = TEST_NAMESPACE + ":testtable";
72 private static byte[] TEST_FAMILY = Bytes.toBytes("f1");
73
74 @BeforeClass
75 public static void beforeClass() throws Exception {
76 conf = UTIL.getConfiguration();
77 enableSecurity(conf);
78
79 SUPERUSER = User.createUserForTesting(conf, "admin", new String[] { "supergroup" });
80 USER_RW = User.createUserForTesting(conf, "rw_user", new String[0]);
81 USER_CREATE = User.createUserForTesting(conf, "create_user", new String[0]);
82 USER_NSP_WRITE = User.createUserForTesting(conf, "namespace_write", new String[0]);
83 USER_NSP_ADMIN = User.createUserForTesting(conf, "namespace_admin", new String[0]);
84
85 UTIL.startMiniCluster();
86
87 UTIL.waitTableAvailable(AccessControlLists.ACL_TABLE_NAME.getName(), 30 * 1000);
88
89 ACCESS_CONTROLLER = (AccessController) UTIL.getMiniHBaseCluster().getMaster()
90 .getCoprocessorHost()
91 .findCoprocessor(AccessController.class.getName());
92
93 UTIL.getHBaseAdmin().createNamespace(NamespaceDescriptor.create(TEST_NAMESPACE).build());
94 UTIL.getHBaseAdmin().createNamespace(NamespaceDescriptor.create(TEST_NAMESPACE2).build());
95
96 grantOnNamespace(UTIL, USER_NSP_WRITE.getShortName(),
97 TEST_NAMESPACE, Permission.Action.WRITE, Permission.Action.CREATE);
98
99 grantOnNamespace(UTIL, USER_NSP_ADMIN.getShortName(), TEST_NAMESPACE, Permission.Action.ADMIN);
100 grantOnNamespace(UTIL, USER_NSP_ADMIN.getShortName(), TEST_NAMESPACE2, Permission.Action.ADMIN);
101 }
102
103 @AfterClass
104 public static void afterClass() throws Exception {
105 UTIL.getHBaseAdmin().deleteNamespace(TEST_NAMESPACE);
106 UTIL.getHBaseAdmin().deleteNamespace(TEST_NAMESPACE2);
107 UTIL.shutdownMiniCluster();
108 }
109
110 @Test
111 public void testAclTableEntries() throws Exception {
112 String userTestNamespace = "userTestNsp";
113 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
114 try {
115
116 grantOnNamespace(UTIL, userTestNamespace, TEST_NAMESPACE,
117 Permission.Action.WRITE);
118
119 Result result = acl.get(new Get(Bytes.toBytes(userTestNamespace)));
120 assertTrue(result != null);
121 ListMultimap<String, TablePermission> perms =
122 AccessControlLists.getNamespacePermissions(conf, TEST_NAMESPACE);
123 assertEquals(3, perms.size());
124 List<TablePermission> namespacePerms = perms.get(userTestNamespace);
125 assertTrue(perms.containsKey(userTestNamespace));
126 assertEquals(1, namespacePerms.size());
127 assertEquals(TEST_NAMESPACE,
128 namespacePerms.get(0).getNamespace());
129 assertEquals(null, namespacePerms.get(0).getFamily());
130 assertEquals(null, namespacePerms.get(0).getQualifier());
131 assertEquals(1, namespacePerms.get(0).getActions().length);
132 assertEquals(Permission.Action.WRITE, namespacePerms.get(0).getActions()[0]);
133
134
135 revokeFromNamespace(UTIL, userTestNamespace, TEST_NAMESPACE,
136 Permission.Action.WRITE);
137
138 perms = AccessControlLists.getNamespacePermissions(conf, TEST_NAMESPACE);
139 assertEquals(2, perms.size());
140 } finally {
141 acl.close();
142 }
143 }
144
145 @Test
146 public void testModifyNamespace() throws Exception {
147 AccessTestAction modifyNamespace = new AccessTestAction() {
148 public Object run() throws Exception {
149 ACCESS_CONTROLLER.preModifyNamespace(ObserverContext.createAndPrepare(CP_ENV, null),
150 NamespaceDescriptor.create(TEST_NAMESPACE).addConfiguration("abc", "156").build());
151 return null;
152 }
153 };
154
155 verifyAllowed(modifyNamespace, SUPERUSER, USER_NSP_ADMIN);
156
157 verifyDenied(modifyNamespace, USER_NSP_WRITE, USER_CREATE, USER_RW);
158 }
159
160 @Test
161 public void testCreateAndDeleteNamespace() throws Exception {
162 AccessTestAction createNamespace = new AccessTestAction() {
163 public Object run() throws Exception {
164 ACCESS_CONTROLLER.preCreateNamespace(ObserverContext.createAndPrepare(CP_ENV, null),
165 NamespaceDescriptor.create(TEST_NAMESPACE2).build());
166 return null;
167 }
168 };
169
170 AccessTestAction deleteNamespace = new AccessTestAction() {
171 public Object run() throws Exception {
172 ACCESS_CONTROLLER.preDeleteNamespace(ObserverContext.createAndPrepare(CP_ENV, null),
173 TEST_NAMESPACE2);
174 return null;
175 }
176 };
177
178
179 verifyAllowed(createNamespace, SUPERUSER);
180
181 verifyAllowed(deleteNamespace, SUPERUSER, USER_NSP_ADMIN);
182
183
184 verifyDenied(createNamespace, USER_NSP_WRITE, USER_CREATE, USER_RW, USER_NSP_ADMIN);
185 verifyDenied(deleteNamespace, USER_NSP_WRITE, USER_CREATE, USER_RW);
186 }
187
188 @Test
189 public void testGrantRevoke() throws Exception{
190 final String testUser = "testUser";
191
192
193
194 AccessTestAction grantAction = new AccessTestAction() {
195 public Object run() throws Exception {
196 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
197 try {
198 BlockingRpcChannel service =
199 acl.coprocessorService(HConstants.EMPTY_START_ROW);
200 AccessControlService.BlockingInterface protocol =
201 AccessControlService.newBlockingStub(service);
202 ProtobufUtil.grant(protocol, testUser, TEST_NAMESPACE, Action.WRITE);
203 } finally {
204 acl.close();
205 }
206 return null;
207 }
208 };
209
210 AccessTestAction revokeAction = new AccessTestAction() {
211 public Object run() throws Exception {
212 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
213 try {
214 BlockingRpcChannel service =
215 acl.coprocessorService(HConstants.EMPTY_START_ROW);
216 AccessControlService.BlockingInterface protocol =
217 AccessControlService.newBlockingStub(service);
218 ProtobufUtil.revoke(protocol, testUser, TEST_NAMESPACE, Action.WRITE);
219 } finally {
220 acl.close();
221 }
222 return null;
223 }
224 };
225
226 AccessTestAction getPermissionsAction = new AccessTestAction() {
227 @Override
228 public Object run() throws Exception {
229 HTable acl = new HTable(conf, AccessControlLists.ACL_TABLE_NAME);
230 try {
231 BlockingRpcChannel service = acl.coprocessorService(HConstants.EMPTY_START_ROW);
232 AccessControlService.BlockingInterface protocol =
233 AccessControlService.newBlockingStub(service);
234 ProtobufUtil.getUserPermissions(protocol, Bytes.toBytes(TEST_NAMESPACE));
235 } finally {
236 acl.close();
237 }
238 return null;
239 }
240 };
241
242
243
244 verifyAllowed(grantAction, SUPERUSER, USER_NSP_ADMIN);
245 verifyDenied(grantAction, USER_CREATE, USER_RW);
246 verifyAllowed(revokeAction, SUPERUSER, USER_NSP_ADMIN);
247 verifyDenied(revokeAction, USER_CREATE, USER_RW);
248
249
250 verifyAllowed(revokeAction, SUPERUSER, USER_NSP_ADMIN);
251 verifyDenied(revokeAction, USER_CREATE, USER_RW);
252 }
253
254 @Test
255 public void testCreateTableWithNamespace() throws Exception {
256 AccessTestAction createTable = new AccessTestAction() {
257 @Override
258 public Object run() throws Exception {
259 HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(TEST_TABLE));
260 htd.addFamily(new HColumnDescriptor(TEST_FAMILY));
261 ACCESS_CONTROLLER.preCreateTable(ObserverContext.createAndPrepare(CP_ENV, null), htd, null);
262 return null;
263 }
264 };
265
266
267 verifyAllowed(createTable, SUPERUSER, USER_NSP_WRITE);
268
269
270 verifyDenied(createTable, USER_CREATE, USER_RW);
271 }
272 }