You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by st...@apache.org on 2016/12/23 15:06:28 UTC

ambari git commit: AMBARI-19187. Disable security hook. (Attila Magyar via stoader)

Repository: ambari
Updated Branches:
  refs/heads/trunk 2f311bedd -> 2f2c9cc58


AMBARI-19187. Disable security hook. (Attila Magyar via stoader)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/2f2c9cc5
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/2f2c9cc5
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/2f2c9cc5

Branch: refs/heads/trunk
Commit: 2f2c9cc588fca9522a159902d3e7db560877ff98
Parents: 2f311be
Author: Attila Magyar <am...@hortonworks.com>
Authored: Fri Dec 23 16:03:31 2016 +0100
Committer: Toader, Sebastian <st...@hortonworks.com>
Committed: Fri Dec 23 16:03:51 2016 +0100

----------------------------------------------------------------------
 ambari-agent/pom.xml                            |  64 +++++++-
 .../java/org/apache/ambari/tools/zk/ZkAcl.java  | 107 +++++++++++++
 .../apache/ambari/tools/zk/ZkConnection.java    |  53 +++++++
 .../org/apache/ambari/tools/zk/ZkMigrator.java  |  86 +++++++++++
 .../apache/ambari/tools/zk/ZkMigratorTest.java  | 154 +++++++++++++++++++
 .../core/resources/zkmigrator.py                |  44 ++++++
 .../libraries/script/script.py                  |   6 +
 ambari-server/pom.xml                           |   1 +
 .../server/controller/KerberosHelperImpl.java   |  81 ++++++++++
 .../ambari/server/metadata/ActionMetadata.java  |   1 +
 .../server/controller/KerberosHelperTest.java   |  23 ++-
 .../main/admin/kerberos/disable_controller.js   |  10 +-
 ambari-web/app/messages.js                      |  10 +-
 13 files changed, 628 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2c9cc5/ambari-agent/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-agent/pom.xml b/ambari-agent/pom.xml
index a8ed7f1..35fba19 100644
--- a/ambari-agent/pom.xml
+++ b/ambari-agent/pom.xml
@@ -25,7 +25,6 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>org.apache.ambari</groupId>
   <artifactId>ambari-agent</artifactId>
-  <packaging>pom</packaging>
   <version>2.0.0.0-SNAPSHOT</version>
   <name>Ambari Agent</name>
   <description>Ambari Agent</description>
@@ -52,6 +51,41 @@
     <customActionsLocation>${target.cache.dir}/custom_actions</customActionsLocation>
     <empty.dir>src/packages/tarball</empty.dir> <!-- any directory in project with not very big amount of files (not to waste-load them) -->
   </properties>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.zookeeper</groupId>
+      <artifactId>zookeeper</artifactId>
+      <version>3.4.9</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-cli</groupId>
+      <artifactId>commons-cli</artifactId>
+      <version>1.3.1</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.curator</groupId>
+      <artifactId>curator-test</artifactId>
+      <version>2.9.0</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.curator</groupId>
+      <artifactId>curator-framework</artifactId>
+      <version>2.7.1</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>utility</groupId>
+      <artifactId>utility</artifactId>
+      <scope>test</scope>
+      <version>1.0.0.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
   <build>
     <plugins>
       <plugin>
@@ -84,12 +118,39 @@
       <plugin>
         <artifactId>maven-compiler-plugin</artifactId>
         <version>3.0</version>
+        <configuration>
+          <source>1.7</source>
+          <target>1.7</target>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-shade-plugin</artifactId>
+        <version>2.3</version>
+        <executions>
+          <execution>
+            <phase>package</phase>
+            <goals>
+              <goal>shade</goal>
+            </goals>
+            <configuration>
+              <transformers>
+                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                  <mainClass>org.apache.ambari.tools.zk.ZkMigrator</mainClass>
+                </transformer>
+              </transformers>
+              <outputFile>${project.build.directory}${dirsep}${project.artifactId}-${project.version}/var/lib/ambari-agent/tools/zkmigrator.jar</outputFile>
+            </configuration>
+          </execution>
+        </executions>
       </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
           <skip>${skipSurefireTests}</skip>
+          <!-- Each profile in the top-level pom.xml defines which test group categories to run. -->
+          <groups>${testcase.groups}</groups>
         </configuration>
       </plugin>
       <plugin>
@@ -462,6 +523,7 @@
             <exclude>**/*.json</exclude>
             <exclude>**/*.pydevproject</exclude>
             <exclude>src/main/package/choco/ambari-agent.nuspec</exclude>
+            <exclude>**/dependency-reduced-pom.xml</exclude>
           </excludes>
         </configuration>
         <executions>

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2c9cc5/ambari-agent/src/main/java/org/apache/ambari/tools/zk/ZkAcl.java
----------------------------------------------------------------------
diff --git a/ambari-agent/src/main/java/org/apache/ambari/tools/zk/ZkAcl.java b/ambari-agent/src/main/java/org/apache/ambari/tools/zk/ZkAcl.java
new file mode 100644
index 0000000..420ab0a
--- /dev/null
+++ b/ambari-agent/src/main/java/org/apache/ambari/tools/zk/ZkAcl.java
@@ -0,0 +1,107 @@
+/**
+ * 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.ambari.tools.zk;
+
+import static java.util.Collections.singletonList;
+
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.data.ACL;
+import org.apache.zookeeper.data.Id;
+
+/**
+ * ZkAcl represent a ZooKeeper ACL (scheme, id and permissions)
+ */
+public class ZkAcl {
+  private static final int ANY_NODE_VER = -1;
+  private final AclScheme scheme;
+  private final String id;
+  private final Permission permission;
+
+  /**
+   * Creates an instance of me by parsing the given string
+   * @param acl in the following format scheme:id:permissions e.g.: world:anyone:crdw
+     */
+  public static ZkAcl parse(String acl) {
+    String[] parts = acl.split(":");
+    if (parts.length != 3) {
+      throw new IllegalArgumentException("Invalid ACL: " + acl + " must be <scheme:id:permission>");
+    }
+    return new ZkAcl(AclScheme.parse(parts[0]), parts[1], Permission.parse(parts[2]));
+  }
+
+  private ZkAcl(AclScheme scheme, String id, Permission permission) {
+    this.scheme = scheme;
+    this.id = id;
+    this.permission = permission;
+  }
+
+  /**
+   * Sets the ACL on the given znode according to my state
+   */
+  public void setRecursivelyOn(ZooKeeper zkClient, String node) throws KeeperException, InterruptedException {
+    zkClient.setACL(node, singletonList(new ACL(permission.code, new Id(scheme.value, id))), ANY_NODE_VER);
+    for (String child : zkClient.getChildren(node, null)) {
+      setRecursivelyOn(zkClient, path(node, child));
+    }
+  }
+
+  private String path(String node, String child) {
+    return node.endsWith("/") ? node + child : node + "/" + child;
+  }
+
+  static class AclScheme {
+    final String value;
+
+    public static AclScheme parse(String scheme) {
+      if (scheme.toLowerCase().equals("world") || scheme.toLowerCase().equals("ip")) {
+        return new AclScheme(scheme);
+      }
+      throw new IllegalArgumentException("Unsupported scheme: " + scheme);
+    }
+
+    private AclScheme(String value) {
+      this.value = value;
+    }
+  }
+
+  static class Permission {
+    final int code;
+
+    public static Permission parse(String permission) {
+      int permissionCode = 0;
+      for (char each : permission.toLowerCase().toCharArray()) {
+        switch (each) {
+          case 'r': permissionCode |= ZooDefs.Perms.READ; break;
+          case 'w': permissionCode |= ZooDefs.Perms.WRITE; break;
+          case 'c': permissionCode |= ZooDefs.Perms.CREATE; break;
+          case 'd': permissionCode |= ZooDefs.Perms.DELETE; break;
+          case 'a': permissionCode |= ZooDefs.Perms.ADMIN; break;
+          default: throw new IllegalArgumentException("Unsupported permission: " + permission);
+        }
+      }
+      return new Permission(permissionCode);
+    }
+
+    private Permission(int code) {
+      this.code = code;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2c9cc5/ambari-agent/src/main/java/org/apache/ambari/tools/zk/ZkConnection.java
----------------------------------------------------------------------
diff --git a/ambari-agent/src/main/java/org/apache/ambari/tools/zk/ZkConnection.java b/ambari-agent/src/main/java/org/apache/ambari/tools/zk/ZkConnection.java
new file mode 100644
index 0000000..6bac892
--- /dev/null
+++ b/ambari-agent/src/main/java/org/apache/ambari/tools/zk/ZkConnection.java
@@ -0,0 +1,53 @@
+/**
+ * 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.ambari.tools.zk;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static org.apache.zookeeper.Watcher.Event.KeeperState.SyncConnected;
+
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZooKeeper;
+
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * I can open connections to ZooKeeper
+ */
+public class ZkConnection {
+
+  /**
+   * Opens a connection to zookeeper and waits until the connection established
+   */
+  public static ZooKeeper open(String serverAddress, int sessionTimeoutMillis, int connectionTimeoutMillis)
+    throws IOException, InterruptedException, IllegalStateException
+  {
+    final CountDownLatch connSignal = new CountDownLatch(1);
+    ZooKeeper zooKeeper = new ZooKeeper(serverAddress, sessionTimeoutMillis, new Watcher() {
+      public void process(WatchedEvent event) {
+        if (event.getState() == SyncConnected) {
+          connSignal.countDown();
+        }
+      }
+    });
+    connSignal.await(connectionTimeoutMillis, MILLISECONDS);
+    return zooKeeper;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2c9cc5/ambari-agent/src/main/java/org/apache/ambari/tools/zk/ZkMigrator.java
----------------------------------------------------------------------
diff --git a/ambari-agent/src/main/java/org/apache/ambari/tools/zk/ZkMigrator.java b/ambari-agent/src/main/java/org/apache/ambari/tools/zk/ZkMigrator.java
new file mode 100644
index 0000000..15edb69
--- /dev/null
+++ b/ambari-agent/src/main/java/org/apache/ambari/tools/zk/ZkMigrator.java
@@ -0,0 +1,86 @@
+/**
+ * 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.ambari.tools.zk;
+
+import java.io.IOException;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.ZooKeeper;
+
+/**
+ * I'm a command line utility that provides functionality that the official zookeeper-client does not support.
+ * E.g. I can set ACLs recursively on a znode.
+ */
+public class ZkMigrator {
+  private static final int SESSION_TIMEOUT_MILLIS = 5000;
+  private static final int CONNECTION_TIMEOUT_MILLIS = 30000;
+
+  public static void main(String[] args) throws Exception {
+    CommandLine cli = new DefaultParser().parse(options(), args);
+    if (cli.hasOption("connection-string") && cli.hasOption("acl") && cli.hasOption("znode")) {
+      setAcls(cli.getOptionValue("connection-string"), cli.getOptionValue("znode"), ZkAcl.parse(cli.getOptionValue("acl")));
+    } else {
+      printHelp();
+    }
+  }
+
+  private static Options options() {
+    return new Options()
+      .addOption(Option.builder("h")
+        .longOpt("help")
+        .desc("print help")
+        .build())
+      .addOption(Option.builder("c")
+        .longOpt("connection-string")
+        .desc("zookeeper connection string")
+        .hasArg()
+        .argName("connection-string")
+        .build())
+      .addOption(Option.builder("a")
+        .longOpt("acl")
+        .desc("ACL of a znode in the following format <scheme:id:permission>")
+        .hasArg()
+        .argName("acl")
+        .build())
+      .addOption(Option.builder("z")
+        .longOpt("znode")
+        .desc("znode path")
+        .hasArg()
+        .argName("znode")
+        .build());
+  }
+
+  private static void setAcls(String connectionString, String znode, ZkAcl acl) throws IOException, InterruptedException, KeeperException {
+    ZooKeeper client = ZkConnection.open(connectionString, SESSION_TIMEOUT_MILLIS, CONNECTION_TIMEOUT_MILLIS);
+    try {
+      acl.setRecursivelyOn(client, znode);
+    } finally {
+      client.close();
+    }
+  }
+
+  private static void printHelp() {
+    System.out.println("Usage zkmigrator -connection-string <host:port> -acl <scheme:id:permission> -znode /path/to/znode");
+    System.exit(1);
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2c9cc5/ambari-agent/src/test/java/org/apache/ambari/tools/zk/ZkMigratorTest.java
----------------------------------------------------------------------
diff --git a/ambari-agent/src/test/java/org/apache/ambari/tools/zk/ZkMigratorTest.java b/ambari-agent/src/test/java/org/apache/ambari/tools/zk/ZkMigratorTest.java
new file mode 100644
index 0000000..0a2bbac
--- /dev/null
+++ b/ambari-agent/src/test/java/org/apache/ambari/tools/zk/ZkMigratorTest.java
@@ -0,0 +1,154 @@
+/**
+ * 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.ambari.tools.zk;
+
+import static org.apache.zookeeper.ZooDefs.Perms.DELETE;
+import static org.apache.zookeeper.ZooDefs.Perms.READ;
+import static org.apache.zookeeper.ZooDefs.Perms.WRITE;
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.util.List;
+
+import org.apache.curator.framework.CuratorFramework;
+import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.retry.RetryOneTime;
+import org.apache.curator.test.TestingServer;
+import org.apache.zookeeper.data.ACL;
+import org.apache.zookeeper.data.Id;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+@Category({ category.SlowTest.class})
+public class ZkMigratorTest {
+  private CuratorFramework cli;
+  private TestingServer zkTestServer;
+
+  @Test
+  public void testSetAclsOnSingleNode() throws Exception {
+    // Given
+    path("/single");
+    // When
+    setAcls("/single", "ip:127.0.0.1:rwd");
+    // Then
+    assertHasAcl("/single", "ip", "127.0.0.1", WRITE | READ | DELETE);
+  }
+
+  @Test
+  public void testSetAclsOnParentAndItsDirectChildren() throws Exception {
+    // Given
+    path("/parent");
+    path("/parent/a");
+    path("/parent/b");
+    // When
+    setAcls("/parent", "ip:127.0.0.1:rd");
+    // Then
+    assertHasAcl("/parent", "ip", "127.0.0.1", READ | DELETE);
+    assertHasAcl("/parent/a", "ip", "127.0.0.1", READ | DELETE);
+    assertHasAcl("/parent/b", "ip", "127.0.0.1", READ | DELETE);
+  }
+
+  @Test
+  public void testSetAclsRecursively() throws Exception {
+    // Given
+    path("/parent");
+    path("/parent/a");
+    path("/parent/a/b");
+    path("/parent/a/b/c");
+    // When
+    setAcls("/", "ip:127.0.0.1:r");
+    // Then
+    assertHasAcl("/parent", "ip", "127.0.0.1", READ);
+    assertHasAcl("/parent/a", "ip", "127.0.0.1", READ);
+    assertHasAcl("/parent/a/b", "ip", "127.0.0.1", READ);
+    assertHasAcl("/parent/a/b/c", "ip", "127.0.0.1", READ);
+  }
+
+  @Test
+  public void testSupportsWorldScheme() throws Exception {
+    // Given
+    path("/unprotected");
+    // When
+    setAcls("/unprotected", "world:anyone:r");
+    // Then
+    assertHasAcl("/unprotected", "world", "anyone", READ);
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testRejectsUnsupportedScheme() throws Exception {
+    path("/any");
+    setAcls("/any", "unsupported:anyone:r");
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testRejectUnsupportedPermission() throws Exception {
+    path("/any");
+    setAcls("/any", "world:anyone:invalid");
+  }
+
+  @Before
+  public void startZookeeper() throws Exception {
+    zkTestServer = new TestingServer(Port.free());
+    zkTestServer.start();
+    cli = CuratorFrameworkFactory.newClient(zkTestServer.getConnectString(), new RetryOneTime(2000));
+    cli.start();
+  }
+
+  @After
+  public void stopZookeeper() throws IOException {
+    cli.close();
+    zkTestServer.stop();
+  }
+
+  private String path(String s) throws Exception {
+    return cli.create().forPath(s, "any".getBytes());
+  }
+
+  private void setAcls(String path, String acl) throws Exception {
+    ZkMigrator.main(new String[] {
+      "-connection-string", zkTestServer.getConnectString(),
+      "-znode", path,
+      "-acl", acl
+    });
+  }
+
+  private void assertHasAcl(String path, String scheme, String id, int permission) throws Exception {
+    List<ACL> acls = cli.getACL().forPath(path);
+    assertEquals("expected 1 acl on " + path, 1, acls.size());
+    assertEquals("acl on " + path, new Id(scheme, id), acls.get(0).getId());
+    assertEquals(permission, acls.get(0).getPerms());
+  }
+
+  static class Port {
+    public static int free() throws IOException {
+      ServerSocket socket = null;
+      try {
+        socket = new ServerSocket(0);
+        return socket.getLocalPort();
+      } finally {
+        if (socket != null) {
+          socket.close();
+        }
+      }
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2c9cc5/ambari-common/src/main/python/resource_management/core/resources/zkmigrator.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/resource_management/core/resources/zkmigrator.py b/ambari-common/src/main/python/resource_management/core/resources/zkmigrator.py
new file mode 100644
index 0000000..a946e47
--- /dev/null
+++ b/ambari-common/src/main/python/resource_management/core/resources/zkmigrator.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+"""
+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.
+
+Ambari Agent
+
+"""
+
+from resource_management.core.resources.system import Execute
+
+class ZkMigrator:
+  def __init__(self, zk_host, java_exec, java_home, jaas_file, user):
+    self.zk_host = zk_host
+    self.java_exec = java_exec
+    self.java_home = java_home
+    self.jaas_file = jaas_file
+    self.user = user
+    self.zkmigrator_jar = "/var/lib/ambari-agent/tools/zkmigrator.jar"
+
+  def set_acls(self, znode, acl, tries=1):
+    Execute(
+      self._command(znode, acl), \
+      user=self.user, \
+      environment={ 'JAVA_HOME': self.java_home }, \
+      logoutput=True, \
+      tries=tries)
+
+  def _command(self, znode, acl):
+    return "{0} -Djava.security.auth.login.config={1} -jar {2} -connection-string {3} -znode {4} -acl {5}".format( \
+      self.java_exec, self.jaas_file, self.zkmigrator_jar, self.zk_host, znode, acl)

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2c9cc5/ambari-common/src/main/python/resource_management/libraries/script/script.py
----------------------------------------------------------------------
diff --git a/ambari-common/src/main/python/resource_management/libraries/script/script.py b/ambari-common/src/main/python/resource_management/libraries/script/script.py
index 6a4865d..ccb09c7 100644
--- a/ambari-common/src/main/python/resource_management/libraries/script/script.py
+++ b/ambari-common/src/main/python/resource_management/libraries/script/script.py
@@ -670,6 +670,12 @@ class Script(object):
     """
     pass
 
+  def disable_security(self, env):
+    """
+    To be overridden by subclasses if a custom action is required upon dekerberization (e.g. removing zk ACLs)
+    """
+    pass
+
   def restart(self, env):
     """
     Default implementation of restart command is to call stop and start methods

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2c9cc5/ambari-server/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-server/pom.xml b/ambari-server/pom.xml
index ceec39c..102cb71 100644
--- a/ambari-server/pom.xml
+++ b/ambari-server/pom.xml
@@ -312,6 +312,7 @@
             <exclude>**/cluster.properties.j2</exclude>
             <exclude>**/repo_ubuntu.j2</exclude>
             <exclude>**/.pydev*</exclude>
+            <exclude>**/.hash</exclude>
             <!--gitignore content -->
             <exclude>src/main/resources/db/newcerts/**</exclude>
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2c9cc5/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java
index 3261a56..51c0b2c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java
@@ -18,6 +18,8 @@
 
 package org.apache.ambari.server.controller;
 
+import static java.util.Collections.singletonList;
+
 import java.io.File;
 import java.io.IOException;
 import java.text.SimpleDateFormat;
@@ -38,6 +40,7 @@ import java.util.regex.Matcher;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.Role;
 import org.apache.ambari.server.RoleCommand;
+import org.apache.ambari.server.ServiceNotFoundException;
 import org.apache.ambari.server.actionmanager.ActionManager;
 import org.apache.ambari.server.actionmanager.RequestFactory;
 import org.apache.ambari.server.actionmanager.Stage;
@@ -3012,6 +3015,78 @@ public class KerberosHelperImpl implements KerberosHelper {
       return serviceComponentHosts;
     }
 
+    void addDisableSecurityHookStage(Cluster cluster,
+                                            String clusterHostInfoJson,
+                                            String hostParamsJson,
+                                            Map<String, String> commandParameters,
+                                            RoleCommandOrder roleCommandOrder,
+                                            RequestStageContainer requestStageContainer)
+      throws AmbariException
+    {
+      Stage stage = createNewStage(requestStageContainer.getLastStageId(),
+        cluster,
+        requestStageContainer.getId(),
+        "Disable security",
+        clusterHostInfoJson,
+        StageUtils.getGson().toJson(commandParameters),
+        hostParamsJson);
+      addDisableSecurityCommandToAllServices(cluster, stage);
+      RoleGraph roleGraph = roleGraphFactory.createNew(roleCommandOrder);
+      roleGraph.build(stage);
+      requestStageContainer.addStages(roleGraph.getStages());
+    }
+
+    private void addDisableSecurityCommandToAllServices(Cluster cluster, Stage stage) throws AmbariException {
+      for (Service service : cluster.getServices().values()) {
+        for (ServiceComponent component : service.getServiceComponents().values()) {
+            if (!component.getServiceComponentHosts().isEmpty()) {
+              String firstHost = component.getServiceComponentHosts().keySet().iterator().next(); // it is only necessary to send it to one host
+              ActionExecutionContext exec = new ActionExecutionContext(
+                cluster.getClusterName(),
+                "DISABLE_SECURITY",
+                singletonList(new RequestResourceFilter(service.getName(), component.getName(), singletonList(firstHost))),
+                Collections.<String, String>emptyMap());
+              customCommandExecutionHelper.addExecutionCommandsToStage(exec, stage, Collections.<String, String>emptyMap());
+          }
+        }
+      }
+    }
+
+    void addStopZookeeperStage(Cluster cluster,
+                                      String clusterHostInfoJson,
+                                      String hostParamsJson,
+                                      Map<String, String> commandParameters,
+                                      RoleCommandOrder roleCommandOrder,
+                                      RequestStageContainer requestStageContainer)
+      throws AmbariException
+    {
+      Service zookeeper;
+      try {
+        zookeeper = cluster.getService("ZOOKEEPER");
+      } catch (ServiceNotFoundException e) {
+        return;
+      }
+      Stage stage = createNewStage(requestStageContainer.getLastStageId(),
+        cluster,
+        requestStageContainer.getId(),
+        "Stopping ZooKeeper",
+        clusterHostInfoJson,
+        StageUtils.getGson().toJson(commandParameters),
+        hostParamsJson);
+      for (ServiceComponent component : zookeeper.getServiceComponents().values()) {
+          Set<String> hosts = component.getServiceComponentHosts().keySet();
+          ActionExecutionContext exec = new ActionExecutionContext(
+            cluster.getClusterName(),
+            "STOP",
+            singletonList(new RequestResourceFilter(zookeeper.getName(), component.getName(), new ArrayList<>(hosts))),
+            Collections.<String, String>emptyMap());
+          customCommandExecutionHelper.addExecutionCommandsToStage(exec, stage, Collections.<String, String>emptyMap());
+      }
+      RoleGraph roleGraph = roleGraphFactory.createNew(roleCommandOrder);
+      roleGraph.build(stage);
+      requestStageContainer.addStages(roleGraph.getStages());
+    }
+
     public void addDeleteKeytabFilesStage(Cluster cluster, List<ServiceComponentHost> serviceComponentHosts,
                                           String clusterHostInfoJson, String hostParamsJson,
                                           Map<String, String> commandParameters,
@@ -3331,6 +3406,12 @@ public class KerberosHelperImpl implements KerberosHelper {
         commandParameters.put(KerberosServerAction.IDENTITY_FILTER, StageUtils.getGson().toJson(identityFilter));
       }
 
+      addDisableSecurityHookStage(cluster, clusterHostInfoJson, hostParamsJson, commandParameters,
+        roleCommandOrder, requestStageContainer);
+
+      addStopZookeeperStage(cluster, clusterHostInfoJson, hostParamsJson, commandParameters,
+        roleCommandOrder, requestStageContainer);
+
       // *****************************************************************
       // Create stage to prepare operations
       addPrepareDisableKerberosOperationsStage(cluster, clusterHostInfoJson, hostParamsJson, event, commandParameters,

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2c9cc5/ambari-server/src/main/java/org/apache/ambari/server/metadata/ActionMetadata.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/metadata/ActionMetadata.java b/ambari-server/src/main/java/org/apache/ambari/server/metadata/ActionMetadata.java
index 0064662..54ce9ae 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/metadata/ActionMetadata.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/metadata/ActionMetadata.java
@@ -64,6 +64,7 @@ public class ActionMetadata {
     defaultHostComponentCommands.add("INSTALL");
     defaultHostComponentCommands.add("CONFIGURE");
     defaultHostComponentCommands.add("CONFIGURE_FUNCTION");
+    defaultHostComponentCommands.add("DISABLE_SECURITY");
   }
 
   private void fillServiceClients() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2c9cc5/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java
index ba152e6..8a70f0c 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java
@@ -1380,27 +1380,27 @@ public class KerberosHelperTest extends EasyMockSupport {
     expect(serviceComponentKerberosClient.getName()).andReturn(Role.KERBEROS_CLIENT.name()).anyTimes();
     expect(serviceComponentKerberosClient.getServiceComponentHosts()).andReturn(Collections.singletonMap("host1", schKerberosClient)).anyTimes();
 
-    final Service serviceKerberos = createStrictMock(Service.class);
+    final Service serviceKerberos = createNiceMock(Service.class);
     expect(serviceKerberos.getName()).andReturn(Service.Type.KERBEROS.name()).anyTimes();
     expect(serviceKerberos.getServiceComponents())
         .andReturn(Collections.singletonMap(Role.KERBEROS_CLIENT.name(), serviceComponentKerberosClient))
-        .times(1);
+        .anyTimes();
     serviceKerberos.setSecurityState(SecurityState.UNSECURED);
     expectLastCall().once();
 
-    final Service service1 = createStrictMock(Service.class);
+    final Service service1 = createNiceMock(Service.class);
     expect(service1.getName()).andReturn("SERVICE1").anyTimes();
     expect(service1.getServiceComponents())
         .andReturn(Collections.<String, ServiceComponent>emptyMap())
-        .times(1);
+        .anyTimes();
     service1.setSecurityState(SecurityState.UNSECURED);
     expectLastCall().once();
 
-    final Service service2 = createStrictMock(Service.class);
+    final Service service2 = createNiceMock(Service.class);
     expect(service2.getName()).andReturn("SERVICE2").anyTimes();
     expect(service2.getServiceComponents())
         .andReturn(Collections.<String, ServiceComponent>emptyMap())
-        .times(1);
+        .anyTimes();
     service2.setSecurityState(SecurityState.UNSECURED);
     expectLastCall().once();
 
@@ -1466,6 +1466,17 @@ public class KerberosHelperTest extends EasyMockSupport {
 
     // This is a STRICT mock to help ensure that the end result is what we want.
     final RequestStageContainer requestStageContainer = createStrictMock(RequestStageContainer.class);
+    expect(cluster.getService("ZOOKEEPER")).andReturn(service1).anyTimes();
+    // Hook Stage
+    expect(requestStageContainer.getLastStageId()).andReturn(2L).anyTimes();
+    expect(requestStageContainer.getId()).andReturn(1L).once();
+    requestStageContainer.addStages(anyObject(List.class));
+    expectLastCall().once();
+    // StopZk Stage
+    expect(requestStageContainer.getLastStageId()).andReturn(2L).anyTimes();
+    expect(requestStageContainer.getId()).andReturn(1L).once();
+    requestStageContainer.addStages(anyObject(List.class));
+    expectLastCall().once();
     // Preparation Stage
     expect(requestStageContainer.getLastStageId()).andReturn(2L).anyTimes();
     expect(requestStageContainer.getId()).andReturn(1L).once();

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2c9cc5/ambari-web/app/controllers/main/admin/kerberos/disable_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/admin/kerberos/disable_controller.js b/ambari-web/app/controllers/main/admin/kerberos/disable_controller.js
index cec4503..75a9a33 100644
--- a/ambari-web/app/controllers/main/admin/kerberos/disable_controller.js
+++ b/ambari-web/app/controllers/main/admin/kerberos/disable_controller.js
@@ -23,7 +23,7 @@ App.KerberosDisableController = App.KerberosProgressPageController.extend(App.Wi
 
   name: 'kerberosDisableController',
   clusterDeployState: 'DEFAULT',
-  commands: ['stopServices', 'unkerberize', 'deleteKerberos', 'startAllServices'],
+  commands: ['startZookeeper', 'stopAllButZookeeper', 'unkerberize', 'deleteKerberos', 'startAllServices'],
 
   tasksMessagesPrefix: 'admin.kerberos.disable.step',
 
@@ -35,6 +35,14 @@ App.KerberosDisableController = App.KerberosProgressPageController.extend(App.Wi
     this._super();
   },
 
+  startZookeeper: function () {
+    this.startServices(false, ["ZOOKEEPER"], true);
+  },
+
+  stopAllButZookeeper: function () {
+    this.stopServices(["ZOOKEEPER"], false);
+  },
+
   unkerberize: function () {
     return App.ajax.send({
       name: 'admin.unkerberize.cluster',

http://git-wip-us.apache.org/repos/asf/ambari/blob/2f2c9cc5/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index 64a5e77..e9d117a 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -1284,10 +1284,12 @@ Em.I18n.translations = {
   'admin.kerberos.regenerate_keytabs.checkbox.restart.label': 'Automatically restart components after keytab regeneration',
   'admin.kerberos.service.alert.yarn': 'YARN log and local dir will be deleted and ResourceManager state will be formatted as part of Enabling/Disabling Kerberos.',
 
-  'admin.kerberos.disable.step1.task0.title': 'Stop Services',
-  'admin.kerberos.disable.step1.task1.title': 'Unkerberize Cluster',
-  'admin.kerberos.disable.step1.task2.title': 'Remove Kerberos',
-  'admin.kerberos.disable.step1.task3.title': 'Start Services',
+  'admin.kerberos.disable.step1.task0.title': 'Start ZooKeeper',
+  'admin.kerberos.disable.step1.task1.title': 'Stop Required Services',
+  'admin.kerberos.disable.step1.task2.title': 'Unkerberize Cluster',
+  'admin.kerberos.disable.step1.task3.title': 'Remove Kerberos',
+  'admin.kerberos.disable.step1.task4.title': 'Start Services',
+
   'admin.kerberos.disable.unkerberize.header': 'Unkerberize cluster',
   'admin.kerberos.disable.unkerberize.message': 'You cannot quit wizard while cluster is being unkerberized',
   'admin.kerberos.disable.inProgress': 'Please wait while cluster is being unkerberized',