You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by kd...@apache.org on 2019/02/12 18:43:42 UTC

[nifi-registry] branch master updated: NIFIREG-217 Adding identity and group transforms

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

kdoran pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git


The following commit(s) were added to refs/heads/master by this push:
     new ecce44e  NIFIREG-217 Adding identity and group transforms
ecce44e is described below

commit ecce44e587dc9e2b2fa2cbaf4b13702623577fa3
Author: Bryan Bende <bb...@apache.org>
AuthorDate: Thu Feb 7 14:32:08 2019 -0500

    NIFIREG-217 Adding identity and group transforms
    
    This closses #154.
    
    Signed-off-by: Kevin Doran <kd...@apache.org>
---
 .../ldap/tenants/LdapUserGroupProvider.java        |  4 +-
 .../ldap/tenants/LdapUserGroupProviderTest.java    | 43 +++++++++++
 .../properties/NiFiRegistryProperties.java         |  4 ++
 .../registry/properties/util/IdentityMapping.java  | 17 +++++
 .../properties/util/IdentityMappingUtil.java       | 83 +++++++++++++++++++---
 .../main/resources/conf/nifi-registry.properties   | 12 ++++
 6 files changed, 153 insertions(+), 10 deletions(-)

diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/ldap/tenants/LdapUserGroupProvider.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/ldap/tenants/LdapUserGroupProvider.java
index 984c890..5a892be 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/ldap/tenants/LdapUserGroupProvider.java
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/ldap/tenants/LdapUserGroupProvider.java
@@ -117,6 +117,7 @@ public class LdapUserGroupProvider implements UserGroupProvider {
     public static final String PROP_SYNC_INTERVAL = "Sync Interval";
 
     private List<IdentityMapping> identityMappings;
+    private List<IdentityMapping> groupMappings;
     private NiFiRegistryProperties properties;
 
     private ScheduledExecutorService ldapSync;
@@ -350,6 +351,7 @@ public class LdapUserGroupProvider implements UserGroupProvider {
 
         // extract the identity mappings from nifi-registry.properties if any are provided
         identityMappings = Collections.unmodifiableList(IdentityMappingUtil.getIdentityMappings(properties));
+        groupMappings = Collections.unmodifiableList(IdentityMappingUtil.getGroupMappings(properties));
 
         // set the base environment is necessary
         if (!baseEnvironment.isEmpty()) {
@@ -704,7 +706,7 @@ public class LdapUserGroupProvider implements UserGroupProvider {
             }
         }
 
-        return name;
+        return IdentityMappingUtil.mapIdentity(name, groupMappings);
     }
 
     private String getReferencedGroupValue(final DirContextOperations ctx) {
diff --git a/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/security/ldap/tenants/LdapUserGroupProviderTest.java b/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/security/ldap/tenants/LdapUserGroupProviderTest.java
index 9a408b2..94d2031 100644
--- a/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/security/ldap/tenants/LdapUserGroupProviderTest.java
+++ b/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/security/ldap/tenants/LdapUserGroupProviderTest.java
@@ -507,6 +507,49 @@ public class LdapUserGroupProviderTest extends AbstractLdapTestUnit {
         assertNotNull(ldapUserGroupProvider.getUserByIdentity("User 1,ou=users"));
     }
 
+    @Test
+    public void testUserIdentityMappingWithTransforms() throws Exception {
+        final Properties props = new Properties();
+        props.setProperty("nifi.registry.security.identity.mapping.pattern.dn1", "^cn=(.*?),ou=(.*?),o=(.*?)$");
+        props.setProperty("nifi.registry.security.identity.mapping.value.dn1", "$1");
+        props.setProperty("nifi.registry.security.identity.mapping.transform.dn1", "UPPER");
+
+        final NiFiRegistryProperties properties = getNiFiProperties(props);
+        ldapUserGroupProvider.setNiFiProperties(properties);
+
+        final AuthorizerConfigurationContext configurationContext = getBaseConfiguration(USER_SEARCH_BASE, null);
+        when(configurationContext.getProperty(PROP_USER_SEARCH_FILTER)).thenReturn(new StandardPropertyValue("(uid=user1)"));
+        ldapUserGroupProvider.onConfigured(configurationContext);
+
+        assertEquals(1, ldapUserGroupProvider.getUsers().size());
+        assertNotNull(ldapUserGroupProvider.getUserByIdentity("USER 1"));
+    }
+
+    @Test
+    public void testUserIdentityAndGroupMappingWithTransforms() throws Exception {
+        final Properties props = new Properties();
+        props.setProperty("nifi.registry.security.identity.mapping.pattern.dn1", "^cn=(.*?),ou=(.*?),o=(.*?)$");
+        props.setProperty("nifi.registry.security.identity.mapping.value.dn1", "$1");
+        props.setProperty("nifi.registry.security.identity.mapping.transform.dn1", "UPPER");
+        props.setProperty("nifi.registry.security.group.mapping.pattern.dn1", "^cn=(.*?),ou=(.*?),o=(.*?)$");
+        props.setProperty("nifi.registry.security.group.mapping.value.dn1", "$1");
+        props.setProperty("nifi.registry.security.group.mapping.transform.dn1", "UPPER");
+
+        final NiFiRegistryProperties properties = getNiFiProperties(props);
+        ldapUserGroupProvider.setNiFiProperties(properties);
+
+        final AuthorizerConfigurationContext configurationContext = getBaseConfiguration(USER_SEARCH_BASE, GROUP_SEARCH_BASE);
+        when(configurationContext.getProperty(PROP_USER_SEARCH_FILTER)).thenReturn(new StandardPropertyValue("(uid=user1)"));
+        when(configurationContext.getProperty(PROP_GROUP_SEARCH_FILTER)).thenReturn(new StandardPropertyValue("(cn=admins)"));
+        ldapUserGroupProvider.onConfigured(configurationContext);
+
+        assertEquals(1, ldapUserGroupProvider.getUsers().size());
+        assertNotNull(ldapUserGroupProvider.getUserByIdentity("USER 1"));
+
+        assertEquals(1, ldapUserGroupProvider.getGroups().size());
+        assertEquals("ADMINS", ldapUserGroupProvider.getGroups().iterator().next().getName());
+    }
+
     @Test(expected = SecurityProviderCreationException.class)
     public void testReferencedGroupAttributeWithoutGroupSearchBase() throws Exception {
         final AuthorizerConfigurationContext configurationContext = getBaseConfiguration("ou=users-2,o=nifi", null);
diff --git a/nifi-registry-core/nifi-registry-properties/src/main/java/org/apache/nifi/registry/properties/NiFiRegistryProperties.java b/nifi-registry-core/nifi-registry-properties/src/main/java/org/apache/nifi/registry/properties/NiFiRegistryProperties.java
index 89a8e60..aa4d19e 100644
--- a/nifi-registry-core/nifi-registry-properties/src/main/java/org/apache/nifi/registry/properties/NiFiRegistryProperties.java
+++ b/nifi-registry-core/nifi-registry-properties/src/main/java/org/apache/nifi/registry/properties/NiFiRegistryProperties.java
@@ -53,6 +53,10 @@ public class NiFiRegistryProperties extends Properties {
     public static final String SECURITY_IDENTITY_PROVIDER = "nifi.registry.security.identity.provider";
     public static final String SECURITY_IDENTITY_MAPPING_PATTERN_PREFIX = "nifi.registry.security.identity.mapping.pattern.";
     public static final String SECURITY_IDENTITY_MAPPING_VALUE_PREFIX = "nifi.registry.security.identity.mapping.value.";
+    public static final String SECURITY_IDENTITY_MAPPING_TRANSFORM_PREFIX = "nifi.registry.security.identity.mapping.transform.";
+    public static final String SECURITY_GROUP_MAPPING_PATTERN_PREFIX = "nifi.registry.security.group.mapping.pattern.";
+    public static final String SECURITY_GROUP_MAPPING_VALUE_PREFIX = "nifi.registry.security.group.mapping.value.";
+    public static final String SECURITY_GROUP_MAPPING_TRANSFORM_PREFIX = "nifi.registry.security.group.mapping.transform.";
 
     public static final String EXTENSION_DIR_PREFIX = "nifi.registry.extension.dir.";
 
diff --git a/nifi-registry-core/nifi-registry-properties/src/main/java/org/apache/nifi/registry/properties/util/IdentityMapping.java b/nifi-registry-core/nifi-registry-properties/src/main/java/org/apache/nifi/registry/properties/util/IdentityMapping.java
index df3bbe6..cedec8b 100644
--- a/nifi-registry-core/nifi-registry-properties/src/main/java/org/apache/nifi/registry/properties/util/IdentityMapping.java
+++ b/nifi-registry-core/nifi-registry-properties/src/main/java/org/apache/nifi/registry/properties/util/IdentityMapping.java
@@ -18,19 +18,33 @@ package org.apache.nifi.registry.properties.util;
 
 import java.util.regex.Pattern;
 
+import static org.apache.nifi.registry.properties.util.IdentityMapping.Transform.NONE;
+
 /**
  * Holder to pass around the key, pattern, and replacement from an identity mapping in NiFiProperties.
  */
 public class IdentityMapping {
 
+    public enum Transform {
+        NONE,
+        UPPER,
+        LOWER
+    }
+
     private final String key;
     private final Pattern pattern;
     private final String replacementValue;
+    private final Transform transform;
 
     public IdentityMapping(String key, Pattern pattern, String replacementValue) {
+        this(key, pattern, replacementValue, NONE);
+    }
+
+    public IdentityMapping(String key, Pattern pattern, String replacementValue, Transform transform) {
         this.key = key;
         this.pattern = pattern;
         this.replacementValue = replacementValue;
+        this.transform = transform;
     }
 
     public String getKey() {
@@ -45,4 +59,7 @@ public class IdentityMapping {
         return replacementValue;
     }
 
+    public Transform getTransform() {
+        return transform;
+    }
 }
diff --git a/nifi-registry-core/nifi-registry-properties/src/main/java/org/apache/nifi/registry/properties/util/IdentityMappingUtil.java b/nifi-registry-core/nifi-registry-properties/src/main/java/org/apache/nifi/registry/properties/util/IdentityMappingUtil.java
index 3c9208c..d7c2709 100644
--- a/nifi-registry-core/nifi-registry-properties/src/main/java/org/apache/nifi/registry/properties/util/IdentityMappingUtil.java
+++ b/nifi-registry-core/nifi-registry-properties/src/main/java/org/apache/nifi/registry/properties/util/IdentityMappingUtil.java
@@ -17,6 +17,7 @@
 package org.apache.nifi.registry.properties.util;
 
 import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.registry.properties.util.IdentityMapping.Transform;
 import org.apache.nifi.registry.properties.NiFiRegistryProperties;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -25,9 +26,17 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
+import java.util.function.Supplier;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import static org.apache.nifi.registry.properties.NiFiRegistryProperties.SECURITY_GROUP_MAPPING_PATTERN_PREFIX;
+import static org.apache.nifi.registry.properties.NiFiRegistryProperties.SECURITY_GROUP_MAPPING_TRANSFORM_PREFIX;
+import static org.apache.nifi.registry.properties.NiFiRegistryProperties.SECURITY_GROUP_MAPPING_VALUE_PREFIX;
+import static org.apache.nifi.registry.properties.NiFiRegistryProperties.SECURITY_IDENTITY_MAPPING_PATTERN_PREFIX;
+import static org.apache.nifi.registry.properties.NiFiRegistryProperties.SECURITY_IDENTITY_MAPPING_TRANSFORM_PREFIX;
+import static org.apache.nifi.registry.properties.NiFiRegistryProperties.SECURITY_IDENTITY_MAPPING_VALUE_PREFIX;
+
 public class IdentityMappingUtil {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(IdentityMappingUtil.class);
@@ -40,33 +49,81 @@ public class IdentityMappingUtil {
      * @return a list of identity mappings
      */
     public static List<IdentityMapping> getIdentityMappings(final NiFiRegistryProperties properties) {
+        return getMappings(
+                properties,
+                SECURITY_IDENTITY_MAPPING_PATTERN_PREFIX,
+                SECURITY_IDENTITY_MAPPING_VALUE_PREFIX,
+                SECURITY_IDENTITY_MAPPING_TRANSFORM_PREFIX,
+                () -> "Identity");
+    }
+
+    /**
+     * Buils the group mappings from NiFiProperties.
+     *
+     * @param properties the NiFiProperties instance
+     * @return a list of group mappings
+     */
+    public static List<IdentityMapping> getGroupMappings(final NiFiRegistryProperties properties) {
+        return getMappings(
+                properties,
+                SECURITY_GROUP_MAPPING_PATTERN_PREFIX,
+                SECURITY_GROUP_MAPPING_VALUE_PREFIX,
+                SECURITY_GROUP_MAPPING_TRANSFORM_PREFIX,
+                () -> "Group");
+    }
+
+    /**
+     * Builds the identity mappings from NiFiRegistryProperties.
+     *
+     * @param properties the NiFiRegistryProperties instance
+     * @return a list of identity mappings
+     */
+    private static List<IdentityMapping> getMappings(final NiFiRegistryProperties properties, final String patternPrefix,
+                                                     final String valuePrefix, final String transformPrefix, final Supplier<String> getSubject) {
         final List<IdentityMapping> mappings = new ArrayList<>();
 
         // go through each property
         for (String propertyName : properties.getPropertyKeys()) {
-            if (StringUtils.startsWith(propertyName, NiFiRegistryProperties.SECURITY_IDENTITY_MAPPING_PATTERN_PREFIX)) {
-                final String key = StringUtils.substringAfter(propertyName, NiFiRegistryProperties.SECURITY_IDENTITY_MAPPING_PATTERN_PREFIX);
+            if (StringUtils.startsWith(propertyName, patternPrefix)) {
+                final String key = StringUtils.substringAfter(propertyName, patternPrefix);
                 final String identityPattern = properties.getProperty(propertyName);
 
                 if (StringUtils.isBlank(identityPattern)) {
-                    LOGGER.warn("Identity Mapping property {} was found, but was empty", new Object[]{propertyName});
+                    LOGGER.warn("{} Mapping property {} was found, but was empty", new Object[] {getSubject.get(), propertyName});
                     continue;
                 }
 
-                final String identityValueProperty = NiFiRegistryProperties.SECURITY_IDENTITY_MAPPING_VALUE_PREFIX + key;
+                final String identityValueProperty = valuePrefix + key;
                 final String identityValue = properties.getProperty(identityValueProperty);
 
                 if (StringUtils.isBlank(identityValue)) {
-                    LOGGER.warn("Identity Mapping property {} was found, but corresponding value {} was not found",
+                    LOGGER.warn("{} Mapping property {} was found, but corresponding value {} was not found",
                             new Object[]{propertyName, identityValueProperty});
                     continue;
                 }
 
-                final IdentityMapping identityMapping = new IdentityMapping(key, Pattern.compile(identityPattern), identityValue);
+                final String identityTransformProperty = transformPrefix + key;
+                String rawIdentityTransform = properties.getProperty(identityTransformProperty);
+
+                if (StringUtils.isBlank(rawIdentityTransform)) {
+                    LOGGER.debug("{} Mapping property {} was found, but no transform was present. Using NONE.", new Object[] {getSubject.get(), propertyName});
+                    rawIdentityTransform = IdentityMapping.Transform.NONE.name();
+                }
+
+                final Transform identityTransform;
+                try {
+                    identityTransform = Transform.valueOf(rawIdentityTransform);
+                } catch (final IllegalArgumentException iae) {
+                    LOGGER.warn("{} Mapping property {} was found, but corresponding transform {} was not valid. Allowed values {}",
+                            new Object[] {getSubject.get(), propertyName, rawIdentityTransform, StringUtils.join(Transform.values(), ", ")});
+                    continue;
+                }
+
+                final IdentityMapping identityMapping = new IdentityMapping(key, Pattern.compile(identityPattern), identityValue, identityTransform);
                 mappings.add(identityMapping);
 
-                LOGGER.debug("Found Identity Mapping with key = {}, pattern = {}, value = {}",
-                        new Object[] {key, identityPattern, identityValue});
+                LOGGER.debug("Found {} Mapping with key = {}, pattern = {}, value = {}, transform = {}",
+                    new Object[] {getSubject.get(), key, identityPattern, identityValue, rawIdentityTransform});
             }
         }
 
@@ -95,7 +152,15 @@ public class IdentityMappingUtil {
             if (m.matches()) {
                 final String pattern = mapping.getPattern().pattern();
                 final String replacementValue = escapeLiteralBackReferences(mapping.getReplacementValue(), m.groupCount());
-                return identity.replaceAll(pattern, replacementValue);
+                final String replacement = identity.replaceAll(pattern, replacementValue);
+
+                if (Transform.UPPER.equals(mapping.getTransform())) {
+                    return replacement.toUpperCase();
+                } else if (Transform.LOWER.equals(mapping.getTransform())) {
+                    return replacement.toLowerCase();
+                } else {
+                    return replacement;
+                }
             }
         }
 
diff --git a/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/nifi-registry.properties b/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/nifi-registry.properties
index ce4377f..6d8771f 100644
--- a/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/nifi-registry.properties
+++ b/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/nifi-registry.properties
@@ -73,8 +73,20 @@ nifi.registry.db.sql.debug=${nifi.registry.db.sql.debug}
 #
 # nifi.registry.security.identity.mapping.pattern.dn=^CN=(.*?), OU=(.*?), O=(.*?), L=(.*?), ST=(.*?), C=(.*?)$
 # nifi.registry.security.identity.mapping.value.dn=$1@$2
+# nifi.registry.security.identity.mapping.transform.dn=NONE
+
 # nifi.registry.security.identity.mapping.pattern.kerb=^(.*?)/instance@(.*?)$
 # nifi.registry.security.identity.mapping.value.kerb=$1@$2
+# nifi.registry.security.identity.mapping.transform.kerb=UPPER
+
+# Group Mapping Properties #
+# These properties allow normalizing group names coming from external sources like LDAP. The following example
+# lowercases any group name.
+#
+# nifi.registry.security.group.mapping.pattern.anygroup=^(.*)$
+# nifi.registry.security.group.mapping.value.anygroup=$1
+# nifi.registry.security.group.mapping.transform.anygroup=LOWER
+
 
 # kerberos properties #
 nifi.registry.kerberos.krb5.file=${nifi.registry.kerberos.krb5.file}