You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by rn...@apache.org on 2015/05/15 17:12:04 UTC

ambari git commit: AMBARI-9480. Ranger password properties are incorrectly included in Blueprint export. (rnettleton)

Repository: ambari
Updated Branches:
  refs/heads/trunk 0fe39d5e8 -> 46c802dae


AMBARI-9480. Ranger password properties are incorrectly included in Blueprint export. (rnettleton)


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

Branch: refs/heads/trunk
Commit: 46c802daed7ec886da1a678fba4ab361b2800e3d
Parents: 0fe39d5
Author: Bob Nettleton <rn...@hortonworks.com>
Authored: Fri May 15 11:10:42 2015 -0400
Committer: Bob Nettleton <rn...@hortonworks.com>
Committed: Fri May 15 11:11:51 2015 -0400

----------------------------------------------------------------------
 .../BlueprintConfigurationProcessor.java        | 118 +++++++++++++++++++
 .../BlueprintConfigurationProcessorTest.java    |  82 +++++++++++++
 2 files changed, 200 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/46c802da/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 aef6664..d7ff543 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
@@ -106,6 +106,13 @@ public class BlueprintConfigurationProcessor {
     new HashSet<String>(Arrays.asList("fs.defaultFS", "hbase.rootdir", "instance.volumes"));
 
   /**
+   * Statically-defined list of filters to apply on property exports.
+   * 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[] propertyFilters = { new PasswordPropertyFilter() };
+
+  /**
    * Configuration properties to be updated
    */
   //private Map<String, Map<String, String>> properties;
@@ -233,6 +240,39 @@ public class BlueprintConfigurationProcessor {
       doMultiHostExportUpdate(multiHostTopologyUpdaters, properties);
 
       doRemovePropertyExport(removePropertyUpdaters, properties);
+
+      doFilterPriorToExport(properties);
+    }
+  }
+
+  /**
+   * This method iterates over the properties passed in, and applies a
+   * list of filters to the properties.
+   *
+   * If any filter implementations indicate that the property should
+   * not be included in a collection (a Blueprint export in this case),
+   * then the property is removed prior to the export.
+   *
+   *
+   * @param properties config properties to process for filtering
+   */
+  private static void doFilterPriorToExport(Map<String, Map<String, String>> properties) {
+    for (String configType : properties.keySet()) {
+      Map<String, String> configPropertiesPerType =
+        properties.get(configType);
+
+      Set<String> propertiesToExclude = new HashSet<String>();
+      for (String propertyName : configPropertiesPerType.keySet()) {
+        if (shouldPropertyBeExcluded(propertyName, configPropertiesPerType.get(propertyName))) {
+          propertiesToExclude.add(propertyName);
+        }
+      }
+
+      if (!propertiesToExclude.isEmpty()) {
+        for (String propertyName : propertiesToExclude) {
+          configPropertiesPerType.remove(propertyName);
+        }
+      }
     }
   }
 
@@ -435,6 +475,29 @@ public class BlueprintConfigurationProcessor {
   }
 
   /**
+   * Iterates over the list of registered filters for this config processor, and
+   * queries each filter to determine if a given property should be included
+   * in a property collection.  If any filters return false for the isPropertyIncluded()
+   * query, then the property should be excluded.
+   *
+   * @param propertyName config property name
+   * @param propertyValue config property value
+   * @return true if the property should be excluded
+   *         false if the property should not be excluded
+   */
+  private static boolean shouldPropertyBeExcluded(String propertyName, String propertyValue) {
+    for(PropertyFilter filter : propertyFilters) {
+      if (!filter.isPropertyIncluded(propertyName, propertyValue)) {
+        return true;
+      }
+    }
+
+    // if no filters require that the property be excluded,
+    // then allow it to be included in the property collection
+    return false;
+  }
+
+  /**
    * Update single host topology configuration properties for blueprint export.
    *
    * @param updaters    registered updaters
@@ -1790,4 +1853,59 @@ public class BlueprintConfigurationProcessor {
       properties.put(property, defaultValue);
     }
   }
+
+
+  /**
+   * Defines an interface for querying a filter to determine
+   * if a given property should be included in an external
+   * collection of properties.
+   */
+  private static interface PropertyFilter {
+
+    /**
+     * Query to determine if a given property should be included in a collection of
+     * properties.
+     *
+     * @param propertyName property name
+     * @param propertyValue property value
+     * @return true if the property should be included
+     *         false if the property should not be included
+     */
+    boolean isPropertyIncluded(String propertyName, String propertyValue);
+  }
+
+  /**
+   * A Filter that excludes properties if the property name matches
+   * a pattern of "*PASSWORD" (case-insensitive).
+   *
+   */
+  private static class PasswordPropertyFilter implements PropertyFilter {
+
+    private static final Pattern PASSWORD_NAME_REGEX = Pattern.compile("\\S+PASSWORD", Pattern.CASE_INSENSITIVE);
+
+    /**
+     * Query to determine if a given property should be included in a collection of
+     * properties.
+     *
+     * This implementation uses a regular expression to determine if
+     * a given property name ends with "PASSWORD", using a case-insensitive match.
+     * This will be used to filter out Ranger passwords that are not considered "required"
+     * passwords by the stack metadata. This could potentially also
+     * be useful in filtering out properties that are added to
+     * stacks, but not directly marked as the PASSWORD type, even if they
+     * are indeed passwords.
+     *
+     *
+     * @param propertyName property name
+     * @param propertyValue property value
+     *
+     * @return true if the property should be included
+     *         false if the property should not be included
+     */
+    @Override
+    public boolean isPropertyIncluded(String propertyName, String propertyValue) {
+      return !PASSWORD_NAME_REGEX.matcher(propertyName).matches();
+    }
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/46c802da/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 390f73e..bebc884 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
@@ -456,6 +456,88 @@ public class BlueprintConfigurationProcessorTest {
   }
 
   @Test
+  public void testDoUpdateForBlueprintExport_PasswordFilterApplied() throws Exception {
+    Map<String, Map<String, String>> properties = new HashMap<String, Map<String, String>>();
+    Map<String, String> typeProps = new HashMap<String, String>();
+    typeProps.put("REPOSITORY_CONFIG_PASSWORD", "test-password-one");
+    typeProps.put("SSL_KEYSTORE_PASSWORD", "test-password-two");
+    typeProps.put("SSL_TRUSTSTORE_PASSWORD", "test-password-three");
+    typeProps.put("XAAUDIT.DB.PASSWORD", "test-password-four");
+    typeProps.put("test.ssl.password", "test-password-five");
+    typeProps.put("test.password.should.be.included", "test-another-pwd");
+
+    // create a custom config type, to verify that the filters can
+    // be applied across all config types
+    Map<String, String> customProps = new HashMap<String, String>();
+    customProps.put("my_test_PASSWORD", "should be excluded");
+    customProps.put("PASSWORD_mytest", "should be included");
+
+    properties.put("ranger-yarn-plugin-properties", typeProps);
+    properties.put("custom-test-properties", customProps);
+
+    Configuration clusterConfig = new Configuration(properties,
+      Collections.<String, Map<String, Map<String, String>>>emptyMap());
+
+    Collection<String> hgComponents = new HashSet<String>();
+    hgComponents.add("NAMENODE");
+    hgComponents.add("SECONDARY_NAMENODE");
+    hgComponents.add("RESOURCEMANAGER");
+    TestHostGroup group1 = new TestHostGroup("group1", hgComponents, Collections.singleton("testhost"));
+
+    Collection<String> hgComponents2 = new HashSet<String>();
+    hgComponents2.add("DATANODE");
+    hgComponents2.add("HDFS_CLIENT");
+    TestHostGroup group2 = new TestHostGroup("group2", hgComponents2, Collections.singleton("testhost2"));
+
+    Collection<TestHostGroup> hostGroups = new HashSet<TestHostGroup>();
+    hostGroups.add(group1);
+    hostGroups.add(group2);
+
+    ClusterTopology topology = createClusterTopology(bp, clusterConfig, hostGroups);
+    BlueprintConfigurationProcessor configProcessor = new BlueprintConfigurationProcessor(topology);
+    configProcessor.doUpdateForBlueprintExport();
+
+
+    assertEquals("Exported properties map was not of the expected size",
+                 1,typeProps.size());
+    assertEquals("ranger-yarn-plugin-properties config type was not properly exported",
+                 1, properties.get("ranger-yarn-plugin-properties").size());
+
+    // verify that the following password properties matching the "*_PASSWORD" rule have been excluded
+    assertFalse("Password property should have been excluded",
+                properties.get("ranger-yarn-plugin-properties").containsKey("REPOSITORY_CONFIG_PASSWORD"));
+    assertFalse("Password property should have been excluded",
+                properties.get("ranger-yarn-plugin-properties").containsKey("SSL_KEYSTORE_PASSWORD"));
+    assertFalse("Password property should have been excluded",
+                properties.get("ranger-yarn-plugin-properties").containsKey("SSL_TRUSTSTORE_PASSWORD"));
+    assertFalse("Password property should have been excluded",
+                properties.get("ranger-yarn-plugin-properties").containsKey("XAAUDIT.DB.PASSWORD"));
+    assertFalse("Password property should have been excluded",
+      properties.get("ranger-yarn-plugin-properties").containsKey("test.ssl.password"));
+
+
+    // verify that the property that does not match the "*_PASSWORD" rule is still included
+    assertTrue("Expected password property not found",
+      properties.get("ranger-yarn-plugin-properties").containsKey("test.password.should.be.included"));
+
+    // verify the custom properties map has been modified by the filters
+    assertEquals("custom-test-properties type was not properly exported",
+      1, properties.get("custom-test-properties").size());
+
+    // verify that the following password properties matching the "*_PASSWORD" rule have been excluded
+    assertFalse("Password property should have been excluded",
+      properties.get("custom-test-properties").containsKey("my_test_PASSWORD"));
+
+    // verify that the property that does not match the "*_PASSWORD" rule is still included
+    assertTrue("Expected password property not found",
+      properties.get("custom-test-properties").containsKey("PASSWORD_mytest"));
+    assertEquals("Expected password property should not have been modified",
+      "should be included", properties.get("custom-test-properties").get("PASSWORD_mytest"));
+
+  }
+
+
+  @Test
   public void testFalconConfigExport() throws Exception {
     final String expectedHostName = "c6401.apache.ambari.org";
     final String expectedPortNum = "808080";