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 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 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. 17 */ 18 19 package org.apache.zookeeper.test; 20 21 import static org.apache.zookeeper.test.ClientBase.CONNECTION_TIMEOUT; 22 import static org.junit.jupiter.api.Assertions.assertFalse; 23 import static org.junit.jupiter.api.Assertions.assertTrue; 24 import static org.junit.jupiter.api.Assertions.fail; 25 import java.io.File; 26 import java.util.ArrayList; 27 import java.util.List; 28 import java.util.concurrent.CountDownLatch; 29 import org.apache.zookeeper.CreateMode; 30 import org.apache.zookeeper.KeeperException.InvalidACLException; 31 import org.apache.zookeeper.PortAssignment; 32 import org.apache.zookeeper.WatchedEvent; 33 import org.apache.zookeeper.Watcher; 34 import org.apache.zookeeper.Watcher.Event.KeeperState; 35 import org.apache.zookeeper.ZKTestCase; 36 import org.apache.zookeeper.ZooDefs.Ids; 37 import org.apache.zookeeper.ZooKeeper; 38 import org.apache.zookeeper.data.ACL; 39 import org.apache.zookeeper.data.Id; 40 import org.apache.zookeeper.server.ServerCnxn; 41 import org.apache.zookeeper.server.ServerCnxnFactory; 42 import org.apache.zookeeper.server.SyncRequestProcessor; 43 import org.apache.zookeeper.server.ZooKeeperServer; 44 import org.apache.zookeeper.server.auth.IPAuthenticationProvider; 45 import org.junit.jupiter.api.Test; 46 import org.slf4j.Logger; 47 import org.slf4j.LoggerFactory; 48 49 public class ACLTest extends ZKTestCase implements Watcher { 50 51 private static final Logger LOG = LoggerFactory.getLogger(ACLTest.class); 52 private static final String HOSTPORT = "127.0.0.1:" + PortAssignment.unique(); 53 private volatile CountDownLatch startSignal; 54 55 @Test testIPAuthenticationIsValidCIDR()56 public void testIPAuthenticationIsValidCIDR() throws Exception { 57 IPAuthenticationProvider prov = new IPAuthenticationProvider(); 58 assertTrue(prov.isValid("127.0.0.1"), "testing no netmask"); 59 assertTrue(prov.isValid("127.0.0.1/32"), "testing single ip netmask"); 60 assertTrue(prov.isValid("127.0.0.1/0"), "testing lowest netmask possible"); 61 assertFalse(prov.isValid("127.0.0.1/33"), "testing netmask too high"); 62 assertFalse(prov.isValid("10.0.0.1/-1"), "testing netmask too low"); 63 } 64 65 @Test testNettyIpAuthDefault()66 public void testNettyIpAuthDefault() throws Exception { 67 String HOSTPORT = "127.0.0.1:" + PortAssignment.unique(); 68 System.setProperty(ServerCnxnFactory.ZOOKEEPER_SERVER_CNXN_FACTORY, "org.apache.zookeeper.server.NettyServerCnxnFactory"); 69 ClientBase.setupTestEnv(); 70 File tmpDir = ClientBase.createTmpDir(); 71 ZooKeeperServer zks = new ZooKeeperServer(tmpDir, tmpDir, 3000); 72 SyncRequestProcessor.setSnapCount(1000); 73 final int PORT = Integer.parseInt(HOSTPORT.split(":")[1]); 74 ServerCnxnFactory f = ServerCnxnFactory.createFactory(PORT, -1); 75 f.startup(zks); 76 try { 77 LOG.info("starting up the zookeeper server .. waiting"); 78 assertTrue(ClientBase.waitForServerUp(HOSTPORT, CONNECTION_TIMEOUT), "waiting for server being up"); 79 ClientBase.createZKClient(HOSTPORT); 80 for (ServerCnxn cnxn : f.getConnections()) { 81 boolean foundID = false; 82 for (Id id : cnxn.getAuthInfo()) { 83 if (id.getScheme().equals("ip")) { 84 foundID = true; 85 break; 86 } 87 } 88 assertTrue(foundID); 89 } 90 } finally { 91 f.shutdown(); 92 zks.shutdown(); 93 assertTrue(ClientBase.waitForServerDown(HOSTPORT, CONNECTION_TIMEOUT), "waiting for server down"); 94 System.clearProperty(ServerCnxnFactory.ZOOKEEPER_SERVER_CNXN_FACTORY); 95 } 96 } 97 98 @Test testDisconnectedAddAuth()99 public void testDisconnectedAddAuth() throws Exception { 100 File tmpDir = ClientBase.createTmpDir(); 101 ClientBase.setupTestEnv(); 102 ZooKeeperServer zks = new ZooKeeperServer(tmpDir, tmpDir, 3000); 103 SyncRequestProcessor.setSnapCount(1000); 104 final int PORT = Integer.parseInt(HOSTPORT.split(":")[1]); 105 ServerCnxnFactory f = ServerCnxnFactory.createFactory(PORT, -1); 106 f.startup(zks); 107 try { 108 LOG.info("starting up the zookeeper server .. waiting"); 109 assertTrue(ClientBase.waitForServerUp(HOSTPORT, CONNECTION_TIMEOUT), "waiting for server being up"); 110 ZooKeeper zk = ClientBase.createZKClient(HOSTPORT); 111 try { 112 zk.addAuthInfo("digest", "pat:test".getBytes()); 113 zk.setACL("/", Ids.CREATOR_ALL_ACL, -1); 114 } finally { 115 zk.close(); 116 } 117 } finally { 118 f.shutdown(); 119 zks.shutdown(); 120 assertTrue(ClientBase.waitForServerDown(HOSTPORT, ClientBase.CONNECTION_TIMEOUT), "waiting for server down"); 121 } 122 } 123 124 /** 125 * Verify that acl optimization of storing just 126 * a few acls and there references in the data 127 * node is actually working. 128 */ 129 @Test testAcls()130 public void testAcls() throws Exception { 131 File tmpDir = ClientBase.createTmpDir(); 132 ClientBase.setupTestEnv(); 133 ZooKeeperServer zks = new ZooKeeperServer(tmpDir, tmpDir, 3000); 134 SyncRequestProcessor.setSnapCount(1000); 135 final int PORT = Integer.parseInt(HOSTPORT.split(":")[1]); 136 ServerCnxnFactory f = ServerCnxnFactory.createFactory(PORT, -1); 137 f.startup(zks); 138 ZooKeeper zk; 139 String path; 140 try { 141 LOG.info("starting up the zookeeper server .. waiting"); 142 assertTrue(ClientBase.waitForServerUp(HOSTPORT, CONNECTION_TIMEOUT), "waiting for server being up"); 143 zk = ClientBase.createZKClient(HOSTPORT); 144 LOG.info("starting creating acls"); 145 for (int i = 0; i < 100; i++) { 146 path = "/" + i; 147 zk.create(path, path.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); 148 } 149 int size = zks.getZKDatabase().getAclSize(); 150 assertTrue((2 == zks.getZKDatabase().getAclSize()), "size of the acl map "); 151 for (int j = 100; j < 200; j++) { 152 path = "/" + j; 153 ACL acl = new ACL(); 154 acl.setPerms(0); 155 Id id = new Id(); 156 id.setId("1.1.1." + j); 157 id.setScheme("ip"); 158 acl.setId(id); 159 List<ACL> list = new ArrayList<ACL>(); 160 list.add(acl); 161 zk.create(path, path.getBytes(), list, CreateMode.PERSISTENT); 162 } 163 assertTrue((102 == zks.getZKDatabase().getAclSize()), "size of the acl map "); 164 } finally { 165 // now shutdown the server and restart it 166 f.shutdown(); 167 zks.shutdown(); 168 assertTrue(ClientBase.waitForServerDown(HOSTPORT, CONNECTION_TIMEOUT), "waiting for server down"); 169 } 170 171 zks = new ZooKeeperServer(tmpDir, tmpDir, 3000); 172 f = ServerCnxnFactory.createFactory(PORT, -1); 173 174 f.startup(zks); 175 try { 176 assertTrue(ClientBase.waitForServerUp(HOSTPORT, CONNECTION_TIMEOUT), "waiting for server up"); 177 zk = ClientBase.createZKClient(HOSTPORT); 178 assertTrue((102 == zks.getZKDatabase().getAclSize()), "acl map "); 179 for (int j = 200; j < 205; j++) { 180 path = "/" + j; 181 ACL acl = new ACL(); 182 acl.setPerms(0); 183 Id id = new Id(); 184 id.setId("1.1.1." + j); 185 id.setScheme("ip"); 186 acl.setId(id); 187 ArrayList<ACL> list = new ArrayList<ACL>(); 188 list.add(acl); 189 zk.create(path, path.getBytes(), list, CreateMode.PERSISTENT); 190 } 191 assertTrue((107 == zks.getZKDatabase().getAclSize()), "acl map "); 192 193 zk.close(); 194 } finally { 195 f.shutdown(); 196 zks.shutdown(); 197 assertTrue(ClientBase.waitForServerDown(HOSTPORT, ClientBase.CONNECTION_TIMEOUT), "waiting for server down"); 198 } 199 200 } 201 202 /* 203 * (non-Javadoc) 204 * 205 * @see org.apache.zookeeper.Watcher#process(org.apache.zookeeper.WatcherEvent) 206 */ process(WatchedEvent event)207 public void process(WatchedEvent event) { 208 LOG.info("Event:{} {} {}", event.getState(), event.getType(), event.getPath()); 209 if (event.getState() == KeeperState.SyncConnected) { 210 if (startSignal != null && startSignal.getCount() > 0) { 211 LOG.info("startsignal.countDown()"); 212 startSignal.countDown(); 213 } else { 214 LOG.warn("startsignal {}", startSignal); 215 } 216 } 217 } 218 219 @Test testNullACL()220 public void testNullACL() throws Exception { 221 File tmpDir = ClientBase.createTmpDir(); 222 ClientBase.setupTestEnv(); 223 ZooKeeperServer zks = new ZooKeeperServer(tmpDir, tmpDir, 3000); 224 final int PORT = Integer.parseInt(HOSTPORT.split(":")[1]); 225 ServerCnxnFactory f = ServerCnxnFactory.createFactory(PORT, -1); 226 f.startup(zks); 227 ZooKeeper zk = ClientBase.createZKClient(HOSTPORT); 228 try { 229 // case 1 : null ACL with create 230 try { 231 zk.create("/foo", "foo".getBytes(), null, CreateMode.PERSISTENT); 232 fail("Expected InvalidACLException for null ACL parameter"); 233 } catch (InvalidACLException e) { 234 // Expected. Do nothing 235 } 236 237 // case 2 : null ACL with other create API 238 try { 239 zk.create("/foo", "foo".getBytes(), null, CreateMode.PERSISTENT, null); 240 fail("Expected InvalidACLException for null ACL parameter"); 241 } catch (InvalidACLException e) { 242 // Expected. Do nothing 243 } 244 245 // case 3 : null ACL with setACL 246 try { 247 zk.setACL("/foo", null, 0); 248 fail("Expected InvalidACLException for null ACL parameter"); 249 } catch (InvalidACLException e) { 250 // Expected. Do nothing 251 } 252 } finally { 253 zk.close(); 254 f.shutdown(); 255 zks.shutdown(); 256 assertTrue(ClientBase.waitForServerDown(HOSTPORT, ClientBase.CONNECTION_TIMEOUT), "waiting for server down"); 257 } 258 } 259 260 @Test testNullValueACL()261 public void testNullValueACL() throws Exception { 262 File tmpDir = ClientBase.createTmpDir(); 263 ClientBase.setupTestEnv(); 264 ZooKeeperServer zks = new ZooKeeperServer(tmpDir, tmpDir, 3000); 265 final int PORT = Integer.parseInt(HOSTPORT.split(":")[1]); 266 ServerCnxnFactory f = ServerCnxnFactory.createFactory(PORT, -1); 267 f.startup(zks); 268 ZooKeeper zk = ClientBase.createZKClient(HOSTPORT); 269 try { 270 271 List<ACL> acls = new ArrayList<ACL>(); 272 acls.add(null); 273 274 // case 1 : null value in ACL list with create 275 try { 276 zk.create("/foo", "foo".getBytes(), acls, CreateMode.PERSISTENT); 277 fail("Expected InvalidACLException for null value in ACL List"); 278 } catch (InvalidACLException e) { 279 // Expected. Do nothing 280 } 281 282 // case 2 : null value in ACL list with other create API 283 try { 284 zk.create("/foo", "foo".getBytes(), acls, CreateMode.PERSISTENT, null); 285 fail("Expected InvalidACLException for null value in ACL List"); 286 } catch (InvalidACLException e) { 287 // Expected. Do nothing 288 } 289 290 // case 3 : null value in ACL list with setACL 291 try { 292 zk.setACL("/foo", acls, -1); 293 fail("Expected InvalidACLException for null value in ACL List"); 294 } catch (InvalidACLException e) { 295 // Expected. Do nothing 296 } 297 } finally { 298 zk.close(); 299 f.shutdown(); 300 zks.shutdown(); 301 assertTrue(ClientBase.waitForServerDown(HOSTPORT, ClientBase.CONNECTION_TIMEOUT), "waiting for server down"); 302 } 303 } 304 305 } 306