Repository: oozie
Updated Branches:
  refs/heads/branch-4.1 814ef922b -> 6156c383a


OOZIE-1959 TestZKUtilsWithSecurity fails (rkanter)


Project: http://git-wip-us.apache.org/repos/asf/oozie/repo
Commit: http://git-wip-us.apache.org/repos/asf/oozie/commit/6156c383
Tree: http://git-wip-us.apache.org/repos/asf/oozie/tree/6156c383
Diff: http://git-wip-us.apache.org/repos/asf/oozie/diff/6156c383

Branch: refs/heads/branch-4.1
Commit: 6156c383a57ec55c2c66b98d2b60bfae80432850
Parents: 814ef92
Author: Robert Kanter <[email protected]>
Authored: Thu Oct 30 13:37:49 2014 -0700
Committer: Robert Kanter <[email protected]>
Committed: Thu Oct 30 13:37:49 2014 -0700

----------------------------------------------------------------------
 core/pom.xml                                    |  12 --
 .../java/org/apache/oozie/test/ZKXTestCase.java |   2 +-
 .../oozie/test/ZKXTestCaseWithSecurity.java     | 133 -------------
 .../oozie/util/TestZKUtilsWithSecurity.java     | 187 -------------------
 pom.xml                                         |   5 +-
 release-log.txt                                 |   1 +
 zookeeper-security-tests/pom.xml                | 101 ++++++++++
 .../oozie/test/ZKXTestCaseWithSecurity.java     | 134 +++++++++++++
 .../oozie/util/TestZKUtilsWithSecurity.java     | 187 +++++++++++++++++++
 9 files changed, 425 insertions(+), 337 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/oozie/blob/6156c383/core/pom.xml
----------------------------------------------------------------------
diff --git a/core/pom.xml b/core/pom.xml
index c72b50e..8b24575 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -43,12 +43,6 @@
         </dependency>
 
         <dependency>
-            <groupId>org.apache.hadoop</groupId>
-            <artifactId>hadoop-minikdc</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
             <groupId>org.apache.oozie</groupId>
             <artifactId>oozie-hadoop</artifactId>
             <scope>provided</scope>
@@ -467,12 +461,6 @@
                     </dependency>
                 </dependencies>
             </plugin>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <inherited>true</inherited>
-                <extensions>true</extensions>
-            </plugin>
         </plugins>
     </build>
 

http://git-wip-us.apache.org/repos/asf/oozie/blob/6156c383/core/src/test/java/org/apache/oozie/test/ZKXTestCase.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/oozie/test/ZKXTestCase.java 
b/core/src/test/java/org/apache/oozie/test/ZKXTestCase.java
index 4c7d0d7..8465b65 100644
--- a/core/src/test/java/org/apache/oozie/test/ZKXTestCase.java
+++ b/core/src/test/java/org/apache/oozie/test/ZKXTestCase.java
@@ -142,7 +142,7 @@ public abstract class ZKXTestCase extends XDataTestCase {
     }
 
     private void createClient() throws Exception {
-        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
+        RetryPolicy retryPolicy = ZKUtils.getRetryPolicy();
         String zkConnectionString = 
Services.get().getConf().get("oozie.zookeeper.connection.string", 
zkServer.getConnectString());
         String zkNamespace = 
Services.get().getConf().get("oozie.zookeeper.namespace", "oozie");
         client = CuratorFrameworkFactory.builder()

http://git-wip-us.apache.org/repos/asf/oozie/blob/6156c383/core/src/test/java/org/apache/oozie/test/ZKXTestCaseWithSecurity.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/oozie/test/ZKXTestCaseWithSecurity.java 
b/core/src/test/java/org/apache/oozie/test/ZKXTestCaseWithSecurity.java
deleted file mode 100644
index b0b064d..0000000
--- a/core/src/test/java/org/apache/oozie/test/ZKXTestCaseWithSecurity.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.oozie.test;
-
-import java.io.File;
-import javax.security.auth.login.Configuration;
-
-import org.apache.curator.test.TestingServer;
-import org.apache.hadoop.minikdc.MiniKdc;
-import org.apache.oozie.service.HadoopAccessorService;
-import org.apache.oozie.service.Services;
-import org.apache.oozie.util.JaasConfiguration;
-import org.apache.zookeeper.server.ZooKeeperSaslServer;
-
-/**
- * Provides a version of {@link ZKXTestCase} with security.  A MiniKdc will be 
started (so no special outside setup is needed) and
- * the embedded ZooKeeper provided by this class will support connecting to it 
with SASL/Kerberos authentication.  However,
- * currently, the client returned by {@link #getClient()) and the client used 
by DummyZKOozie do not authenticate, so they won't
- * have full access to any znodes with "sasl" ACLs (this is not always true, 
see {@link #setupZKServer()).
- * <p>
- * Anything using {@link ZKUtils} can connect using authentication by simply 
setting "oozie.zookeeper.secure" to "true" before
- * creating the first thing that uses ZKUtils.  Make sure to set it back to 
false when done.
- */
-public abstract class ZKXTestCaseWithSecurity extends ZKXTestCase {
-    private MiniKdc kdc = null;
-    private File keytabFile;
-    private String originalKeytabLoc;
-    private String originalPrincipal;
-
-    /**
-     * The primary part of the principal name for the Kerberos user
-     */
-    protected static final String PRIMARY_PRINCIPAL = "oozie";
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        // Set the keytab location and principal to the miniKDC values
-        originalKeytabLoc = 
Services.get().getConf().get(HadoopAccessorService.KERBEROS_KEYTAB);
-        originalPrincipal = 
Services.get().getConf().get(HadoopAccessorService.KERBEROS_PRINCIPAL);
-        Services.get().getConf().set(HadoopAccessorService.KERBEROS_KEYTAB, 
keytabFile.getAbsolutePath());
-        Services.get().getConf().set(HadoopAccessorService.KERBEROS_PRINCIPAL, 
getPrincipal());
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        // Restore these values
-        Services.get().getConf().set(HadoopAccessorService.KERBEROS_KEYTAB, 
originalKeytabLoc);
-        Services.get().getConf().set(HadoopAccessorService.KERBEROS_PRINCIPAL, 
originalPrincipal);
-        // Just in case the test forgets to set this back
-        Services.get().getConf().set("oozie.zookeeper.secure", "false");
-        super.tearDown();
-        if (kdc != null) {
-            kdc.stop();
-        }
-    }
-
-    /**
-     * Creates and sets up the embedded ZooKeeper server.  Test subclasses 
should have no reason to override this method.
-     * <p>
-     * Here we override it to start the MiniKdc, set the jaas configuration, 
configure ZooKeeper for SASL/Kerberos authentication
-     * and ACLs, and to start the ZooKeeper server.
-     * <p>
-     * Unfortunately, ZooKeeper security requires setting the security for the 
entire JVM.  And for the tests, we're running the
-     * ZK server and one or more clients from the same JVM, so things get 
messy.  There are two ways to tell ZooKeeper to
-     * authenticate: (1) set the system property, 
"java.security.auth.login.config", to a jaas.conf file and (2) create a
-     * javax.security.auth.login.Configuration object with the same info as 
the jaas.conf and set it.  In either case, once set and
-     * something has authenticated, it seems that it can't be unset or 
changed, and there's no way to log out.  By setting the
-     * system property, "javax.security.auth.useSubjectCredsOnly", to "false" 
we can sort-of change the jaas Configuration, but its
-     * kind of funny about it.  Another effect of this is that we have to add 
jaas entries for the "Server" and "Client" here
-     * instead of just the "Server" here and the "Client" in the normal place 
({@link ZKUtils}) or it will be unable to find the
-     * "Client" info.  Also, because there is no way to logout, once any 
client has authenticated once, all subsequent clients will
-     * automatically connect using the same authentication; trying to stop 
this is futile and either results in an error or has no
-     * effect.  This means that there's no way to do any tests with an 
unauthenticated client.  Also, if any tests using secure
-     * ZooKeeper get run before tests not using secure ZooKeeper, they will 
likely fail because it will try to use authentication:
-     * so they should be run separately.
-     *
-     * @return the embedded ZooKeeper server
-     * @throws Exception
-     */
-    @Override
-    protected TestingServer setupZKServer() throws Exception {
-        // Not entirely sure exactly what 
"javax.security.auth.useSubjectCredsOnly=false" does, but it has something to 
do with
-        // re-authenticating in cases where it otherwise wouldn't.  One of the 
sections on this page briefly mentions it:
-        // 
http://docs.oracle.com/javase/7/docs/technotes/guides/security/jgss/tutorials/Troubleshooting.html
-        setSystemProperty("javax.security.auth.useSubjectCredsOnly", "false");
-
-        // Setup KDC and principal
-        kdc = new MiniKdc(MiniKdc.createConf(), new File(getTestCaseDir()));
-        kdc.start();
-        keytabFile = new File(getTestCaseDir(), "test.keytab");
-        String serverPrincipal = "zookeeper/" + kdc.getHost();
-        kdc.createPrincipal(keytabFile, getPrincipal(), serverPrincipal);
-
-        setSystemProperty("zookeeper.authProvider.1", 
"org.apache.zookeeper.server.auth.SASLAuthenticationProvider");
-        setSystemProperty("zookeeper.kerberos.removeHostFromPrincipal", 
"true");
-        setSystemProperty("zookeeper.kerberos.removeRealmFromPrincipal", 
"true");
-
-        JaasConfiguration.addEntry("Server", serverPrincipal, 
keytabFile.getAbsolutePath());
-        // Here's where we add the "Client" to the jaas configuration, even 
though we'd like not to
-        JaasConfiguration.addEntry("Client", getPrincipal(), 
keytabFile.getAbsolutePath());
-        Configuration.setConfiguration(JaasConfiguration.getInstance());
-
-        setSystemProperty(ZooKeeperSaslServer.LOGIN_CONTEXT_NAME_KEY, 
"Server");
-
-        return new TestingServer();
-    }
-
-    /**
-     * Returns the principal of the Kerberos user.  This would be {@link 
#PRIMARY_PRINCIPAL}/_host_
-     *
-     * @return the principal of the Kerberos user
-     */
-    protected String getPrincipal() {
-        return PRIMARY_PRINCIPAL + "/" + kdc.getHost();
-    }
-}
-

http://git-wip-us.apache.org/repos/asf/oozie/blob/6156c383/core/src/test/java/org/apache/oozie/util/TestZKUtilsWithSecurity.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/apache/oozie/util/TestZKUtilsWithSecurity.java 
b/core/src/test/java/org/apache/oozie/util/TestZKUtilsWithSecurity.java
deleted file mode 100644
index af35594..0000000
--- a/core/src/test/java/org/apache/oozie/util/TestZKUtilsWithSecurity.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.oozie.util;
-
-import java.util.List;
-import static junit.framework.Assert.assertEquals;
-
-import org.apache.oozie.lock.LockToken;
-import org.apache.oozie.service.Services;
-import org.apache.oozie.service.ZKLocksService;
-import org.apache.oozie.test.ZKXTestCaseWithSecurity;
-import org.apache.zookeeper.ZooDefs;
-import org.apache.zookeeper.data.ACL;
-import org.apache.zookeeper.data.Stat;
-
-public class TestZKUtilsWithSecurity extends ZKXTestCaseWithSecurity {
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-    }
-
-    public void testCheckAndSetACLs() throws Exception {
-        // We want to verify the ACLs on locks and the service discovery; 
ZKUtils does the service discovery and starting
-        // ZKLocksService will use ZKUtils which will start advertising on the 
service discovery.  We can also acquire a lock so
-        // it will create a lock znode.
-        ZKLocksService zkls = new ZKLocksService();
-        try {
-            zkls.init(Services.get());
-            LockToken lock = zkls.getWriteLock("foo", 3);
-            lock.release();
-            List<ACL> acls = 
getClient().getZookeeperClient().getZooKeeper().getACL("/oozie", new Stat());
-            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
-            assertEquals("world", acls.get(0).getId().getScheme());
-            assertEquals("anyone", acls.get(0).getId().getId());
-            acls = getClient().getACL().forPath("/locks");
-            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
-            assertEquals("world", acls.get(0).getId().getScheme());
-            assertEquals("anyone", acls.get(0).getId().getId());
-            acls = getClient().getACL().forPath("/locks/foo");
-            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
-            assertEquals("world", acls.get(0).getId().getScheme());
-            assertEquals("anyone", acls.get(0).getId().getId());
-            acls = getClient().getACL().forPath("/services");
-            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
-            assertEquals("world", acls.get(0).getId().getScheme());
-            assertEquals("anyone", acls.get(0).getId().getId());
-            acls = getClient().getACL().forPath("/services/servers");
-            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
-            assertEquals("world", acls.get(0).getId().getScheme());
-            assertEquals("anyone", acls.get(0).getId().getId());
-            acls = getClient().getACL().forPath("/services/servers/" + ZK_ID);
-            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
-            assertEquals("world", acls.get(0).getId().getScheme());
-            assertEquals("anyone", acls.get(0).getId().getId());
-        }
-        finally {
-            // unregistering all users of ZKUtils (i.e. ZKLocksService) will 
cause it to disconnect so when we set
-            // "oozie.zookeeper.secure" to true, it will again connect but 
using SASL/Kerberos
-            zkls.destroy();
-        }
-
-        // Verify that the expected paths created above still exist with the 
"world" ACLs
-        List<ACL> acls = 
getClient().getZookeeperClient().getZooKeeper().getACL("/oozie", new Stat());
-        assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
-        assertEquals("world", acls.get(0).getId().getScheme());
-        assertEquals("anyone", acls.get(0).getId().getId());
-        acls = getClient().getACL().forPath("/locks");
-        assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
-        assertEquals("world", acls.get(0).getId().getScheme());
-        assertEquals("anyone", acls.get(0).getId().getId());
-        acls = getClient().getACL().forPath("/locks/foo");
-        assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
-        assertEquals("world", acls.get(0).getId().getScheme());
-        assertEquals("anyone", acls.get(0).getId().getId());
-        acls = getClient().getACL().forPath("/services");
-        assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
-        assertEquals("world", acls.get(0).getId().getScheme());
-        assertEquals("anyone", acls.get(0).getId().getId());
-        acls = getClient().getACL().forPath("/services/servers");
-        assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
-        assertEquals("world", acls.get(0).getId().getScheme());
-        assertEquals("anyone", acls.get(0).getId().getId());
-
-        zkls = new ZKLocksService();
-        try {
-            Services.get().getConf().set("oozie.zookeeper.secure", "true");
-            // Now that security is enabled, it will trigger the 
checkAndSetACLs() code to go through and set all of the previously
-            // created znodes to have "sasl" ACLs
-            zkls.init(Services.get());
-            acls = 
getClient().getZookeeperClient().getZooKeeper().getACL("/oozie", new Stat());
-            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
-            assertEquals("sasl", acls.get(0).getId().getScheme());
-            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
-            acls = getClient().getACL().forPath("/locks");
-            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
-            assertEquals("sasl", acls.get(0).getId().getScheme());
-            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
-            acls = getClient().getACL().forPath("/locks/foo");
-            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
-            assertEquals("sasl", acls.get(0).getId().getScheme());
-            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
-            acls = getClient().getACL().forPath("/services");
-            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
-            assertEquals("sasl", acls.get(0).getId().getScheme());
-            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
-            acls = getClient().getACL().forPath("/services/servers");
-            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
-            assertEquals("sasl", acls.get(0).getId().getScheme());
-            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
-            acls = getClient().getACL().forPath("/services/servers/" + ZK_ID);
-            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
-            assertEquals("sasl", acls.get(0).getId().getScheme());
-            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
-        }
-        finally {
-            zkls.destroy();
-            Services.get().getConf().set("oozie.zookeeper.secure", "false");
-        }
-    }
-
-    public void testNewUsingACLs() throws Exception {
-        // We want to verify the ACLs on new locks and the service discovery; 
ZKUtils does the service discovery and starting
-        // ZKLocksService will use ZKUtils which will start advertising on the 
service discovery.  We can also acquire a lock so
-        // it will create a lock znode.
-        ZKLocksService zkls = new ZKLocksService();
-        try {
-            Services.get().getConf().set("oozie.zookeeper.secure", "true");
-            // Verify that the znodes don't already exist
-            
assertNull(getClient().getZookeeperClient().getZooKeeper().exists("/oozie", 
null));
-            assertNull(getClient().checkExists().forPath("/locks"));
-            assertNull(getClient().checkExists().forPath("/services"));
-            // Check that new znodes will use the ACLs
-            zkls.init(Services.get());
-            LockToken lock = zkls.getWriteLock("foo", 3);
-            lock.release();
-            List<ACL> acls = 
getClient().getZookeeperClient().getZooKeeper().getACL("/oozie", new Stat());
-            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
-            assertEquals("sasl", acls.get(0).getId().getScheme());
-            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
-            acls = getClient().getACL().forPath("/locks");
-            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
-            assertEquals("sasl", acls.get(0).getId().getScheme());
-            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
-            acls = getClient().getACL().forPath("/locks/foo");
-            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
-            assertEquals("sasl", acls.get(0).getId().getScheme());
-            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
-            acls = getClient().getACL().forPath("/services");
-            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
-            assertEquals("sasl", acls.get(0).getId().getScheme());
-            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
-            acls = getClient().getACL().forPath("/services/servers");
-            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
-            assertEquals("sasl", acls.get(0).getId().getScheme());
-            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
-            acls = getClient().getACL().forPath("/services/servers/" + ZK_ID);
-            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
-            assertEquals("sasl", acls.get(0).getId().getScheme());
-            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
-        }
-        finally {
-            zkls.destroy();
-            Services.get().getConf().set("oozie.zookeeper.secure", "false");
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/oozie/blob/6156c383/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 0b01fee..c2acf6c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -113,6 +113,7 @@
         <module>tools</module>
         <module>minitest</module>
         <module>distro</module>
+        <module>zookeeper-security-tests</module>
     </modules>
 
     <distributionManagement>
@@ -1030,10 +1031,6 @@
                         -->
                         
<exclude>**/TestMapReduceActionExecutorUberJar.java</exclude>
 
-                        <!-- Explictly use -Dtest=TestZKUtilsWithSecurity to 
test the ZKUtils with security.
-                             It can conflict with other non-secure tests that 
use zookeeper
-                        -->
-                        <exclude>**/TestZKUtilsWithSecurity.java</exclude>
                     </excludes>
                     <!-- DO NOT CHANGE THIS VALUES, TESTCASES CANNOT RUN IN 
PARALLEL -->
                     <parallel>classes</parallel>

http://git-wip-us.apache.org/repos/asf/oozie/blob/6156c383/release-log.txt
----------------------------------------------------------------------
diff --git a/release-log.txt b/release-log.txt
index 0d2370e..9818664 100644
--- a/release-log.txt
+++ b/release-log.txt
@@ -1,5 +1,6 @@
 -- Oozie 4.1.0 release (4.1 - unreleased)
 
+OOZIE-1959 TestZKUtilsWithSecurity fails (rkanter)
 OOZIE-2033 HA and misc improvements to SSL docs (rkanter)
 OOZIE-1789 Support backward compatibility of oozie share lib (shwethags)
 OOZIE-2047 Oozie does not support Hive tables that use datatypes introduced 
since Hive 0.8 (venkatnrangan via bzhang)

http://git-wip-us.apache.org/repos/asf/oozie/blob/6156c383/zookeeper-security-tests/pom.xml
----------------------------------------------------------------------
diff --git a/zookeeper-security-tests/pom.xml b/zookeeper-security-tests/pom.xml
new file mode 100644
index 0000000..04c36a4
--- /dev/null
+++ b/zookeeper-security-tests/pom.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.oozie</groupId>
+        <artifactId>oozie-main</artifactId>
+        <version>4.1.0-SNAPSHOT</version>
+    </parent>
+    <groupId>org.apache.oozie</groupId>
+    <artifactId>oozie-zookeeper-security-tests</artifactId>
+    <version>4.1.0-SNAPSHOT</version>
+    <description>Apache Oozie ZooKeeper Security Tests</description>
+    <name>Apache Oozie ZooKeeper Security Tests</name>
+    <packaging>jar</packaging>
+
+    <!-- The unit tests in here change JVM level security configs in such a 
way that tests non expecting them would
+         fail.  In order to not interfere with other tests, these unit tests 
need to be run in their own JVM, which
+         happens when they're in a separate module -->
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.curator</groupId>
+            <artifactId>curator-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.hadoop</groupId>
+            <artifactId>hadoop-minikdc</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.oozie</groupId>
+            <artifactId>oozie-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.oozie</groupId>
+            <artifactId>oozie-core</artifactId>
+            <classifier>tests</classifier>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.oozie</groupId>
+            <artifactId>oozie-hadoop</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+           <groupId>org.apache.oozie</groupId>
+           <artifactId>oozie-hadoop-test</artifactId>
+           <scope>test</scope>
+       </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.rat</groupId>
+                <artifactId>apache-rat-plugin</artifactId>
+                <configuration>
+                    <excludeSubProjects>false</excludeSubProjects>
+                    <excludes>
+                        <!-- excluding all as the root POM does the full 
check-->
+                        <exclude>**</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+            <!-- Required for MiniKDC -->
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <inherited>true</inherited>
+                <extensions>true</extensions>
+            </plugin>
+        </plugins>
+    </build>
+</project>

http://git-wip-us.apache.org/repos/asf/oozie/blob/6156c383/zookeeper-security-tests/src/test/java/org/apache/oozie/test/ZKXTestCaseWithSecurity.java
----------------------------------------------------------------------
diff --git 
a/zookeeper-security-tests/src/test/java/org/apache/oozie/test/ZKXTestCaseWithSecurity.java
 
b/zookeeper-security-tests/src/test/java/org/apache/oozie/test/ZKXTestCaseWithSecurity.java
new file mode 100644
index 0000000..56ff98d
--- /dev/null
+++ 
b/zookeeper-security-tests/src/test/java/org/apache/oozie/test/ZKXTestCaseWithSecurity.java
@@ -0,0 +1,134 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.oozie.test;
+
+import java.io.File;
+import javax.security.auth.login.Configuration;
+
+import org.apache.curator.test.TestingServer;
+import org.apache.hadoop.minikdc.MiniKdc;
+import org.apache.oozie.service.HadoopAccessorService;
+import org.apache.oozie.service.Services;
+import org.apache.oozie.util.JaasConfiguration;
+import org.apache.zookeeper.server.ZooKeeperSaslServer;
+
+/**
+ * Provides a version of {@link ZKXTestCase} with security.  A MiniKdc will be 
started (so no special outside setup is needed) and
+ * the embedded ZooKeeper provided by this class will support connecting to it 
with SASL/Kerberos authentication.  However,
+ * currently, the client returned by {@link #getClient()) and the client used 
by DummyZKOozie do not authenticate, so they won't
+ * have full access to any znodes with "sasl" ACLs (this is not always true, 
see {@link #setupZKServer()).
+ * <p>
+ * Anything using {@link ZKUtils} can connect using authentication by simply 
setting "oozie.zookeeper.secure" to "true" before
+ * creating the first thing that uses ZKUtils.  Make sure to set it back to 
false when done.
+ */
+public abstract class ZKXTestCaseWithSecurity extends ZKXTestCase {
+    private MiniKdc kdc = null;
+    private File keytabFile;
+    private String originalKeytabLoc;
+    private String originalPrincipal;
+
+    /**
+     * The primary part of the principal name for the Kerberos user
+     */
+    protected static final String PRIMARY_PRINCIPAL = "oozie";
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        // Set the keytab location and principal to the miniKDC values
+        originalKeytabLoc = 
Services.get().getConf().get(HadoopAccessorService.KERBEROS_KEYTAB);
+        originalPrincipal = 
Services.get().getConf().get(HadoopAccessorService.KERBEROS_PRINCIPAL);
+        Services.get().getConf().set(HadoopAccessorService.KERBEROS_KEYTAB, 
keytabFile.getAbsolutePath());
+        Services.get().getConf().set(HadoopAccessorService.KERBEROS_PRINCIPAL, 
getPrincipal());
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        // Restore these values
+        Services.get().getConf().set(HadoopAccessorService.KERBEROS_KEYTAB, 
originalKeytabLoc);
+        Services.get().getConf().set(HadoopAccessorService.KERBEROS_PRINCIPAL, 
originalPrincipal);
+        // Just in case the test forgets to set this back
+        Services.get().getConf().set("oozie.zookeeper.secure", "false");
+        super.tearDown();
+        if (kdc != null) {
+            kdc.stop();
+        }
+    }
+
+    /**
+     * Creates and sets up the embedded ZooKeeper server.  Test subclasses 
should have no reason to override this method.
+     * <p>
+     * Here we override it to start the MiniKdc, set the jaas configuration, 
configure ZooKeeper for SASL/Kerberos authentication
+     * and ACLs, and to start the ZooKeeper server.
+     * <p>
+     * Unfortunately, ZooKeeper security requires setting the security for the 
entire JVM.  And for the tests, we're running the
+     * ZK server and one or more clients from the same JVM, so things get 
messy.  There are two ways to tell ZooKeeper to
+     * authenticate: (1) set the system property, 
"java.security.auth.login.config", to a jaas.conf file and (2) create a
+     * javax.security.auth.login.Configuration object with the same info as 
the jaas.conf and set it.  In either case, once set and
+     * something has authenticated, it seems that it can't be unset or 
changed, and there's no way to log out.  By setting the
+     * system property, "javax.security.auth.useSubjectCredsOnly", to "false" 
we can sort-of change the jaas Configuration, but its
+     * kind of funny about it.  Another effect of this is that we have to add 
jaas entries for the "Server" and "Client" here
+     * instead of just the "Server" here and the "Client" in the normal place 
({@link ZKUtils}) or it will be unable to find the
+     * "Client" info.  Also, because there is no way to logout, once any 
client has authenticated once, all subsequent clients will
+     * automatically connect using the same authentication; trying to stop 
this is futile and either results in an error or has no
+     * effect.  This means that there's no way to do any tests with an 
unauthenticated client.  Also, if any tests using secure
+     * ZooKeeper get run before tests not using secure ZooKeeper, they will 
likely fail because it will try to use authentication:
+     * so they should be run separately.  For this reason, the secure tests 
should be run in a separate module where they will get
+     * their own JVM.
+     *
+     * @return the embedded ZooKeeper server
+     * @throws Exception
+     */
+    @Override
+    protected TestingServer setupZKServer() throws Exception {
+        // Not entirely sure exactly what 
"javax.security.auth.useSubjectCredsOnly=false" does, but it has something to 
do with
+        // re-authenticating in cases where it otherwise wouldn't.  One of the 
sections on this page briefly mentions it:
+        // 
http://docs.oracle.com/javase/7/docs/technotes/guides/security/jgss/tutorials/Troubleshooting.html
+        setSystemProperty("javax.security.auth.useSubjectCredsOnly", "false");
+
+        // Setup KDC and principal
+        kdc = new MiniKdc(MiniKdc.createConf(), new File(getTestCaseDir()));
+        kdc.start();
+        keytabFile = new File(getTestCaseDir(), "test.keytab");
+        String serverPrincipal = "zookeeper/127.0.0.1";
+        kdc.createPrincipal(keytabFile, getPrincipal(), serverPrincipal);
+
+        setSystemProperty("zookeeper.authProvider.1", 
"org.apache.zookeeper.server.auth.SASLAuthenticationProvider");
+        setSystemProperty("zookeeper.kerberos.removeHostFromPrincipal", 
"true");
+        setSystemProperty("zookeeper.kerberos.removeRealmFromPrincipal", 
"true");
+
+        JaasConfiguration.addEntry("Server", serverPrincipal, 
keytabFile.getAbsolutePath());
+        // Here's where we add the "Client" to the jaas configuration, even 
though we'd like not to
+        JaasConfiguration.addEntry("Client", getPrincipal(), 
keytabFile.getAbsolutePath());
+        Configuration.setConfiguration(JaasConfiguration.getInstance());
+
+        setSystemProperty(ZooKeeperSaslServer.LOGIN_CONTEXT_NAME_KEY, 
"Server");
+
+        return new TestingServer();
+    }
+
+    /**
+     * Returns the principal of the Kerberos user.  This would be {@link 
#PRIMARY_PRINCIPAL}/_host_
+     *
+     * @return the principal of the Kerberos user
+     */
+    protected String getPrincipal() {
+        return PRIMARY_PRINCIPAL + "/" + kdc.getHost();
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/oozie/blob/6156c383/zookeeper-security-tests/src/test/java/org/apache/oozie/util/TestZKUtilsWithSecurity.java
----------------------------------------------------------------------
diff --git 
a/zookeeper-security-tests/src/test/java/org/apache/oozie/util/TestZKUtilsWithSecurity.java
 
b/zookeeper-security-tests/src/test/java/org/apache/oozie/util/TestZKUtilsWithSecurity.java
new file mode 100644
index 0000000..af35594
--- /dev/null
+++ 
b/zookeeper-security-tests/src/test/java/org/apache/oozie/util/TestZKUtilsWithSecurity.java
@@ -0,0 +1,187 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.oozie.util;
+
+import java.util.List;
+import static junit.framework.Assert.assertEquals;
+
+import org.apache.oozie.lock.LockToken;
+import org.apache.oozie.service.Services;
+import org.apache.oozie.service.ZKLocksService;
+import org.apache.oozie.test.ZKXTestCaseWithSecurity;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.data.ACL;
+import org.apache.zookeeper.data.Stat;
+
+public class TestZKUtilsWithSecurity extends ZKXTestCaseWithSecurity {
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    public void testCheckAndSetACLs() throws Exception {
+        // We want to verify the ACLs on locks and the service discovery; 
ZKUtils does the service discovery and starting
+        // ZKLocksService will use ZKUtils which will start advertising on the 
service discovery.  We can also acquire a lock so
+        // it will create a lock znode.
+        ZKLocksService zkls = new ZKLocksService();
+        try {
+            zkls.init(Services.get());
+            LockToken lock = zkls.getWriteLock("foo", 3);
+            lock.release();
+            List<ACL> acls = 
getClient().getZookeeperClient().getZooKeeper().getACL("/oozie", new Stat());
+            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
+            assertEquals("world", acls.get(0).getId().getScheme());
+            assertEquals("anyone", acls.get(0).getId().getId());
+            acls = getClient().getACL().forPath("/locks");
+            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
+            assertEquals("world", acls.get(0).getId().getScheme());
+            assertEquals("anyone", acls.get(0).getId().getId());
+            acls = getClient().getACL().forPath("/locks/foo");
+            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
+            assertEquals("world", acls.get(0).getId().getScheme());
+            assertEquals("anyone", acls.get(0).getId().getId());
+            acls = getClient().getACL().forPath("/services");
+            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
+            assertEquals("world", acls.get(0).getId().getScheme());
+            assertEquals("anyone", acls.get(0).getId().getId());
+            acls = getClient().getACL().forPath("/services/servers");
+            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
+            assertEquals("world", acls.get(0).getId().getScheme());
+            assertEquals("anyone", acls.get(0).getId().getId());
+            acls = getClient().getACL().forPath("/services/servers/" + ZK_ID);
+            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
+            assertEquals("world", acls.get(0).getId().getScheme());
+            assertEquals("anyone", acls.get(0).getId().getId());
+        }
+        finally {
+            // unregistering all users of ZKUtils (i.e. ZKLocksService) will 
cause it to disconnect so when we set
+            // "oozie.zookeeper.secure" to true, it will again connect but 
using SASL/Kerberos
+            zkls.destroy();
+        }
+
+        // Verify that the expected paths created above still exist with the 
"world" ACLs
+        List<ACL> acls = 
getClient().getZookeeperClient().getZooKeeper().getACL("/oozie", new Stat());
+        assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
+        assertEquals("world", acls.get(0).getId().getScheme());
+        assertEquals("anyone", acls.get(0).getId().getId());
+        acls = getClient().getACL().forPath("/locks");
+        assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
+        assertEquals("world", acls.get(0).getId().getScheme());
+        assertEquals("anyone", acls.get(0).getId().getId());
+        acls = getClient().getACL().forPath("/locks/foo");
+        assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
+        assertEquals("world", acls.get(0).getId().getScheme());
+        assertEquals("anyone", acls.get(0).getId().getId());
+        acls = getClient().getACL().forPath("/services");
+        assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
+        assertEquals("world", acls.get(0).getId().getScheme());
+        assertEquals("anyone", acls.get(0).getId().getId());
+        acls = getClient().getACL().forPath("/services/servers");
+        assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
+        assertEquals("world", acls.get(0).getId().getScheme());
+        assertEquals("anyone", acls.get(0).getId().getId());
+
+        zkls = new ZKLocksService();
+        try {
+            Services.get().getConf().set("oozie.zookeeper.secure", "true");
+            // Now that security is enabled, it will trigger the 
checkAndSetACLs() code to go through and set all of the previously
+            // created znodes to have "sasl" ACLs
+            zkls.init(Services.get());
+            acls = 
getClient().getZookeeperClient().getZooKeeper().getACL("/oozie", new Stat());
+            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
+            assertEquals("sasl", acls.get(0).getId().getScheme());
+            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
+            acls = getClient().getACL().forPath("/locks");
+            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
+            assertEquals("sasl", acls.get(0).getId().getScheme());
+            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
+            acls = getClient().getACL().forPath("/locks/foo");
+            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
+            assertEquals("sasl", acls.get(0).getId().getScheme());
+            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
+            acls = getClient().getACL().forPath("/services");
+            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
+            assertEquals("sasl", acls.get(0).getId().getScheme());
+            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
+            acls = getClient().getACL().forPath("/services/servers");
+            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
+            assertEquals("sasl", acls.get(0).getId().getScheme());
+            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
+            acls = getClient().getACL().forPath("/services/servers/" + ZK_ID);
+            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
+            assertEquals("sasl", acls.get(0).getId().getScheme());
+            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
+        }
+        finally {
+            zkls.destroy();
+            Services.get().getConf().set("oozie.zookeeper.secure", "false");
+        }
+    }
+
+    public void testNewUsingACLs() throws Exception {
+        // We want to verify the ACLs on new locks and the service discovery; 
ZKUtils does the service discovery and starting
+        // ZKLocksService will use ZKUtils which will start advertising on the 
service discovery.  We can also acquire a lock so
+        // it will create a lock znode.
+        ZKLocksService zkls = new ZKLocksService();
+        try {
+            Services.get().getConf().set("oozie.zookeeper.secure", "true");
+            // Verify that the znodes don't already exist
+            
assertNull(getClient().getZookeeperClient().getZooKeeper().exists("/oozie", 
null));
+            assertNull(getClient().checkExists().forPath("/locks"));
+            assertNull(getClient().checkExists().forPath("/services"));
+            // Check that new znodes will use the ACLs
+            zkls.init(Services.get());
+            LockToken lock = zkls.getWriteLock("foo", 3);
+            lock.release();
+            List<ACL> acls = 
getClient().getZookeeperClient().getZooKeeper().getACL("/oozie", new Stat());
+            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
+            assertEquals("sasl", acls.get(0).getId().getScheme());
+            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
+            acls = getClient().getACL().forPath("/locks");
+            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
+            assertEquals("sasl", acls.get(0).getId().getScheme());
+            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
+            acls = getClient().getACL().forPath("/locks/foo");
+            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
+            assertEquals("sasl", acls.get(0).getId().getScheme());
+            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
+            acls = getClient().getACL().forPath("/services");
+            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
+            assertEquals("sasl", acls.get(0).getId().getScheme());
+            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
+            acls = getClient().getACL().forPath("/services/servers");
+            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
+            assertEquals("sasl", acls.get(0).getId().getScheme());
+            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
+            acls = getClient().getACL().forPath("/services/servers/" + ZK_ID);
+            assertEquals(ZooDefs.Perms.ALL, acls.get(0).getPerms());
+            assertEquals("sasl", acls.get(0).getId().getScheme());
+            assertEquals(PRIMARY_PRINCIPAL, acls.get(0).getId().getId());
+        }
+        finally {
+            zkls.destroy();
+            Services.get().getConf().set("oozie.zookeeper.secure", "false");
+        }
+    }
+}

Reply via email to