You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by wu...@apache.org on 2022/11/03 09:40:59 UTC

[ambari] branch trunk updated: AMBARI-25186: Kerberos Client is unnecessarily installed via Blueprints when kerberos-env/kdc-type is none (#3432)

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

wuzhiguo pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 011e752b6a AMBARI-25186: Kerberos Client is unnecessarily installed via Blueprints when kerberos-env/kdc-type is none (#3432)
011e752b6a is described below

commit 011e752b6a1b7c93a5c4e5070bca4b1b772ec9b0
Author: Zhiguo Wu <wu...@apache.org>
AuthorDate: Thu Nov 3 17:40:53 2022 +0800

    AMBARI-25186: Kerberos Client is unnecessarily installed via Blueprints when kerberos-env/kdc-type is none (#3432)
---
 .../ambari/server/topology/TopologyManager.java    | 25 ++++++-
 .../server/topology/TopologyManagerTest.java       | 84 ++++++++++++++++++++--
 2 files changed, 102 insertions(+), 7 deletions(-)

diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyManager.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyManager.java
index f3fa58ab9a..b0cb3c2d16 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyManager.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/TopologyManager.java
@@ -44,6 +44,7 @@ import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorBlueprintProcessor;
 import org.apache.ambari.server.configuration.Configuration;
 import org.apache.ambari.server.controller.AmbariServer;
+import org.apache.ambari.server.controller.KerberosHelper;
 import org.apache.ambari.server.controller.RequestStatusResponse;
 import org.apache.ambari.server.controller.internal.ArtifactResourceProvider;
 import org.apache.ambari.server.controller.internal.BaseClusterRequest;
@@ -72,6 +73,7 @@ import org.apache.ambari.server.orm.dao.SettingDAO;
 import org.apache.ambari.server.orm.entities.SettingEntity;
 import org.apache.ambari.server.orm.entities.StageEntity;
 import org.apache.ambari.server.security.authorization.AuthorizationHelper;
+import org.apache.ambari.server.serveraction.kerberos.KDCType;
 import org.apache.ambari.server.state.Host;
 import org.apache.ambari.server.state.SecurityType;
 import org.apache.ambari.server.state.host.HostImpl;
@@ -209,7 +211,7 @@ public class TopologyManager {
           replayRequests(persistedState.getAllRequests());
           // ensure KERBEROS_CLIENT is present in each hostgroup even if it's not in original BP
           for(ClusterTopology clusterTopology : clusterTopologyMap.values()) {
-            if (clusterTopology.isClusterKerberosEnabled()) {
+            if (clusterTopology.isClusterKerberosEnabled() && isKerberosClientInstallAllowed(clusterTopology)) {
               addKerberosClient(clusterTopology);
             }
           }
@@ -296,7 +298,10 @@ public class TopologyManager {
 
     if (securityConfiguration != null && securityConfiguration.getType() == SecurityType.KERBEROS) {
       securityType = SecurityType.KERBEROS;
-      addKerberosClient(topology);
+
+      if (isKerberosClientInstallAllowed(topology)) {
+        addKerberosClient(topology);
+      }
 
       // refresh default stack config after adding KERBEROS_CLIENT component to topology
       topology.getBlueprint().getConfiguration().setParentConfiguration(stack.getConfiguration(topology.getBlueprint().getServices()));
@@ -360,6 +365,22 @@ public class TopologyManager {
     return getRequestStatus(logicalRequest.getRequestId());
   }
 
+  /**
+   * The Kerberos Client component is unnecessarily installed via Blueprints when kerberos-env/kdc-type is "none".
+   * The Blueprint TopologyManager should only force the Kerberos client to be installed if Kerberos is enabled
+   * and kerberos_env/kdc_type is not "none" or when kerberos_env/manage_identities is true.
+   *
+   * @param topology the Cluster Topology which provides the topology's Configuration object.
+   * @return true if kerberos_env/kdc_type is not "none" or when kerberos_env/manage_identities is true
+   */
+  private boolean isKerberosClientInstallAllowed(final ClusterTopology topology) {
+    final org.apache.ambari.server.topology.Configuration topologyConfig = topology.getBlueprint().getConfiguration();
+    final String kdc_type = topologyConfig.getPropertyValue(KerberosHelper.KERBEROS_ENV, KerberosHelper.KDC_TYPE);
+    final String manage_identities = topologyConfig.getPropertyValue(KerberosHelper.KERBEROS_ENV, KerberosHelper.MANAGE_IDENTITIES);
+
+    return KDCType.NONE != KDCType.translate(kdc_type) || Boolean.parseBoolean(manage_identities);
+  }
+
   @Subscribe
   public void onClusterConfigFinishedEvent(ClusterConfigFinishedEvent event) {
     ManagedThreadPoolExecutor taskExecutor = topologyTaskExecutorServiceMap.get(event.getClusterId());
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/topology/TopologyManagerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/topology/TopologyManagerTest.java
index 71e5fb6678..15c38efcd1 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/topology/TopologyManagerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/topology/TopologyManagerTest.java
@@ -49,13 +49,16 @@ import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.actionmanager.HostRoleStatus;
 import org.apache.ambari.server.controller.ClusterRequest;
 import org.apache.ambari.server.controller.ConfigurationRequest;
+import org.apache.ambari.server.controller.KerberosHelper;
 import org.apache.ambari.server.controller.RequestStatusResponse;
 import org.apache.ambari.server.controller.ShortTaskStatus;
 import org.apache.ambari.server.controller.internal.HostResourceProvider;
 import org.apache.ambari.server.controller.internal.ProvisionClusterRequest;
+import org.apache.ambari.server.controller.internal.RequestStatusImpl;
 import org.apache.ambari.server.controller.internal.ScaleClusterRequest;
 import org.apache.ambari.server.controller.internal.Stack;
 import org.apache.ambari.server.controller.spi.ClusterController;
+import org.apache.ambari.server.controller.spi.Request;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.ResourceProvider;
 import org.apache.ambari.server.events.ClusterProvisionStartedEvent;
@@ -66,6 +69,7 @@ import org.apache.ambari.server.orm.dao.SettingDAO;
 import org.apache.ambari.server.orm.entities.SettingEntity;
 import org.apache.ambari.server.security.authorization.AuthorizationHelper;
 import org.apache.ambari.server.security.encryption.CredentialStoreService;
+import org.apache.ambari.server.security.encryption.CredentialStoreType;
 import org.apache.ambari.server.stack.NoSuchStackException;
 import org.apache.ambari.server.state.SecurityType;
 import org.apache.ambari.server.state.quicklinksprofile.QuickLinksProfile;
@@ -142,12 +146,16 @@ public class TopologyManagerTest {
   private ExecutorService executor;
   @Mock(type = MockType.NICE)
   private PersistedState persistedState;
-  @Mock(type = MockType.NICE)
+  @Mock(type = MockType.STRICT)
   private HostGroup group1;
-  @Mock(type = MockType.NICE)
+  @Mock(type = MockType.STRICT)
   private HostGroup group2;
   @Mock(type = MockType.STRICT)
   private SecurityConfigurationFactory securityConfigurationFactory;
+  @Mock(type = MockType.NICE)
+  private SecurityConfiguration securityConfiguration;
+  @Mock(type = MockType.NICE)
+  private Credential credential;
   @Mock(type = MockType.STRICT)
   private CredentialStoreService credentialStoreService;
   @Mock(type = MockType.STRICT)
@@ -246,6 +254,10 @@ public class TopologyManagerTest {
     group1ServiceComponents.put("service2", Collections.singleton("component2"));
     group2ServiceComponents.put("service2",  Arrays.asList("component3", "component4"));
 
+    expect(securityConfiguration.getType()).andReturn(SecurityType.KERBEROS).anyTimes();
+
+    expect(credential.getType()).andReturn(CredentialStoreType.TEMPORARY).anyTimes();
+
     expect(blueprint.getHostGroup("group1")).andReturn(group1).anyTimes();
     expect(blueprint.getHostGroup("group2")).andReturn(group2).anyTimes();
     expect(blueprint.getComponents("service1")).andReturn(Arrays.asList("component1", "component3")).anyTimes();
@@ -349,6 +361,8 @@ public class TopologyManagerTest {
 
     expect(clusterController.ensureResourceProvider(anyObject(Resource.Type.class))).andReturn(resourceProvider);
 
+    expect(resourceProvider.createResources(anyObject(Request.class))).andReturn(new RequestStatusImpl(null));
+
     expect(configureClusterTaskFactory.createConfigureClusterTask(anyObject(), anyObject(), anyObject())).andReturn(configureClusterTask);
     expect(configureClusterTask.getTimeout()).andReturn(1000L);
     expect(configureClusterTask.getRepeatDelay()).andReturn(50L);
@@ -372,6 +386,12 @@ public class TopologyManagerTest {
 
     EasyMockSupport.injectMocks(topologyManagerReplay);
 
+    clazz = AmbariContext.class;
+    f = clazz.getDeclaredField("clusterController");
+    f.setAccessible(true);
+    f.set(ambariContext, clusterController);
+
+    EasyMockSupport.injectMocks(ambariContext);
   }
 
   @After
@@ -379,12 +399,14 @@ public class TopologyManagerTest {
     PowerMock.verify(System.class);
     verify(blueprint, stack, request, group1, group2, ambariContext, logicalRequestFactory,
         logicalRequest, configurationRequest, configurationRequest2, configurationRequest3,
-        requestStatusResponse, executor, persistedState, clusterTopologyMock, mockFuture, settingDAO, eventPublisher);
+        requestStatusResponse, executor, persistedState, clusterTopologyMock, mockFuture, settingDAO, eventPublisher,
+        securityConfiguration, credential);
 
     PowerMock.reset(System.class);
     reset(blueprint, stack, request, group1, group2, ambariContext, logicalRequestFactory,
         logicalRequest, configurationRequest, configurationRequest2, configurationRequest3,
-        requestStatusResponse, executor, persistedState, clusterTopologyMock, mockFuture, settingDAO, eventPublisher);
+        requestStatusResponse, executor, persistedState, clusterTopologyMock, mockFuture, settingDAO, eventPublisher,
+        securityConfiguration, credential);
   }
 
   @Test
@@ -430,6 +452,58 @@ public class TopologyManagerTest {
     //todo: assertions
   }
 
+  @Test
+  public void testDoNotAddKerberosClientAtTopologyInit_KdcTypeNone() throws Exception {
+    Map<ClusterTopology, List<LogicalRequest>> allRequests = Collections.singletonMap(clusterTopologyMock, Collections.singletonList(logicalRequest));
+
+    expect(logicalRequest.hasPendingHostRequests()).andReturn(false).anyTimes();
+    expect(logicalRequest.isFinished()).andReturn(false).anyTimes();
+    expect(requestStatusResponse.getTasks()).andReturn(Collections.emptyList()).anyTimes();
+
+    expect(clusterTopologyMock.isClusterKerberosEnabled()).andReturn(true);
+    expect(clusterTopologyMock.getClusterId()).andReturn(CLUSTER_ID).anyTimes();
+    expect(clusterTopologyMock.getBlueprint()).andReturn(blueprint).anyTimes();
+
+    expect(persistedState.getAllRequests()).andReturn(allRequests).anyTimes();
+    expect(persistedState.getProvisionRequest(CLUSTER_ID)).andReturn(logicalRequest).anyTimes();
+    expect(ambariContext.isTopologyResolved(CLUSTER_ID)).andReturn(true).anyTimes();
+
+    expect(blueprint.getSecurity()).andReturn(securityConfiguration).anyTimes();
+    expect(request.getCredentialsMap()).andReturn(Collections.singletonMap(TopologyManager.KDC_ADMIN_CREDENTIAL, credential));
+
+    bpConfiguration.setProperty(KerberosHelper.KERBEROS_ENV, KerberosHelper.KDC_TYPE, "none");
+
+    replayAll();
+
+    topologyManager.provisionCluster(request);
+  }
+
+  @Test
+  public void testDoNotAddKerberosClientAtTopologyInit_ManageIdentity() throws Exception {
+    Map<ClusterTopology, List<LogicalRequest>> allRequests = Collections.singletonMap(clusterTopologyMock, Collections.singletonList(logicalRequest));
+
+    expect(logicalRequest.hasPendingHostRequests()).andReturn(false).anyTimes();
+    expect(logicalRequest.isFinished()).andReturn(false).anyTimes();
+    expect(requestStatusResponse.getTasks()).andReturn(Collections.emptyList()).anyTimes();
+
+    expect(clusterTopologyMock.isClusterKerberosEnabled()).andReturn(true);
+    expect(clusterTopologyMock.getClusterId()).andReturn(CLUSTER_ID).anyTimes();
+    expect(clusterTopologyMock.getBlueprint()).andReturn(blueprint).anyTimes();
+
+    expect(persistedState.getAllRequests()).andReturn(allRequests).anyTimes();
+    expect(persistedState.getProvisionRequest(CLUSTER_ID)).andReturn(logicalRequest).anyTimes();
+    expect(ambariContext.isTopologyResolved(CLUSTER_ID)).andReturn(true).anyTimes();
+
+    expect(blueprint.getSecurity()).andReturn(securityConfiguration).anyTimes();
+    expect(request.getCredentialsMap()).andReturn(Collections.singletonMap(TopologyManager.KDC_ADMIN_CREDENTIAL, credential));
+
+    bpConfiguration.setProperty(KerberosHelper.KERBEROS_ENV, KerberosHelper.MANAGE_IDENTITIES, "false");
+
+    replayAll();
+
+    topologyManager.provisionCluster(request);
+  }
+
   @Test
   public void testBlueprintRequestCompletion() throws Exception {
     List<ShortTaskStatus> tasks = new ArrayList<>();
@@ -554,7 +628,7 @@ public class TopologyManagerTest {
             configurationRequest, configurationRequest2, configurationRequest3, executor,
             persistedState, clusterTopologyMock, securityConfigurationFactory, credentialStoreService,
             clusterController, resourceProvider, mockFuture, requestStatusResponse, logicalRequest, settingDAO,
-            configureClusterTaskFactory, configureClusterTask, eventPublisher);
+            configureClusterTaskFactory, configureClusterTask, eventPublisher, securityConfiguration, credential);
   }
 
   @Test(expected = InvalidTopologyException.class)


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@ambari.apache.org
For additional commands, e-mail: commits-help@ambari.apache.org