Repository: ambari Updated Branches: refs/heads/trunk 4b48b80c0 -> 1aad067cf
AMBARI-20366. Filter out kerberos rules in exported blueprint (Amruta Borkar via magyari_sandor) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/1aad067c Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/1aad067c Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/1aad067c Branch: refs/heads/trunk Commit: 1aad067cff1601d3c0ddd1f019df0fa9eb442199 Parents: 4b48b80 Author: Amruta Borkar <[email protected]> Authored: Fri May 5 12:45:21 2017 +0200 Committer: Sandor Magyari <[email protected]> Committed: Fri May 5 15:48:35 2017 +0200 ---------------------------------------------------------------------- .../BlueprintConfigurationProcessor.java | 56 +++++++++++++++++--- .../render/ClusterBlueprintRendererTest.java | 38 +++++++++++-- .../BlueprintConfigurationProcessorTest.java | 56 +++++++++++++++++--- 3 files changed, 133 insertions(+), 17 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/1aad067c/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessor.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessor.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessor.java index 7381387..1a2947b 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessor.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessor.java @@ -34,6 +34,8 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.apache.ambari.server.AmbariException; +import org.apache.ambari.server.state.Cluster; import org.apache.ambari.server.state.PropertyDependencyInfo; import org.apache.ambari.server.state.ValueAttributesInfo; import org.apache.ambari.server.topology.AdvisedConfiguration; @@ -155,8 +157,10 @@ public class BlueprintConfigurationProcessor { * This will initially be used to filter out the Ranger Passwords, but * could be extended in the future for more generic purposes. */ - private static final PropertyFilter[] exportPropertyFilters = - { new PasswordPropertyFilter(), + private PropertyFilter[] getExportPropertyFilters (Map<Long, Set<String>> authToLocalPerClusterMap) + { + return new PropertyFilter[] { + new PasswordPropertyFilter(), new SimplePropertyNameExportFilter("tez.tez-ui.history-url.base", "tez-site"), new SimplePropertyNameExportFilter("admin_server_host", "kerberos-env"), new SimplePropertyNameExportFilter("kdc_hosts", "kerberos-env"), @@ -168,8 +172,9 @@ public class BlueprintConfigurationProcessor { new SimplePropertyNameExportFilter("domains", "krb5-conf"), new SimplePropertyNameExportFilter("dfs_ha_initial_namenode_active", "hadoop-env"), new SimplePropertyNameExportFilter("dfs_ha_initial_namenode_standby", "hadoop-env"), - new StackPropertyTypeFilter() - }; + new StackPropertyTypeFilter(), + new KerberosAuthToLocalRulesFilter(authToLocalPerClusterMap)}; + } /** * Statically-defined list of filters to apply on cluster config @@ -518,6 +523,16 @@ public class BlueprintConfigurationProcessor { */ private void doFilterPriorToExport(Configuration configuration) { Map<String, Map<String, String>> properties = configuration.getFullProperties(); + Map<Long, Set<String>> authToLocalPerClusterMap = null; + try { + String clusterName = clusterTopology.getAmbariContext().getClusterName(clusterTopology.getClusterId()); + Cluster cluster = clusterTopology.getAmbariContext().getController().getClusters().getCluster(clusterName); + authToLocalPerClusterMap = new HashMap<Long, Set<String>>(); + authToLocalPerClusterMap.put(Long.valueOf(clusterTopology.getClusterId()), clusterTopology.getAmbariContext().getController().getKerberosHelper().getKerberosDescriptor(cluster).getAllAuthToLocalProperties()); + } catch (AmbariException e) { + LOG.error("Error while getting authToLocal properties. ", e); + } + PropertyFilter [] exportPropertyFilters = getExportPropertyFilters(authToLocalPerClusterMap); for (Map.Entry<String, Map<String, String>> configEntry : properties.entrySet()) { String type = configEntry.getKey(); try { @@ -534,7 +549,7 @@ public class BlueprintConfigurationProcessor { for (Map.Entry<String, String> propertyEntry : typeProperties.entrySet()) { String propertyName = propertyEntry.getKey(); String propertyValue = propertyEntry.getValue(); - if (shouldPropertyBeExcludedForBlueprintExport(propertyName, propertyValue, type, clusterTopology)) { + if (shouldPropertyBeExcludedForBlueprintExport(propertyName, propertyValue, type, clusterTopology, exportPropertyFilters)) { configuration.removeProperty(type, propertyName); } } @@ -1032,7 +1047,7 @@ public class BlueprintConfigurationProcessor { * @return true if the property should be excluded * false if the property should not be excluded */ - private static boolean shouldPropertyBeExcludedForBlueprintExport(String propertyName, String propertyValue, String propertyType, ClusterTopology topology) { + private boolean shouldPropertyBeExcludedForBlueprintExport(String propertyName, String propertyValue, String propertyType, ClusterTopology topology, PropertyFilter [] exportPropertyFilters ) { for(PropertyFilter filter : exportPropertyFilters) { if (!filter.isPropertyIncluded(propertyName, propertyValue, propertyType, topology)) { return true; @@ -3023,6 +3038,35 @@ public class BlueprintConfigurationProcessor { } /** + * A Filter that excludes Kerberos auth_to_local rules properties. + */ + private static class KerberosAuthToLocalRulesFilter implements PropertyFilter { + + /** + * Query to determine if a given property should be included in a collection of + * properties. + * + * This implementation filters Kerberos auth_to_local rules properties. + * + * @param propertyName property name + * @param propertyValue property value + * @param configType config type that contains this property + * @param topology cluster topology instance + * + * @return true if the property should be included + * false if the property should not be included + */ + Map<Long, Set<String>> authToLocalPerClusterMap = null; + KerberosAuthToLocalRulesFilter (Map<Long, Set<String>> authToLocalPerClusterMap) { + this.authToLocalPerClusterMap = authToLocalPerClusterMap; + } + @Override + public boolean isPropertyIncluded(String propertyName, String propertyValue, String configType, ClusterTopology topology) { + return (authToLocalPerClusterMap == null || authToLocalPerClusterMap.get(topology.getClusterId()) == null || !authToLocalPerClusterMap.get(topology.getClusterId()).contains(String.format("%s/%s", configType, propertyName))); + } + } + + /** * Simple filter implementation used to remove named properties from * a Blueprint export. Some properties with hostname information set * by the UI do not have straightforward mappings to hosts, so these properties http://git-wip-us.apache.org/repos/asf/ambari/blob/1aad067c/ambari-server/src/test/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRendererTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRendererTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRendererTest.java index 13db5f8..95bceb8 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRendererTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/api/query/render/ClusterBlueprintRendererTest.java @@ -52,6 +52,11 @@ import org.apache.ambari.server.api.services.Result; import org.apache.ambari.server.api.services.ResultImpl; import org.apache.ambari.server.api.util.TreeNode; import org.apache.ambari.server.api.util.TreeNodeImpl; +import org.apache.ambari.server.controller.AmbariManagementController; +import org.apache.ambari.server.controller.AmbariManagementControllerImpl; +import org.apache.ambari.server.controller.AmbariServer; +import org.apache.ambari.server.controller.KerberosHelper; +import org.apache.ambari.server.controller.KerberosHelperImpl; import org.apache.ambari.server.controller.internal.ArtifactResourceProvider; import org.apache.ambari.server.controller.internal.ClusterControllerImpl; import org.apache.ambari.server.controller.internal.ResourceImpl; @@ -61,8 +66,12 @@ import org.apache.ambari.server.controller.spi.Predicate; 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.state.Cluster; +import org.apache.ambari.server.state.Clusters; import org.apache.ambari.server.state.DesiredConfig; import org.apache.ambari.server.state.ServiceInfo; +import org.apache.ambari.server.state.cluster.ClustersImpl; +import org.apache.ambari.server.state.kerberos.KerberosDescriptor; import org.apache.ambari.server.topology.AmbariContext; import org.apache.ambari.server.topology.Blueprint; import org.apache.ambari.server.topology.ClusterTopology; @@ -85,12 +94,19 @@ import org.powermock.modules.junit4.PowerMockRunner; */ @SuppressWarnings("unchecked") @RunWith(PowerMockRunner.class) -@PrepareForTest(AmbariContext.class) +@PrepareForTest({AmbariContext.class, AmbariServer.class}) public class ClusterBlueprintRendererTest { private static final ClusterTopology topology = createNiceMock(ClusterTopology.class); private static final ClusterController clusterController = createNiceMock(ClusterControllerImpl.class); + private static final AmbariContext ambariContext = createNiceMock(AmbariContext.class); + private static final Cluster cluster = createNiceMock(Cluster.class); + private static final Clusters clusters = createNiceMock(ClustersImpl.class); + private static final AmbariManagementController controller = createNiceMock(AmbariManagementControllerImpl.class); + private static final KerberosHelper kerberosHelper = createNiceMock(KerberosHelperImpl.class); + private static final KerberosDescriptor kerberosDescriptor = createNiceMock(KerberosDescriptor.class); + private static final Blueprint blueprint = createNiceMock(Blueprint.class); private static final Stack stack = createNiceMock(Stack.class); private static final HostGroup group1 = createNiceMock(HostGroup.class); @@ -155,7 +171,20 @@ public class ClusterBlueprintRendererTest { expect(group1.getComponents()).andReturn(group1Components).anyTimes(); expect(group2.getComponents()).andReturn(group2Components).anyTimes(); - replay(topology, blueprint, stack, group1, group2); + expect(topology.getAmbariContext()).andReturn(ambariContext).anyTimes(); + expect(topology.getClusterId()).andReturn(1L).anyTimes(); + PowerMock.mockStatic(AmbariServer.class); + expect(AmbariServer.getController()).andReturn(controller).anyTimes(); + PowerMock.replay(AmbariServer.class); + expect(clusters.getCluster("clusterName")).andReturn(cluster).anyTimes(); + expect(controller.getKerberosHelper()).andReturn(kerberosHelper).anyTimes(); + expect(controller.getClusters()).andReturn(clusters).anyTimes(); + expect(kerberosHelper.getKerberosDescriptor(cluster)).andReturn(kerberosDescriptor).anyTimes(); + Set<String> properties = new HashSet<String>(); + properties.add("core-site/hadoop.security.auth_to_local"); + expect(kerberosDescriptor.getAllAuthToLocalProperties()).andReturn(properties).anyTimes(); + expect(ambariContext.getClusterName(1L)).andReturn("clusterName").anyTimes(); + replay(topology, blueprint, stack, group1, group2, ambariContext, clusters, controller, kerberosHelper, cluster, kerberosDescriptor); } private void setupMocksForKerberosEnabledCluster() throws Exception { @@ -165,6 +194,7 @@ public class ClusterBlueprintRendererTest { PowerMock.mockStatic(AmbariContext.class); expect(AmbariContext.getClusterController()).andReturn(clusterController).anyTimes(); + expect(AmbariContext.getController()).andReturn(controller).anyTimes(); reset(topology); @@ -210,8 +240,8 @@ public class ClusterBlueprintRendererTest { @After public void tearDown() { - verify(topology, blueprint, stack, group1, group2); - reset(topology, blueprint, stack, group1, group2); + verify(topology, blueprint, stack, group1, group2, ambariContext, clusters, controller, kerberosHelper, cluster, kerberosDescriptor); + reset(topology, blueprint, stack, group1, group2, ambariContext, clusters, controller, kerberosHelper, cluster, kerberosDescriptor); } @Test http://git-wip-us.apache.org/repos/asf/ambari/blob/1aad067c/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessorTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessorTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessorTest.java index 8ff70a1..24fc3c7 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessorTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/BlueprintConfigurationProcessorTest.java @@ -18,16 +18,16 @@ package org.apache.ambari.server.controller.internal; -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertNull; -import static junit.framework.Assert.assertTrue; -import static junit.framework.Assert.fail; import static org.easymock.EasyMock.anyObject; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.reset; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.util.ArrayList; import java.util.Arrays; @@ -40,11 +40,17 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.apache.ambari.server.controller.AmbariManagementController; +import org.apache.ambari.server.controller.AmbariServer; +import org.apache.ambari.server.controller.KerberosHelper; import org.apache.ambari.server.controller.StackConfigurationResponse; +import org.apache.ambari.server.state.Cluster; +import org.apache.ambari.server.state.Clusters; import org.apache.ambari.server.state.PropertyDependencyInfo; import org.apache.ambari.server.state.PropertyInfo; import org.apache.ambari.server.state.ServiceInfo; import org.apache.ambari.server.state.ValueAttributesInfo; +import org.apache.ambari.server.state.kerberos.KerberosDescriptor; import org.apache.ambari.server.topology.AdvisedConfiguration; import org.apache.ambari.server.topology.AmbariContext; import org.apache.ambari.server.topology.Blueprint; @@ -69,6 +75,10 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.easymock.PowerMock; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; @@ -79,6 +89,8 @@ import com.google.common.collect.Maps; /** * BlueprintConfigurationProcessor unit tests. */ +@RunWith(PowerMockRunner.class) +@PrepareForTest(AmbariServer.class) public class BlueprintConfigurationProcessorTest extends EasyMockSupport { private static final Configuration EMPTY_CONFIG = new Configuration(Collections.<String, Map<String, String>>emptyMap(), Collections.<String, Map<String, Map<String, String>>>emptyMap()); @@ -99,6 +111,21 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport { @Mock(type = MockType.NICE) private Stack stack; + @Mock(type = MockType.NICE) + private AmbariManagementController controller; + + @Mock(type = MockType.NICE) + private KerberosHelper kerberosHelper; + + @Mock(type = MockType.NICE) + private KerberosDescriptor kerberosDescriptor; + + @Mock(type = MockType.NICE) + private Clusters clusters; + + @Mock(type = MockType.NICE) + private Cluster cluster; + @Mock private TopologyRequest topologyRequestMock; @@ -198,6 +225,18 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport { Set<String> emptySet = Collections.emptySet(); expect(stack.getExcludedConfigurationTypes(anyObject(String.class))).andReturn(emptySet).anyTimes(); + expect(ambariContext.isClusterKerberosEnabled(1)).andReturn(true).once(); + expect(ambariContext.getClusterName(1L)).andReturn("clusterName").anyTimes(); + PowerMock.mockStatic(AmbariServer.class); + expect(AmbariServer.getController()).andReturn(controller).anyTimes(); + PowerMock.replay(AmbariServer.class); + expect(clusters.getCluster("clusterName")).andReturn(cluster).anyTimes(); + expect(controller.getKerberosHelper()).andReturn(kerberosHelper).anyTimes(); + expect(controller.getClusters()).andReturn(clusters).anyTimes(); + expect(kerberosHelper.getKerberosDescriptor(cluster)).andReturn(kerberosDescriptor).anyTimes(); + Set<String> properties = new HashSet<String>(); + properties.add("core-site/hadoop.security.auth_to_local"); + expect(kerberosDescriptor.getAllAuthToLocalProperties()).andReturn(properties).anyTimes(); } @After @@ -902,6 +941,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport { kerberosEnvProperties.put("kdc_hosts", expectedHostName + ",secondary.kdc.org"); kerberosEnvProperties.put("master_kdc", expectedHostName); coreSiteProperties.put("hadoop.proxyuser.yarn.hosts", expectedHostName); + coreSiteProperties.put("hadoop.security.auth_to_local", "RULE:clustername"); Configuration clusterConfig = new Configuration(configProperties, Collections.<String, Map<String, Map<String, String>>>emptyMap()); @@ -933,6 +973,8 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport { kerberosEnvProperties.containsKey("master_kdc")); assertEquals("hadoop.proxyuser.yarn.hosts was not exported correctly", createExportedHostName("host_group_1"), coreSiteProperties.get("hadoop.proxyuser.yarn.hosts")); + assertFalse("hadoop.security.auth_to_local should not be present in exported blueprint in core-site", + coreSiteProperties.containsKey("hadoop.security.auth_to_local")); } @Test @@ -8099,7 +8141,7 @@ public class BlueprintConfigurationProcessorTest extends EasyMockSupport { throws InvalidTopologyException { - replay(stack, serviceInfo, ambariContext); + replay(stack, serviceInfo, ambariContext, controller, kerberosHelper, kerberosDescriptor, clusters, cluster); Map<String, HostGroupInfo> hostGroupInfo = new HashMap<>(); Collection<String> allServices = new HashSet<>();
