HBASE-19811 Fix findbugs and error-prone warnings in hbase-server (branch-2)
[hbase.git] / hbase-server / src / test / java / org / apache / hadoop / hbase / zookeeper / TestZooKeeperACL.java
blob3e9e650b37897d088ff0caadd968a1bf4ea55b5a
1 /**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package org.apache.hadoop.hbase.zookeeper;
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertTrue;
23 import java.io.File;
24 import java.io.FileWriter;
25 import java.io.IOException;
26 import java.util.ArrayList;
27 import java.util.List;
29 import javax.security.auth.login.AppConfigurationEntry;
31 import org.apache.hadoop.conf.Configuration;
32 import org.apache.hadoop.hbase.HBaseConfiguration;
33 import org.apache.hadoop.hbase.HBaseTestingUtility;
34 import org.apache.hadoop.hbase.HConstants;
35 import org.apache.hadoop.hbase.ServerName;
36 import org.apache.hadoop.hbase.TestZooKeeper;
37 import org.apache.hadoop.hbase.testclassification.MediumTests;
38 import org.apache.hadoop.hbase.testclassification.ZKTests;
39 import org.apache.zookeeper.ZooDefs;
40 import org.apache.zookeeper.data.ACL;
41 import org.apache.zookeeper.data.Stat;
42 import org.junit.AfterClass;
43 import org.junit.Before;
44 import org.junit.BeforeClass;
45 import org.junit.Test;
46 import org.junit.experimental.categories.Category;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
50 @Category({ ZKTests.class, MediumTests.class })
51 public class TestZooKeeperACL {
52 private final static Logger LOG = LoggerFactory.getLogger(TestZooKeeperACL.class);
53 private final static HBaseTestingUtility TEST_UTIL =
54 new HBaseTestingUtility();
56 private static ZKWatcher zkw;
57 private static boolean secureZKAvailable;
59 @BeforeClass
60 public static void setUpBeforeClass() throws Exception {
61 File saslConfFile = File.createTempFile("tmp", "jaas.conf");
62 FileWriter fwriter = new FileWriter(saslConfFile);
64 fwriter.write("" +
65 "Server {\n" +
66 "org.apache.zookeeper.server.auth.DigestLoginModule required\n" +
67 "user_hbase=\"secret\";\n" +
68 "};\n" +
69 "Client {\n" +
70 "org.apache.zookeeper.server.auth.DigestLoginModule required\n" +
71 "username=\"hbase\"\n" +
72 "password=\"secret\";\n" +
73 "};" + "\n");
74 fwriter.close();
75 System.setProperty("java.security.auth.login.config",
76 saslConfFile.getAbsolutePath());
77 System.setProperty("zookeeper.authProvider.1",
78 "org.apache.zookeeper.server.auth.SASLAuthenticationProvider");
80 TEST_UTIL.getConfiguration().setInt("hbase.zookeeper.property.maxClientCnxns", 1000);
82 // If Hadoop is missing HADOOP-7070 the cluster will fail to start due to
83 // the JAAS configuration required by ZK being clobbered by Hadoop
84 try {
85 TEST_UTIL.startMiniCluster();
86 } catch (IOException e) {
87 LOG.warn("Hadoop is missing HADOOP-7070", e);
88 secureZKAvailable = false;
89 return;
91 zkw = new ZKWatcher(
92 new Configuration(TEST_UTIL.getConfiguration()),
93 TestZooKeeper.class.getName(), null);
96 @AfterClass
97 public static void tearDownAfterClass() throws Exception {
98 if (!secureZKAvailable) {
99 return;
101 TEST_UTIL.shutdownMiniCluster();
104 @Before
105 public void setUp() throws Exception {
106 if (!secureZKAvailable) {
107 return;
109 TEST_UTIL.ensureSomeRegionServersAvailable(2);
113 * Create a node and check its ACL. When authentication is enabled on
114 * ZooKeeper, all nodes (except /hbase/root-region-server, /hbase/master
115 * and /hbase/hbaseid) should be created so that only the hbase server user
116 * (master or region server user) that created them can access them, and
117 * this user should have all permissions on this node. For
118 * /hbase/root-region-server, /hbase/master, and /hbase/hbaseid the
119 * permissions should be as above, but should also be world-readable. First
120 * we check the general case of /hbase nodes in the following test, and
121 * then check the subset of world-readable nodes in the three tests after
122 * that.
124 @Test (timeout=30000)
125 public void testHBaseRootZNodeACL() throws Exception {
126 if (!secureZKAvailable) {
127 return;
130 List<ACL> acls = zkw.getRecoverableZooKeeper().getZooKeeper()
131 .getACL("/hbase", new Stat());
132 assertEquals(1, acls.size());
133 assertEquals("sasl", acls.get(0).getId().getScheme());
134 assertEquals("hbase", acls.get(0).getId().getId());
135 assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
139 * When authentication is enabled on ZooKeeper, /hbase/root-region-server
140 * should be created with 2 ACLs: one specifies that the hbase user has
141 * full access to the node; the other, that it is world-readable.
143 @Test (timeout=30000)
144 public void testHBaseRootRegionServerZNodeACL() throws Exception {
145 if (!secureZKAvailable) {
146 return;
149 List<ACL> acls = zkw.getRecoverableZooKeeper().getZooKeeper()
150 .getACL("/hbase/root-region-server", new Stat());
151 assertEquals(2, acls.size());
153 boolean foundWorldReadableAcl = false;
154 boolean foundHBaseOwnerAcl = false;
155 for(int i = 0; i < 2; i++) {
156 if (acls.get(i).getId().getScheme().equals("world") == true) {
157 assertEquals("anyone", acls.get(0).getId().getId());
158 assertEquals(ZooDefs.Perms.READ, acls.get(0).getPerms());
159 foundWorldReadableAcl = true;
161 else {
162 if (acls.get(i).getId().getScheme().equals("sasl") == true) {
163 assertEquals("hbase", acls.get(1).getId().getId());
164 assertEquals("sasl", acls.get(1).getId().getScheme());
165 foundHBaseOwnerAcl = true;
166 } else { // error: should not get here: test fails.
167 assertTrue(false);
171 assertTrue(foundWorldReadableAcl);
172 assertTrue(foundHBaseOwnerAcl);
176 * When authentication is enabled on ZooKeeper, /hbase/master should be
177 * created with 2 ACLs: one specifies that the hbase user has full access
178 * to the node; the other, that it is world-readable.
180 @Test (timeout=30000)
181 public void testHBaseMasterServerZNodeACL() throws Exception {
182 if (!secureZKAvailable) {
183 return;
186 List<ACL> acls = zkw.getRecoverableZooKeeper().getZooKeeper()
187 .getACL("/hbase/master", new Stat());
188 assertEquals(2, acls.size());
190 boolean foundWorldReadableAcl = false;
191 boolean foundHBaseOwnerAcl = false;
192 for(int i = 0; i < 2; i++) {
193 if (acls.get(i).getId().getScheme().equals("world") == true) {
194 assertEquals("anyone", acls.get(0).getId().getId());
195 assertEquals(ZooDefs.Perms.READ, acls.get(0).getPerms());
196 foundWorldReadableAcl = true;
197 } else {
198 if (acls.get(i).getId().getScheme().equals("sasl") == true) {
199 assertEquals("hbase", acls.get(1).getId().getId());
200 assertEquals("sasl", acls.get(1).getId().getScheme());
201 foundHBaseOwnerAcl = true;
202 } else { // error: should not get here: test fails.
203 assertTrue(false);
207 assertTrue(foundWorldReadableAcl);
208 assertTrue(foundHBaseOwnerAcl);
212 * When authentication is enabled on ZooKeeper, /hbase/hbaseid should be
213 * created with 2 ACLs: one specifies that the hbase user has full access
214 * to the node; the other, that it is world-readable.
216 @Test (timeout=30000)
217 public void testHBaseIDZNodeACL() throws Exception {
218 if (!secureZKAvailable) {
219 return;
222 List<ACL> acls = zkw.getRecoverableZooKeeper().getZooKeeper()
223 .getACL("/hbase/hbaseid", new Stat());
224 assertEquals(2, acls.size());
226 boolean foundWorldReadableAcl = false;
227 boolean foundHBaseOwnerAcl = false;
228 for(int i = 0; i < 2; i++) {
229 if (acls.get(i).getId().getScheme().equals("world") == true) {
230 assertEquals("anyone", acls.get(0).getId().getId());
231 assertEquals(ZooDefs.Perms.READ, acls.get(0).getPerms());
232 foundWorldReadableAcl = true;
233 } else {
234 if (acls.get(i).getId().getScheme().equals("sasl") == true) {
235 assertEquals("hbase", acls.get(1).getId().getId());
236 assertEquals("sasl", acls.get(1).getId().getScheme());
237 foundHBaseOwnerAcl = true;
238 } else { // error: should not get here: test fails.
239 assertTrue(false);
243 assertTrue(foundWorldReadableAcl);
244 assertTrue(foundHBaseOwnerAcl);
248 * Finally, we check the ACLs of a node outside of the /hbase hierarchy and
249 * verify that its ACL is simply 'hbase:Perms.ALL'.
251 @Test
252 public void testOutsideHBaseNodeACL() throws Exception {
253 if (!secureZKAvailable) {
254 return;
257 ZKUtil.createWithParents(zkw, "/testACLNode");
258 List<ACL> acls = zkw.getRecoverableZooKeeper().getZooKeeper()
259 .getACL("/testACLNode", new Stat());
260 assertEquals(1, acls.size());
261 assertEquals("sasl", acls.get(0).getId().getScheme());
262 assertEquals("hbase", acls.get(0).getId().getId());
263 assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
267 * Check if ZooKeeper JaasConfiguration is valid.
269 @Test
270 public void testIsZooKeeperSecure() throws Exception {
271 boolean testJaasConfig =
272 ZKUtil.isSecureZooKeeper(new Configuration(TEST_UTIL.getConfiguration()));
273 assertEquals(testJaasConfig, secureZKAvailable);
274 // Define Jaas configuration without ZooKeeper Jaas config
275 File saslConfFile = File.createTempFile("tmp", "fakeJaas.conf");
276 FileWriter fwriter = new FileWriter(saslConfFile);
278 fwriter.write("");
279 fwriter.close();
280 System.setProperty("java.security.auth.login.config",
281 saslConfFile.getAbsolutePath());
283 testJaasConfig = ZKUtil.isSecureZooKeeper(new Configuration(TEST_UTIL.getConfiguration()));
284 assertEquals(false, testJaasConfig);
285 saslConfFile.delete();
289 * Check if Programmatic way of setting zookeeper security settings is valid.
291 @Test
292 public void testIsZooKeeperSecureWithProgrammaticConfig() throws Exception {
294 javax.security.auth.login.Configuration.setConfiguration(new DummySecurityConfiguration());
296 Configuration config = new Configuration(HBaseConfiguration.create());
297 boolean testJaasConfig = ZKUtil.isSecureZooKeeper(config);
298 assertEquals(false, testJaasConfig);
300 // Now set authentication scheme to Kerberos still it should return false
301 // because no configuration set
302 config.set("hbase.security.authentication", "kerberos");
303 testJaasConfig = ZKUtil.isSecureZooKeeper(config);
304 assertEquals(false, testJaasConfig);
306 // Now set programmatic options related to security
307 config.set(HConstants.ZK_CLIENT_KEYTAB_FILE, "/dummy/file");
308 config.set(HConstants.ZK_CLIENT_KERBEROS_PRINCIPAL, "dummy");
309 config.set(HConstants.ZK_SERVER_KEYTAB_FILE, "/dummy/file");
310 config.set(HConstants.ZK_SERVER_KERBEROS_PRINCIPAL, "dummy");
311 testJaasConfig = ZKUtil.isSecureZooKeeper(config);
312 assertEquals(true, testJaasConfig);
315 private static class DummySecurityConfiguration extends javax.security.auth.login.Configuration {
316 @Override
317 public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
318 return null;
322 @Test(timeout = 10000)
323 public void testAdminDrainAllowedOnSecureZK() throws Exception {
324 if (!secureZKAvailable) {
325 return;
327 List<ServerName> decommissionedServers = new ArrayList<>(1);
328 decommissionedServers.add(ServerName.parseServerName("ZZZ,123,123"));
330 // If unable to connect to secure ZK cluster then this operation would fail.
331 TEST_UTIL.getAdmin().decommissionRegionServers(decommissionedServers, false);
333 decommissionedServers = TEST_UTIL.getAdmin().listDecommissionedRegionServers();
334 assertEquals(1, decommissionedServers.size());
335 assertEquals(ServerName.parseServerName("ZZZ,123,123"), decommissionedServers.get(0));
337 TEST_UTIL.getAdmin().recommissionRegionServer(decommissionedServers.get(0), null);
338 decommissionedServers = TEST_UTIL.getAdmin().listDecommissionedRegionServers();
339 assertEquals(0, decommissionedServers.size());