You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sm...@apache.org on 2019/01/31 16:57:35 UTC

[ambari] branch branch-2.7 updated: AMBARI-24672. Make sure we regenerate all service specific keytabs on all hosts where they are needed (#2802)

This is an automated email from the ASF dual-hosted git repository.

smolnar pushed a commit to branch branch-2.7
in repository https://gitbox.apache.org/repos/asf/ambari.git


The following commit(s) were added to refs/heads/branch-2.7 by this push:
     new 4d9d123  AMBARI-24672. Make sure we regenerate all service specific keytabs on all hosts where they are needed (#2802)
4d9d123 is described below

commit 4d9d123320df7f829a4f4175ef7dbb2a2d4b05b3
Author: Sandor Molnar <sm...@apache.org>
AuthorDate: Thu Jan 31 17:57:27 2019 +0100

    AMBARI-24672. Make sure we regenerate all service specific keytabs on all hosts where they are needed (#2802)
---
 .../ambari/server/controller/AmbariServer.java     |  2 +
 .../events/publishers/AgentCommandsPublisher.java  |  5 ++-
 .../server/orm/dao/KerberosKeytabPrincipalDAO.java | 10 ++++-
 .../kerberos/KerberosServerAction.java             | 25 ++++--------
 .../stageutils/KerberosKeytabController.java       | 44 ++++++++++++++++++++--
 .../ambari/server/agent/TestHeartbeatHandler.java  |  5 ++-
 .../kerberos/KerberosServerActionTest.java         |  4 +-
 7 files changed, 68 insertions(+), 27 deletions(-)

diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index 07bf2b7..6f5f4e6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -110,6 +110,7 @@ import org.apache.ambari.server.security.authorization.Users;
 import org.apache.ambari.server.security.unsecured.rest.CertificateDownload;
 import org.apache.ambari.server.security.unsecured.rest.CertificateSign;
 import org.apache.ambari.server.security.unsecured.rest.ConnectionInfo;
+import org.apache.ambari.server.serveraction.kerberos.stageutils.KerberosKeytabController;
 import org.apache.ambari.server.stack.UpdateActiveRepoVersionOnStartup;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.topology.AmbariContext;
@@ -942,6 +943,7 @@ public class AmbariServer {
     ClusterPrivilegeResourceProvider.init(injector.getInstance(ClusterDAO.class));
     AmbariPrivilegeResourceProvider.init(injector.getInstance(ClusterDAO.class));
     ActionManager.setTopologyManager(injector.getInstance(TopologyManager.class));
+    KerberosKeytabController.setKerberosHelper(injector.getInstance(KerberosHelper.class));
     StackAdvisorBlueprintProcessor.init(injector.getInstance(StackAdvisorHelper.class));
     ThreadPoolEnabledPropertyProvider.init(injector.getInstance(Configuration.class));
 
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/publishers/AgentCommandsPublisher.java b/ambari-server/src/main/java/org/apache/ambari/server/events/publishers/AgentCommandsPublisher.java
index 0043f09..231f92c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/events/publishers/AgentCommandsPublisher.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/publishers/AgentCommandsPublisher.java
@@ -50,6 +50,7 @@ import org.apache.ambari.server.serveraction.kerberos.stageutils.KerberosKeytabC
 import org.apache.ambari.server.serveraction.kerberos.stageutils.ResolvedKerberosKeytab;
 import org.apache.ambari.server.serveraction.kerberos.stageutils.ResolvedKerberosPrincipal;
 import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.kerberos.KerberosIdentityDescriptor;
 import org.apache.ambari.server.utils.StageUtils;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.codec.digest.DigestUtils;
@@ -245,8 +246,8 @@ public class AgentCommandsPublisher {
 
       try {
         Map<String, ? extends Collection<String>> serviceComponentFilter = getServiceComponentFilter(kerberosCommandParameters.getServiceComponentFilter());
-
-        Set<ResolvedKerberosKeytab> keytabsToInject = kerberosKeytabController.getFilteredKeytabs(serviceComponentFilter, kerberosCommandParameters.getHostFilter(), kerberosCommandParameters.getIdentityFilter());
+        final Collection<KerberosIdentityDescriptor> serviceIdentities = serviceComponentFilter == null ? null : kerberosKeytabController.getServiceIdentities(executionCommand.getClusterName(), serviceComponentFilter.keySet());
+        final Set<ResolvedKerberosKeytab> keytabsToInject = kerberosKeytabController.getFilteredKeytabs(serviceIdentities, kerberosCommandParameters.getHostFilter(), kerberosCommandParameters.getIdentityFilter());
         for (ResolvedKerberosKeytab resolvedKeytab : keytabsToInject) {
           for (ResolvedKerberosPrincipal resolvedPrincipal : resolvedKeytab.getPrincipals()) {
             String hostName = resolvedPrincipal.getHostName();
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/KerberosKeytabPrincipalDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/KerberosKeytabPrincipalDAO.java
index 7b1aa45..7a44f2c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/KerberosKeytabPrincipalDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/KerberosKeytabPrincipalDAO.java
@@ -291,7 +291,11 @@ public class KerberosKeytabPrincipalDAO {
     private Collection<String> componentNames;
     private Collection<String> principals;
 
-    public KerberosKeytabPrincipalFilter(Collection<String> hostNames, Collection<String> serviceNames, Collection<String> componentNames, Collection<String> principals) {
+    private KerberosKeytabPrincipalFilter() {
+      this(null, null, null, null);
+    }
+
+    private KerberosKeytabPrincipalFilter(Collection<String> hostNames, Collection<String> serviceNames, Collection<String> componentNames, Collection<String> principals) {
       this.hostNames = hostNames;
       this.serviceNames = serviceNames;
       this.componentNames = componentNames;
@@ -330,6 +334,10 @@ public class KerberosKeytabPrincipalDAO {
       this.principals = principals;
     }
 
+    public static KerberosKeytabPrincipalFilter createEmptyFilter() {
+      return new KerberosKeytabPrincipalFilter();
+    }
+
     public static KerberosKeytabPrincipalFilter createFilter(String serviceName, Collection<String> componentNames, Collection<String> hostNames, Collection<String> principalNames) {
       return new KerberosKeytabPrincipalFilter(hostNames,
           (serviceName == null) ? null : Collections.singleton(serviceName),
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
index 1748648..b6876c8 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerAction.java
@@ -21,7 +21,6 @@ package org.apache.ambari.server.serveraction.kerberos;
 import java.io.File;
 import java.io.IOException;
 import java.lang.reflect.Type;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
@@ -449,11 +448,12 @@ public abstract class KerberosServerAction extends AbstractServerAction {
       }
 
       try {
-        final Map<String, ? extends Collection<String>> serviceComponentFilter = (pruneServiceFilter())
-            ? kerberosKeytabController.adjustServiceComponentFilter(clusters.getCluster(getClusterName()), true, getServiceComponentFilter())
-            : getServiceComponentFilter();
-        final Collection<KerberosIdentityDescriptor> serviceIdentities = serviceComponentFilter == null ? null : calculateServiceIdentities(getClusterName(), serviceComponentFilter);
-        for (ResolvedKerberosKeytab rkk : kerberosKeytabController.getFilteredKeytabs(serviceComponentFilter, getHostFilter(), getIdentityFilter())) {
+        Map<String, Collection<String>> serviceComponentFilter = getServiceComponentFilter();
+        if (serviceComponentFilter != null && pruneServiceFilter()) {
+          kerberosKeytabController.adjustServiceComponentFilter(clusters.getCluster(getClusterName()), true, serviceComponentFilter);
+        }
+        final Collection<KerberosIdentityDescriptor> serviceIdentities = serviceComponentFilter == null ? null : kerberosKeytabController.getServiceIdentities(getClusterName(), serviceComponentFilter.keySet());
+        for (ResolvedKerberosKeytab rkk : kerberosKeytabController.getFilteredKeytabs(serviceIdentities, getHostFilter(),getIdentityFilter())) {
           for (ResolvedKerberosPrincipal principal : rkk.getPrincipals()) {
             commandReport = processIdentity(principal, handler, kerberosConfiguration, isRelevantIdentity(serviceIdentities, principal), requestSharedDataContext);
             // If the principal processor returns a CommandReport, than it is time to stop
@@ -504,17 +504,6 @@ public abstract class KerberosServerAction extends AbstractServerAction {
     return true;
   }
 
-  private Collection<KerberosIdentityDescriptor> calculateServiceIdentities(String clusterName, Map<String, ? extends Collection<String>> serviceComponentFilter)
-      throws AmbariException {
-    final Collection<KerberosIdentityDescriptor> serviceIdentities = new ArrayList<>();
-    for (String service : serviceComponentFilter.keySet()) {
-      for (Collection<KerberosIdentityDescriptor> activeIdentities : kerberosHelper.getActiveIdentities(clusterName, null, service, null, true).values()) {
-        serviceIdentities.addAll(activeIdentities);
-      }
-    }
-    return serviceIdentities;
-  }
-
   /**
    * Processes an identity as necessary.
    * <p/>
@@ -584,7 +573,7 @@ public abstract class KerberosServerAction extends AbstractServerAction {
   }
 
 
-  protected Map<String, ? extends Collection<String>> getServiceComponentFilter() {
+  protected Map<String, Collection<String>> getServiceComponentFilter() {
     String serializedValue = getCommandParameterValue(SERVICE_COMPONENT_FILTER);
 
     if (serializedValue != null) {
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/stageutils/KerberosKeytabController.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/stageutils/KerberosKeytabController.java
index fd26058..ec01310 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/stageutils/KerberosKeytabController.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/stageutils/KerberosKeytabController.java
@@ -28,6 +28,7 @@ import java.util.Map;
 import java.util.Set;
 
 import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.controller.KerberosHelper;
 import org.apache.ambari.server.orm.dao.KerberosKeytabDAO;
 import org.apache.ambari.server.orm.dao.KerberosKeytabPrincipalDAO;
 import org.apache.ambari.server.orm.entities.KerberosKeytabEntity;
@@ -35,6 +36,7 @@ import org.apache.ambari.server.orm.entities.KerberosKeytabPrincipalEntity;
 import org.apache.ambari.server.orm.entities.KerberosPrincipalEntity;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Service;
+import org.apache.ambari.server.state.kerberos.KerberosIdentityDescriptor;
 import org.apache.commons.collections.MapUtils;
 
 import com.google.common.collect.ImmutableSet;
@@ -54,6 +56,13 @@ public class KerberosKeytabController {
   @Inject
   private KerberosKeytabPrincipalDAO kerberosKeytabPrincipalDAO;
 
+  //TODO: due to circular dependencies in Guice this field cannot be injected with Guice's @Inject annotation; for now we should statically inject in AmbariServer
+  private static KerberosHelper kerberosHelper;
+
+  public static void setKerberosHelper(KerberosHelper kerberosHelper) {
+    KerberosKeytabController.kerberosHelper = kerberosHelper;
+  }
+
   /**
    * Tries to find keytab by keytab path in destination filesystem.
    *
@@ -102,7 +111,7 @@ public class KerberosKeytabController {
    * @param identityFilter identity(principal) filter
    * @return set of keytabs found
    */
-  public Set<ResolvedKerberosKeytab> getFilteredKeytabs(Map<String, ? extends Collection<String>> serviceComponentFilter,
+  private Set<ResolvedKerberosKeytab> getFilteredKeytabs(Map<String, ? extends Collection<String>> serviceComponentFilter,
                                                         Set<String> hostFilter, Collection<String> identityFilter) {
     if (serviceComponentFilter == null && hostFilter == null && identityFilter == null) {
       return getAllKeytabs();
@@ -125,6 +134,11 @@ public class KerberosKeytabController {
     return Sets.newHashSet(resultMap.values());
   }
 
+  public Set<ResolvedKerberosKeytab> getFilteredKeytabs(Collection<KerberosIdentityDescriptor> serviceIdentities, Set<String> hostFilter, Collection<String> identityFilters) {
+    final Collection<String> enhancedIdentityFilters = populateIdentityFilter(identityFilters, serviceIdentities);
+    return getFilteredKeytabs((Map<String, ? extends Collection<String>>) null, hostFilter, enhancedIdentityFilters);
+  }
+
   /**
    * This function split serviceComponentFilter to two filters, one with specific components, and another one with service
    * only. Can return only one filter if filter contain only one type of mapping(whole service or component based)
@@ -156,7 +170,7 @@ public class KerberosKeytabController {
       List<KerberosKeytabPrincipalDAO.KerberosKeytabPrincipalFilter> result = new ArrayList<>();
       // Handle the service/component filter
       if (serviceSet.size() > 0) {
-        result.add(new KerberosKeytabPrincipalDAO.KerberosKeytabPrincipalFilter(
+        result.add(KerberosKeytabPrincipalDAO.KerberosKeytabPrincipalFilter.createFilter(
           null,
           serviceSet,
           componentSet,
@@ -165,7 +179,7 @@ public class KerberosKeytabController {
       }
       // Handler the service/* filter
       if (serviceOnlySet.size() > 0) {
-        result.add(new KerberosKeytabPrincipalDAO.KerberosKeytabPrincipalFilter(
+        result.add(KerberosKeytabPrincipalDAO.KerberosKeytabPrincipalFilter.createFilter(
           null,
           serviceOnlySet,
           null,
@@ -177,7 +191,7 @@ public class KerberosKeytabController {
       }
     }
 
-    return Lists.newArrayList(new KerberosKeytabPrincipalDAO.KerberosKeytabPrincipalFilter(null,null,null,null));
+    return Lists.newArrayList(KerberosKeytabPrincipalDAO.KerberosKeytabPrincipalFilter.createEmptyFilter());
   }
 
   private ResolvedKerberosKeytab fromKeytabEntity(KerberosKeytabEntity kke, boolean resolvePrincipals) {
@@ -264,4 +278,26 @@ public class KerberosKeytabController {
 
     return adjustedFilter;
   }
+
+  public Collection<KerberosIdentityDescriptor> getServiceIdentities(String clusterName, Collection<String> services) throws AmbariException {
+    final Collection<KerberosIdentityDescriptor> serviceIdentities = new ArrayList<>();
+    for (String service : services) {
+      for (Collection<KerberosIdentityDescriptor> activeIdentities : kerberosHelper.getActiveIdentities(clusterName, null, service, null, true).values()) {
+        serviceIdentities.addAll(activeIdentities);
+      }
+    }
+    return serviceIdentities;
+  }
+
+  private Collection<String> populateIdentityFilter(Collection<String> identityFilters, Collection<KerberosIdentityDescriptor> serviceIdentities) {
+    if (serviceIdentities != null) {
+      identityFilters = identityFilters == null ? new HashSet<>() : identityFilters;
+      for (KerberosIdentityDescriptor serviceIdentity : serviceIdentities) {
+        if (!KerberosHelper.AMBARI_SERVER_KERBEROS_IDENTITY_NAME.equals(serviceIdentity.getName())) {
+          identityFilters.add(serviceIdentity.getPrincipalDescriptor().getName());
+        }
+      }
+    }
+    return identityFilters;
+  }
 }
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/agent/TestHeartbeatHandler.java b/ambari-server/src/test/java/org/apache/ambari/server/agent/TestHeartbeatHandler.java
index 3a0b2c0..c5bac8b 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/agent/TestHeartbeatHandler.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/agent/TestHeartbeatHandler.java
@@ -104,6 +104,7 @@ import org.apache.ambari.server.state.ServiceComponentHost;
 import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.state.State;
 import org.apache.ambari.server.state.fsm.InvalidStateTransitionException;
+import org.apache.ambari.server.state.kerberos.KerberosIdentityDescriptor;
 import org.apache.ambari.server.state.svccomphost.ServiceComponentHostInstallEvent;
 import org.apache.ambari.server.utils.StageUtils;
 import org.apache.commons.codec.binary.Base64;
@@ -1567,7 +1568,7 @@ public class TestHeartbeatHandler {
     }
 
     expect(kerberosKeytabControllerMock.adjustServiceComponentFilter(anyObject(), eq(false), anyObject())).andReturn(filter).once();
-    expect(kerberosKeytabControllerMock.getFilteredKeytabs(filter,null,null)).andReturn(
+    expect(kerberosKeytabControllerMock.getFilteredKeytabs((Collection<KerberosIdentityDescriptor>) EasyMock.anyObject(), EasyMock.eq(null), EasyMock.eq(null))).andReturn(
       Sets.newHashSet(
         new ResolvedKerberosKeytab(
           "/etc/security/keytabs/dn.service.keytab",
@@ -1592,6 +1593,8 @@ public class TestHeartbeatHandler {
       )
     ).once();
 
+    expect(kerberosKeytabControllerMock.getServiceIdentities(EasyMock.anyString(), EasyMock.anyObject())).andReturn(Collections.emptySet()).anyTimes();
+
     replay(kerberosKeytabControllerMock);
 
     Field controllerField = agentCommandsPublisher.getClass().getDeclaredField("kerberosKeytabController");
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerActionTest.java b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerActionTest.java
index 246a060..0e438fb 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerActionTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/serveraction/kerberos/KerberosServerActionTest.java
@@ -25,6 +25,7 @@ import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.expectLastCall;
 
 import java.io.File;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
@@ -46,6 +47,7 @@ import org.apache.ambari.server.serveraction.kerberos.stageutils.ResolvedKerbero
 import org.apache.ambari.server.serveraction.kerberos.stageutils.ResolvedKerberosPrincipal;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.kerberos.KerberosIdentityDescriptor;
 import org.apache.ambari.server.state.stack.OsFamily;
 import org.easymock.EasyMockSupport;
 import org.junit.After;
@@ -79,7 +81,7 @@ public class KerberosServerActionTest extends EasyMockSupport {
     HostRoleCommand mockHostRoleCommand = createMock(HostRoleCommand.class);
     kerberosKeytabController = createMock(KerberosKeytabController.class);
     expect(kerberosKeytabController.adjustServiceComponentFilter(anyObject(), eq(true), anyObject())).andReturn(null).anyTimes();
-    expect(kerberosKeytabController.getFilteredKeytabs(null, null, null))
+    expect(kerberosKeytabController.getFilteredKeytabs((Collection<KerberosIdentityDescriptor>)null, null, null))
       .andReturn(
         Sets.newHashSet(new ResolvedKerberosKeytab(
           null,