Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 920FB200BE8 for ; Fri, 23 Dec 2016 16:06:30 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 8D6C2160B1E; Fri, 23 Dec 2016 15:06:30 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 1965A160B1D for ; Fri, 23 Dec 2016 16:06:28 +0100 (CET) Received: (qmail 12185 invoked by uid 500); 23 Dec 2016 15:06:28 -0000 Mailing-List: contact commits-help@ambari.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: ambari-dev@ambari.apache.org Delivered-To: mailing list commits@ambari.apache.org Received: (qmail 12175 invoked by uid 99); 23 Dec 2016 15:06:28 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 23 Dec 2016 15:06:28 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 04B03DFB7D; Fri, 23 Dec 2016 15:06:28 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: stoader@apache.org To: commits@ambari.apache.org Message-Id: <63d134ccd82b43d3b1d268d4018ad24b@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: ambari git commit: AMBARI-19187. Disable security hook. (Attila Magyar via stoader) Date: Fri, 23 Dec 2016 15:06:28 +0000 (UTC) archived-at: Fri, 23 Dec 2016 15:06:30 -0000 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 Authored: Fri Dec 23 16:03:31 2016 +0100 Committer: Toader, Sebastian 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 @@ 4.0.0 org.apache.ambari ambari-agent - pom 2.0.0.0-SNAPSHOT Ambari Agent Ambari Agent @@ -52,6 +51,41 @@ ${target.cache.dir}/custom_actions src/packages/tarball + + + org.apache.zookeeper + zookeeper + 3.4.9 + + + commons-cli + commons-cli + 1.3.1 + + + org.apache.curator + curator-test + 2.9.0 + test + + + org.apache.curator + curator-framework + 2.7.1 + test + + + utility + utility + test + 1.0.0.0-SNAPSHOT + + + junit + junit + test + + @@ -84,12 +118,39 @@ maven-compiler-plugin 3.0 + + 1.7 + 1.7 + + + + org.apache.maven.plugins + maven-shade-plugin + 2.3 + + + package + + shade + + + + + org.apache.ambari.tools.zk.ZkMigrator + + + ${project.build.directory}${dirsep}${project.artifactId}-${project.version}/var/lib/ambari-agent/tools/zkmigrator.jar + + + org.apache.maven.plugins maven-surefire-plugin ${skipSurefireTests} + + ${testcase.groups} @@ -462,6 +523,7 @@ **/*.json **/*.pydevproject src/main/package/choco/ambari-agent.nuspec + **/dependency-reduced-pom.xml 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 "); + } + 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 ") + .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 -acl -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 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 @@ **/cluster.properties.j2 **/repo_ubuntu.j2 **/.pydev* + **/.hash src/main/resources/db/newcerts/** 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 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.emptyMap()); + customCommandExecutionHelper.addExecutionCommandsToStage(exec, stage, Collections.emptyMap()); + } + } + } + } + + void addStopZookeeperStage(Cluster cluster, + String clusterHostInfoJson, + String hostParamsJson, + Map 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 hosts = component.getServiceComponentHosts().keySet(); + ActionExecutionContext exec = new ActionExecutionContext( + cluster.getClusterName(), + "STOP", + singletonList(new RequestResourceFilter(zookeeper.getName(), component.getName(), new ArrayList<>(hosts))), + Collections.emptyMap()); + customCommandExecutionHelper.addExecutionCommandsToStage(exec, stage, Collections.emptyMap()); + } + RoleGraph roleGraph = roleGraphFactory.createNew(roleCommandOrder); + roleGraph.build(stage); + requestStageContainer.addStages(roleGraph.getStages()); + } + public void addDeleteKeytabFilesStage(Cluster cluster, List serviceComponentHosts, String clusterHostInfoJson, String hostParamsJson, Map 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.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.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',