mirror of https://github.com/apache/nifi.git
NIFI-5135:
- Adding support for applying transforms to user identities and group names. This closes #2673. Signed-off-by: Bryan Bende <bbende@apache.org>
This commit is contained in:
parent
ff04f8efee
commit
5cfa29e48f
|
@ -151,6 +151,10 @@ public abstract class NiFiProperties {
|
||||||
public static final String SECURITY_OCSP_RESPONDER_CERTIFICATE = "nifi.security.ocsp.responder.certificate";
|
public static final String SECURITY_OCSP_RESPONDER_CERTIFICATE = "nifi.security.ocsp.responder.certificate";
|
||||||
public static final String SECURITY_IDENTITY_MAPPING_PATTERN_PREFIX = "nifi.security.identity.mapping.pattern.";
|
public static final String SECURITY_IDENTITY_MAPPING_PATTERN_PREFIX = "nifi.security.identity.mapping.pattern.";
|
||||||
public static final String SECURITY_IDENTITY_MAPPING_VALUE_PREFIX = "nifi.security.identity.mapping.value.";
|
public static final String SECURITY_IDENTITY_MAPPING_VALUE_PREFIX = "nifi.security.identity.mapping.value.";
|
||||||
|
public static final String SECURITY_IDENTITY_MAPPING_TRANSFORM_PREFIX = "nifi.security.identity.mapping.transform.";
|
||||||
|
public static final String SECURITY_GROUP_MAPPING_PATTERN_PREFIX = "nifi.security.group.mapping.pattern.";
|
||||||
|
public static final String SECURITY_GROUP_MAPPING_VALUE_PREFIX = "nifi.security.group.mapping.value.";
|
||||||
|
public static final String SECURITY_GROUP_MAPPING_TRANSFORM_PREFIX = "nifi.security.group.mapping.transform.";
|
||||||
|
|
||||||
// oidc
|
// oidc
|
||||||
public static final String SECURITY_USER_OIDC_DISCOVERY_URL = "nifi.security.user.oidc.discovery.url";
|
public static final String SECURITY_USER_OIDC_DISCOVERY_URL = "nifi.security.user.oidc.discovery.url";
|
||||||
|
|
|
@ -18,19 +18,33 @@ package org.apache.nifi.authorization.util;
|
||||||
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import static org.apache.nifi.authorization.util.IdentityMapping.Transform.NONE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holder to pass around the key, pattern, and replacement from an identity mapping in NiFiProperties.
|
* Holder to pass around the key, pattern, and replacement from an identity mapping in NiFiProperties.
|
||||||
*/
|
*/
|
||||||
public class IdentityMapping {
|
public class IdentityMapping {
|
||||||
|
|
||||||
|
public enum Transform {
|
||||||
|
NONE,
|
||||||
|
UPPER,
|
||||||
|
LOWER
|
||||||
|
}
|
||||||
|
|
||||||
private final String key;
|
private final String key;
|
||||||
private final Pattern pattern;
|
private final Pattern pattern;
|
||||||
private final String replacementValue;
|
private final String replacementValue;
|
||||||
|
private final Transform transform;
|
||||||
|
|
||||||
public IdentityMapping(String key, Pattern pattern, String replacementValue) {
|
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.key = key;
|
||||||
this.pattern = pattern;
|
this.pattern = pattern;
|
||||||
this.replacementValue = replacementValue;
|
this.replacementValue = replacementValue;
|
||||||
|
this.transform = transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getKey() {
|
public String getKey() {
|
||||||
|
@ -45,4 +59,7 @@ public class IdentityMapping {
|
||||||
return replacementValue;
|
return replacementValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Transform getTransform() {
|
||||||
|
return transform;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.apache.nifi.authorization.util;
|
package org.apache.nifi.authorization.util;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.nifi.authorization.util.IdentityMapping.Transform;
|
||||||
import org.apache.nifi.util.NiFiProperties;
|
import org.apache.nifi.util.NiFiProperties;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -25,9 +26,17 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Supplier;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import static org.apache.nifi.util.NiFiProperties.SECURITY_GROUP_MAPPING_PATTERN_PREFIX;
|
||||||
|
import static org.apache.nifi.util.NiFiProperties.SECURITY_GROUP_MAPPING_TRANSFORM_PREFIX;
|
||||||
|
import static org.apache.nifi.util.NiFiProperties.SECURITY_GROUP_MAPPING_VALUE_PREFIX;
|
||||||
|
import static org.apache.nifi.util.NiFiProperties.SECURITY_IDENTITY_MAPPING_PATTERN_PREFIX;
|
||||||
|
import static org.apache.nifi.util.NiFiProperties.SECURITY_IDENTITY_MAPPING_TRANSFORM_PREFIX;
|
||||||
|
import static org.apache.nifi.util.NiFiProperties.SECURITY_IDENTITY_MAPPING_VALUE_PREFIX;
|
||||||
|
|
||||||
public class IdentityMappingUtil {
|
public class IdentityMappingUtil {
|
||||||
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(IdentityMappingUtil.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(IdentityMappingUtil.class);
|
||||||
|
@ -40,33 +49,76 @@ public class IdentityMappingUtil {
|
||||||
* @return a list of identity mappings
|
* @return a list of identity mappings
|
||||||
*/
|
*/
|
||||||
public static List<IdentityMapping> getIdentityMappings(final NiFiProperties properties) {
|
public static List<IdentityMapping> getIdentityMappings(final NiFiProperties 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 NiFiProperties properties) {
|
||||||
|
return getMappings(
|
||||||
|
properties,
|
||||||
|
SECURITY_GROUP_MAPPING_PATTERN_PREFIX,
|
||||||
|
SECURITY_GROUP_MAPPING_VALUE_PREFIX,
|
||||||
|
SECURITY_GROUP_MAPPING_TRANSFORM_PREFIX,
|
||||||
|
() -> "Group");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<IdentityMapping> getMappings(final NiFiProperties properties, final String patternPrefix,
|
||||||
|
final String valuePrefix, final String transformPrefix, final Supplier<String> getSubject) {
|
||||||
|
|
||||||
final List<IdentityMapping> mappings = new ArrayList<>();
|
final List<IdentityMapping> mappings = new ArrayList<>();
|
||||||
|
|
||||||
// go through each property
|
// go through each property
|
||||||
for (String propertyName : properties.getPropertyKeys()) {
|
for (String propertyName : properties.getPropertyKeys()) {
|
||||||
if (StringUtils.startsWith(propertyName, NiFiProperties.SECURITY_IDENTITY_MAPPING_PATTERN_PREFIX)) {
|
if (StringUtils.startsWith(propertyName, patternPrefix)) {
|
||||||
final String key = StringUtils.substringAfter(propertyName, NiFiProperties.SECURITY_IDENTITY_MAPPING_PATTERN_PREFIX);
|
final String key = StringUtils.substringAfter(propertyName, patternPrefix);
|
||||||
final String identityPattern = properties.getProperty(propertyName);
|
final String identityPattern = properties.getProperty(propertyName);
|
||||||
|
|
||||||
if (StringUtils.isBlank(identityPattern)) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String identityValueProperty = NiFiProperties.SECURITY_IDENTITY_MAPPING_VALUE_PREFIX + key;
|
final String identityValueProperty = valuePrefix + key;
|
||||||
final String identityValue = properties.getProperty(identityValueProperty);
|
final String identityValue = properties.getProperty(identityValueProperty);
|
||||||
|
|
||||||
if (StringUtils.isBlank(identityValue)) {
|
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});
|
new Object[] {getSubject.get(), propertyName, identityValueProperty});
|
||||||
continue;
|
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 = 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);
|
mappings.add(identityMapping);
|
||||||
|
|
||||||
LOGGER.debug("Found Identity Mapping with key = {}, pattern = {}, value = {}",
|
LOGGER.debug("Found {} Mapping with key = {}, pattern = {}, value = {}, transform = {}",
|
||||||
new Object[] {key, identityPattern, identityValue});
|
new Object[] {getSubject.get(), key, identityPattern, identityValue, rawIdentityTransform});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +147,15 @@ public class IdentityMappingUtil {
|
||||||
if (m.matches()) {
|
if (m.matches()) {
|
||||||
final String pattern = mapping.getPattern().pattern();
|
final String pattern = mapping.getPattern().pattern();
|
||||||
final String replacementValue = escapeLiteralBackReferences(mapping.getReplacementValue(), m.groupCount());
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3406,13 +3406,27 @@ The following examples demonstrate normalizing DNs from certificates and princip
|
||||||
----
|
----
|
||||||
nifi.security.identity.mapping.pattern.dn=^CN=(.*?), OU=(.*?), O=(.*?), L=(.*?), ST=(.*?), C=(.*?)$
|
nifi.security.identity.mapping.pattern.dn=^CN=(.*?), OU=(.*?), O=(.*?), L=(.*?), ST=(.*?), C=(.*?)$
|
||||||
nifi.security.identity.mapping.value.dn=$1@$2
|
nifi.security.identity.mapping.value.dn=$1@$2
|
||||||
|
nifi.security.identity.mapping.transform.dn=NONE
|
||||||
nifi.security.identity.mapping.pattern.kerb=^(.*?)/instance@(.*?)$
|
nifi.security.identity.mapping.pattern.kerb=^(.*?)/instance@(.*?)$
|
||||||
nifi.security.identity.mapping.value.kerb=$1@$2
|
nifi.security.identity.mapping.value.kerb=$1@$2
|
||||||
|
nifi.security.identity.mapping.transform.kerb=NONE
|
||||||
----
|
----
|
||||||
|
|
||||||
The last segment of each property is an identifier used to associate the pattern with the replacement value. When a user makes a request to NiFi, their identity is checked to see if it matches each of those patterns in lexicographical order. For the first one that matches, the replacement specified in the `nifi.security.identity.mapping.value.xxxx` property is used. So a login with `CN=localhost, OU=Apache NiFi, O=Apache, L=Santa Monica, ST=CA, C=US` matches the DN mapping pattern above and the DN mapping value `$1@$2` is applied. The user is normalized to `localhost@Apache NiFi`.
|
The last segment of each property is an identifier used to associate the pattern with the replacement value. When a user makes a request to NiFi, their identity is checked to see if it matches each of those patterns in lexicographical order. For the first one that matches, the replacement specified in the `nifi.security.identity.mapping.value.xxxx` property is used. So a login with `CN=localhost, OU=Apache NiFi, O=Apache, L=Santa Monica, ST=CA, C=US` matches the DN mapping pattern above and the DN mapping value `$1@$2` is applied. The user is normalized to `localhost@Apache NiFi`.
|
||||||
|
|
||||||
NOTE: These mappings are also applied to the "Initial Admin Identity" and "Cluster Node Identity" properties in the authorizers.xml file (See <<authorizers-setup>>).
|
In addition to mapping a transform may be applied. The supported versions are NONE (no transform applied), LOWER (identity lowercased), and UPPER (identity uppercased). If not specified, the default value is NONE.
|
||||||
|
|
||||||
|
NOTE: These mappings are also applied to the "Initial Admin Identity", "Cluster Node Identity", and any legacy users in the authorizers.xml file as well as users imported from LDAP (See <<authorizers-setup>>).
|
||||||
|
|
||||||
|
Group names can also be mapped. The following example will accept the existing group name but will lowercase it. This may be helpful when used in conjunction with an external authorizer.
|
||||||
|
|
||||||
|
----
|
||||||
|
nifi.security.group.mapping.pattern.anygroup=^(.*)$
|
||||||
|
nifi.security.group.mapping.value.anygroup=$1
|
||||||
|
nifi.security.group.mapping.transform.anygroup=LOWER
|
||||||
|
----
|
||||||
|
|
||||||
|
NOTE: These mappings are applied to any legacy groups referenced in the authorizers.xml as well as groups imported from LDAP.
|
||||||
|
|
||||||
=== Cluster Common Properties
|
=== Cluster Common Properties
|
||||||
|
|
||||||
|
|
|
@ -16,39 +16,6 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.authorization;
|
package org.apache.nifi.authorization;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import javax.xml.XMLConstants;
|
|
||||||
import javax.xml.bind.JAXBContext;
|
|
||||||
import javax.xml.bind.JAXBElement;
|
|
||||||
import javax.xml.bind.JAXBException;
|
|
||||||
import javax.xml.bind.Marshaller;
|
|
||||||
import javax.xml.bind.Unmarshaller;
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
|
||||||
import javax.xml.stream.XMLOutputFactory;
|
|
||||||
import javax.xml.stream.XMLStreamException;
|
|
||||||
import javax.xml.stream.XMLStreamReader;
|
|
||||||
import javax.xml.stream.XMLStreamWriter;
|
|
||||||
import javax.xml.transform.stream.StreamSource;
|
|
||||||
import javax.xml.validation.Schema;
|
|
||||||
import javax.xml.validation.SchemaFactory;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.nifi.authorization.annotation.AuthorizerContext;
|
import org.apache.nifi.authorization.annotation.AuthorizerContext;
|
||||||
import org.apache.nifi.authorization.exception.AuthorizationAccessException;
|
import org.apache.nifi.authorization.exception.AuthorizationAccessException;
|
||||||
|
@ -76,6 +43,40 @@ import org.w3c.dom.Node;
|
||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.NodeList;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
import javax.xml.XMLConstants;
|
||||||
|
import javax.xml.bind.JAXBContext;
|
||||||
|
import javax.xml.bind.JAXBElement;
|
||||||
|
import javax.xml.bind.JAXBException;
|
||||||
|
import javax.xml.bind.Marshaller;
|
||||||
|
import javax.xml.bind.Unmarshaller;
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import javax.xml.stream.XMLOutputFactory;
|
||||||
|
import javax.xml.stream.XMLStreamException;
|
||||||
|
import javax.xml.stream.XMLStreamReader;
|
||||||
|
import javax.xml.stream.XMLStreamWriter;
|
||||||
|
import javax.xml.transform.stream.StreamSource;
|
||||||
|
import javax.xml.validation.Schema;
|
||||||
|
import javax.xml.validation.SchemaFactory;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class FileAccessPolicyProvider implements ConfigurableAccessPolicyProvider {
|
public class FileAccessPolicyProvider implements ConfigurableAccessPolicyProvider {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(FileAccessPolicyProvider.class);
|
private static final Logger logger = LoggerFactory.getLogger(FileAccessPolicyProvider.class);
|
||||||
|
@ -130,6 +131,7 @@ public class FileAccessPolicyProvider implements ConfigurableAccessPolicyProvide
|
||||||
private Set<String> nodeIdentities;
|
private Set<String> nodeIdentities;
|
||||||
private List<PortDTO> ports = new ArrayList<>();
|
private List<PortDTO> ports = new ArrayList<>();
|
||||||
private List<IdentityMapping> identityMappings;
|
private List<IdentityMapping> identityMappings;
|
||||||
|
private List<IdentityMapping> groupMappings;
|
||||||
|
|
||||||
private UserGroupProvider userGroupProvider;
|
private UserGroupProvider userGroupProvider;
|
||||||
private UserGroupProviderLookup userGroupProviderLookup;
|
private UserGroupProviderLookup userGroupProviderLookup;
|
||||||
|
@ -200,6 +202,7 @@ public class FileAccessPolicyProvider implements ConfigurableAccessPolicyProvide
|
||||||
|
|
||||||
// extract the identity mappings from nifi.properties if any are provided
|
// extract the identity mappings from nifi.properties if any are provided
|
||||||
identityMappings = Collections.unmodifiableList(IdentityMappingUtil.getIdentityMappings(properties));
|
identityMappings = Collections.unmodifiableList(IdentityMappingUtil.getIdentityMappings(properties));
|
||||||
|
groupMappings = Collections.unmodifiableList(IdentityMappingUtil.getGroupMappings(properties));
|
||||||
|
|
||||||
// get the value of the initial admin identity
|
// get the value of the initial admin identity
|
||||||
final PropertyValue initialAdminIdentityProp = configurationContext.getProperty(PROP_INITIAL_ADMIN_IDENTITY);
|
final PropertyValue initialAdminIdentityProp = configurationContext.getProperty(PROP_INITIAL_ADMIN_IDENTITY);
|
||||||
|
@ -728,10 +731,12 @@ public class FileAccessPolicyProvider implements ConfigurableAccessPolicyProvide
|
||||||
|
|
||||||
if (portDTO.getGroupAccessControl() != null) {
|
if (portDTO.getGroupAccessControl() != null) {
|
||||||
for (String groupAccessControl : portDTO.getGroupAccessControl()) {
|
for (String groupAccessControl : portDTO.getGroupAccessControl()) {
|
||||||
|
final String legacyGroupName = IdentityMappingUtil.mapIdentity(groupAccessControl, groupMappings);
|
||||||
|
|
||||||
// find a group where the name is the groupAccessControl
|
// find a group where the name is the groupAccessControl
|
||||||
Group foundGroup = null;
|
Group foundGroup = null;
|
||||||
for (Group group : userGroupProvider.getGroups()) {
|
for (Group group : userGroupProvider.getGroups()) {
|
||||||
if (group.getName().equals(groupAccessControl)) {
|
if (group.getName().equals(legacyGroupName)) {
|
||||||
foundGroup = group;
|
foundGroup = group;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -740,7 +745,7 @@ public class FileAccessPolicyProvider implements ConfigurableAccessPolicyProvide
|
||||||
// couldn't find the group matching the access control so log a warning and skip
|
// couldn't find the group matching the access control so log a warning and skip
|
||||||
if (foundGroup == null) {
|
if (foundGroup == null) {
|
||||||
logger.warn("Found port with group access control for {} but no group exists with this name, skipping...",
|
logger.warn("Found port with group access control for {} but no group exists with this name, skipping...",
|
||||||
new Object[] {groupAccessControl});
|
new Object[] {legacyGroupName});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -751,7 +756,7 @@ public class FileAccessPolicyProvider implements ConfigurableAccessPolicyProvide
|
||||||
resource.getIdentifier(),
|
resource.getIdentifier(),
|
||||||
WRITE_CODE);
|
WRITE_CODE);
|
||||||
|
|
||||||
addGroupToPolicy(IdentifierUtil.getIdentifier(groupAccessControl), policy);
|
addGroupToPolicy(IdentifierUtil.getIdentifier(legacyGroupName), policy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,39 +16,6 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.nifi.authorization;
|
package org.apache.nifi.authorization;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import javax.xml.XMLConstants;
|
|
||||||
import javax.xml.bind.JAXBContext;
|
|
||||||
import javax.xml.bind.JAXBElement;
|
|
||||||
import javax.xml.bind.JAXBException;
|
|
||||||
import javax.xml.bind.Marshaller;
|
|
||||||
import javax.xml.bind.Unmarshaller;
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
|
||||||
import javax.xml.stream.XMLOutputFactory;
|
|
||||||
import javax.xml.stream.XMLStreamException;
|
|
||||||
import javax.xml.stream.XMLStreamReader;
|
|
||||||
import javax.xml.stream.XMLStreamWriter;
|
|
||||||
import javax.xml.transform.stream.StreamSource;
|
|
||||||
import javax.xml.validation.Schema;
|
|
||||||
import javax.xml.validation.SchemaFactory;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.nifi.authorization.annotation.AuthorizerContext;
|
import org.apache.nifi.authorization.annotation.AuthorizerContext;
|
||||||
import org.apache.nifi.authorization.exception.AuthorizationAccessException;
|
import org.apache.nifi.authorization.exception.AuthorizationAccessException;
|
||||||
|
@ -72,6 +39,40 @@ import org.w3c.dom.Node;
|
||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.NodeList;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
import javax.xml.XMLConstants;
|
||||||
|
import javax.xml.bind.JAXBContext;
|
||||||
|
import javax.xml.bind.JAXBElement;
|
||||||
|
import javax.xml.bind.JAXBException;
|
||||||
|
import javax.xml.bind.Marshaller;
|
||||||
|
import javax.xml.bind.Unmarshaller;
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import javax.xml.stream.XMLOutputFactory;
|
||||||
|
import javax.xml.stream.XMLStreamException;
|
||||||
|
import javax.xml.stream.XMLStreamReader;
|
||||||
|
import javax.xml.stream.XMLStreamWriter;
|
||||||
|
import javax.xml.transform.stream.StreamSource;
|
||||||
|
import javax.xml.validation.Schema;
|
||||||
|
import javax.xml.validation.SchemaFactory;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class FileUserGroupProvider implements ConfigurableUserGroupProvider {
|
public class FileUserGroupProvider implements ConfigurableUserGroupProvider {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(FileUserGroupProvider.class);
|
private static final Logger logger = LoggerFactory.getLogger(FileUserGroupProvider.class);
|
||||||
|
@ -118,6 +119,7 @@ public class FileUserGroupProvider implements ConfigurableUserGroupProvider {
|
||||||
private String legacyAuthorizedUsersFile;
|
private String legacyAuthorizedUsersFile;
|
||||||
private Set<String> initialUserIdentities;
|
private Set<String> initialUserIdentities;
|
||||||
private List<IdentityMapping> identityMappings;
|
private List<IdentityMapping> identityMappings;
|
||||||
|
private List<IdentityMapping> groupMappings;
|
||||||
|
|
||||||
private final AtomicReference<UserGroupHolder> userGroupHolder = new AtomicReference<>();
|
private final AtomicReference<UserGroupHolder> userGroupHolder = new AtomicReference<>();
|
||||||
|
|
||||||
|
@ -172,8 +174,9 @@ public class FileUserGroupProvider implements ConfigurableUserGroupProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract the identity mappings from nifi.properties if any are provided
|
// extract the identity and group mappings from nifi.properties if any are provided
|
||||||
identityMappings = Collections.unmodifiableList(IdentityMappingUtil.getIdentityMappings(properties));
|
identityMappings = Collections.unmodifiableList(IdentityMappingUtil.getIdentityMappings(properties));
|
||||||
|
groupMappings = Collections.unmodifiableList(IdentityMappingUtil.getGroupMappings(properties));
|
||||||
|
|
||||||
// get the value of the legacy authorized users file
|
// get the value of the legacy authorized users file
|
||||||
final PropertyValue legacyAuthorizedUsersProp = configurationContext.getProperty(FileAuthorizer.PROP_LEGACY_AUTHORIZED_USERS_FILE);
|
final PropertyValue legacyAuthorizedUsersProp = configurationContext.getProperty(FileAuthorizer.PROP_LEGACY_AUTHORIZED_USERS_FILE);
|
||||||
|
@ -697,8 +700,9 @@ public class FileUserGroupProvider implements ConfigurableUserGroupProvider {
|
||||||
org.apache.nifi.authorization.file.tenants.generated.User user = getOrCreateUser(tenants, legacyUserDn);
|
org.apache.nifi.authorization.file.tenants.generated.User user = getOrCreateUser(tenants, legacyUserDn);
|
||||||
|
|
||||||
// if there was a group name find or create the group and add the user to it
|
// if there was a group name find or create the group and add the user to it
|
||||||
org.apache.nifi.authorization.file.tenants.generated.Group group = getOrCreateGroup(tenants, legacyUser.getGroup());
|
if (StringUtils.isNotBlank(legacyUser.getGroup())) {
|
||||||
if (group != null) {
|
final String legacyGroupName = IdentityMappingUtil.mapIdentity(legacyUser.getGroup(), groupMappings);
|
||||||
|
org.apache.nifi.authorization.file.tenants.generated.Group group = getOrCreateGroup(tenants, legacyGroupName);
|
||||||
org.apache.nifi.authorization.file.tenants.generated.Group.User groupUser = new org.apache.nifi.authorization.file.tenants.generated.Group.User();
|
org.apache.nifi.authorization.file.tenants.generated.Group.User groupUser = new org.apache.nifi.authorization.file.tenants.generated.Group.User();
|
||||||
groupUser.setIdentifier(user.getIdentifier());
|
groupUser.setIdentifier(user.getIdentifier());
|
||||||
group.getUser().add(groupUser);
|
group.getUser().add(groupUser);
|
||||||
|
|
|
@ -435,6 +435,10 @@ public class FileAuthorizerTest {
|
||||||
props.setProperty("nifi.security.identity.mapping.pattern.dn1", "^CN=(.*?), OU=(.*?), O=(.*?), L=(.*?), ST=(.*?), C=(.*?)$");
|
props.setProperty("nifi.security.identity.mapping.pattern.dn1", "^CN=(.*?), OU=(.*?), O=(.*?), L=(.*?), ST=(.*?), C=(.*?)$");
|
||||||
props.setProperty("nifi.security.identity.mapping.value.dn1", "$1");
|
props.setProperty("nifi.security.identity.mapping.value.dn1", "$1");
|
||||||
|
|
||||||
|
props.setProperty("nifi.security.group.mapping.pattern.anygroup", "^(.*)$");
|
||||||
|
props.setProperty("nifi.security.group.mapping.value.anygroup", "$1");
|
||||||
|
props.setProperty("nifi.security.group.mapping.transform.anygroup", "UPPER");
|
||||||
|
|
||||||
properties = getNiFiProperties(props);
|
properties = getNiFiProperties(props);
|
||||||
when(properties.getRestoreDirectory()).thenReturn(restoreAuthorizations.getParentFile());
|
when(properties.getRestoreDirectory()).thenReturn(restoreAuthorizations.getParentFile());
|
||||||
when(properties.getFlowConfigurationFile()).thenReturn(flowWithDns);
|
when(properties.getFlowConfigurationFile()).thenReturn(flowWithDns);
|
||||||
|
@ -469,7 +473,7 @@ public class FileAuthorizerTest {
|
||||||
final Set<Group> groups = authorizer.getGroups();
|
final Set<Group> groups = authorizer.getGroups();
|
||||||
assertEquals(1, groups.size());
|
assertEquals(1, groups.size());
|
||||||
final Group group1 = groups.iterator().next();
|
final Group group1 = groups.iterator().next();
|
||||||
assertEquals("group1", group1.getName());
|
assertEquals("GROUP1", group1.getName());
|
||||||
|
|
||||||
final Resource inputPortResource = ResourceFactory.getDataTransferResource(
|
final Resource inputPortResource = ResourceFactory.getDataTransferResource(
|
||||||
ResourceFactory.getComponentResource(ResourceType.InputPort, "2f7d1606-b090-4be7-a592-a5b70fb55531", "TCP Input"));
|
ResourceFactory.getComponentResource(ResourceType.InputPort, "2f7d1606-b090-4be7-a592-a5b70fb55531", "TCP Input"));
|
||||||
|
|
|
@ -227,6 +227,52 @@ public class FileUserGroupProviderTest {
|
||||||
assertEquals("group1", group1.getName());
|
assertEquals("group1", group1.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnConfiguredWhenLegacyUsersFileProvidedWithIdentityMappingsAndTransforms() throws Exception {
|
||||||
|
final Properties props = new Properties();
|
||||||
|
props.setProperty("nifi.security.identity.mapping.pattern.dn1", "^CN=(.*?), OU=(.*?), O=(.*?), L=(.*?), ST=(.*?), C=(.*?)$");
|
||||||
|
props.setProperty("nifi.security.identity.mapping.value.dn1", "$1");
|
||||||
|
props.setProperty("nifi.security.identity.mapping.transform.dn1", "UPPER");
|
||||||
|
|
||||||
|
props.setProperty("nifi.security.group.mapping.pattern.anygroup", "^(.*)$");
|
||||||
|
props.setProperty("nifi.security.group.mapping.value.anygroup", "$1");
|
||||||
|
props.setProperty("nifi.security.group.mapping.transform.anygroup", "UPPER");
|
||||||
|
|
||||||
|
properties = getNiFiProperties(props);
|
||||||
|
when(properties.getRestoreDirectory()).thenReturn(restoreTenants.getParentFile());
|
||||||
|
userGroupProvider.setNiFiProperties(properties);
|
||||||
|
|
||||||
|
when(configurationContext.getProperty(eq(FileAuthorizer.PROP_LEGACY_AUTHORIZED_USERS_FILE)))
|
||||||
|
.thenReturn(new StandardPropertyValue("src/test/resources/authorized-users-with-dns.xml", null));
|
||||||
|
|
||||||
|
writeFile(primaryTenants, EMPTY_TENANTS_CONCISE);
|
||||||
|
userGroupProvider.onConfigured(configurationContext);
|
||||||
|
|
||||||
|
final User user1 = userGroupProvider.getUserByIdentity("USER1");
|
||||||
|
assertNotNull(user1);
|
||||||
|
|
||||||
|
final User user2 = userGroupProvider.getUserByIdentity("USER2");
|
||||||
|
assertNotNull(user2);
|
||||||
|
|
||||||
|
final User user3 = userGroupProvider.getUserByIdentity("USER3");
|
||||||
|
assertNotNull(user3);
|
||||||
|
|
||||||
|
final User user4 = userGroupProvider.getUserByIdentity("USER4");
|
||||||
|
assertNotNull(user4);
|
||||||
|
|
||||||
|
final User user5 = userGroupProvider.getUserByIdentity("USER5");
|
||||||
|
assertNotNull(user5);
|
||||||
|
|
||||||
|
final User user6 = userGroupProvider.getUserByIdentity("USER6");
|
||||||
|
assertNotNull(user6);
|
||||||
|
|
||||||
|
// verify one group got created
|
||||||
|
final Set<Group> groups = userGroupProvider.getGroups();
|
||||||
|
assertEquals(1, groups.size());
|
||||||
|
final Group group1 = groups.iterator().next();
|
||||||
|
assertEquals("GROUP1", group1.getName());
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = AuthorizerCreationException.class)
|
@Test(expected = AuthorizerCreationException.class)
|
||||||
public void testOnConfiguredWhenBadLegacyUsersFileProvided() throws Exception {
|
public void testOnConfiguredWhenBadLegacyUsersFileProvided() throws Exception {
|
||||||
when(configurationContext.getProperty(eq(FileAuthorizer.PROP_LEGACY_AUTHORIZED_USERS_FILE)))
|
when(configurationContext.getProperty(eq(FileAuthorizer.PROP_LEGACY_AUTHORIZED_USERS_FILE)))
|
||||||
|
|
|
@ -186,8 +186,18 @@ nifi.security.user.knox.audiences=${nifi.security.user.knox.audiences}
|
||||||
#
|
#
|
||||||
# nifi.security.identity.mapping.pattern.dn=^CN=(.*?), OU=(.*?), O=(.*?), L=(.*?), ST=(.*?), C=(.*?)$
|
# nifi.security.identity.mapping.pattern.dn=^CN=(.*?), OU=(.*?), O=(.*?), L=(.*?), ST=(.*?), C=(.*?)$
|
||||||
# nifi.security.identity.mapping.value.dn=$1@$2
|
# nifi.security.identity.mapping.value.dn=$1@$2
|
||||||
|
# nifi.security.identity.mapping.transform.dn=NONE
|
||||||
# nifi.security.identity.mapping.pattern.kerb=^(.*?)/instance@(.*?)$
|
# nifi.security.identity.mapping.pattern.kerb=^(.*?)/instance@(.*?)$
|
||||||
# nifi.security.identity.mapping.value.kerb=$1@$2
|
# nifi.security.identity.mapping.value.kerb=$1@$2
|
||||||
|
# nifi.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.security.group.mapping.pattern.anygroup=^(.*)$
|
||||||
|
# nifi.security.group.mapping.value.anygroup=$1
|
||||||
|
# nifi.security.group.mapping.transform.anygroup=LOWER
|
||||||
|
|
||||||
# cluster common properties (all nodes must have same values) #
|
# cluster common properties (all nodes must have same values) #
|
||||||
nifi.cluster.protocol.heartbeat.interval=${nifi.cluster.protocol.heartbeat.interval}
|
nifi.cluster.protocol.heartbeat.interval=${nifi.cluster.protocol.heartbeat.interval}
|
||||||
|
|
|
@ -47,6 +47,8 @@ public class TestStandardRootGroupPort {
|
||||||
final AuthorizationRequest request = invocation.getArgumentAt(0, AuthorizationRequest.class);
|
final AuthorizationRequest request = invocation.getArgumentAt(0, AuthorizationRequest.class);
|
||||||
if ("node1@nifi.test".equals(request.getIdentity())) {
|
if ("node1@nifi.test".equals(request.getIdentity())) {
|
||||||
return AuthorizationResult.approved();
|
return AuthorizationResult.approved();
|
||||||
|
} else if ("NODE1@NIFI.TEST".equals(request.getIdentity())) {
|
||||||
|
return AuthorizationResult.approved();
|
||||||
}
|
}
|
||||||
return AuthorizationResult.denied();
|
return AuthorizationResult.denied();
|
||||||
}).when(authorizer).authorize(any(AuthorizationRequest.class));
|
}).when(authorizer).authorize(any(AuthorizationRequest.class));
|
||||||
|
@ -97,4 +99,31 @@ public class TestStandardRootGroupPort {
|
||||||
Assert.assertTrue(authResult.isAuthorized());
|
Assert.assertTrue(authResult.isAuthorized());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCheckUserAuthorizationByMappedDnWithTransformation() {
|
||||||
|
|
||||||
|
final NiFiProperties nifiProperties = mock(NiFiProperties.class);
|
||||||
|
final String mapKey = ".dn";
|
||||||
|
Set<String> propertyKeys = new LinkedHashSet<>();
|
||||||
|
propertyKeys.add(NiFiProperties.SECURITY_IDENTITY_MAPPING_PATTERN_PREFIX + mapKey);
|
||||||
|
propertyKeys.add(NiFiProperties.SECURITY_IDENTITY_MAPPING_VALUE_PREFIX + mapKey);
|
||||||
|
propertyKeys.add(NiFiProperties.SECURITY_IDENTITY_MAPPING_TRANSFORM_PREFIX + mapKey);
|
||||||
|
doReturn(propertyKeys).when(nifiProperties).getPropertyKeys();
|
||||||
|
|
||||||
|
final String mapPattern = "^CN=(.*?), OU=(.*?)$";
|
||||||
|
final String mapValue = "$1@$2";
|
||||||
|
final String mapTransform = "UPPER";
|
||||||
|
doReturn(mapPattern).when(nifiProperties).getProperty(eq(NiFiProperties.SECURITY_IDENTITY_MAPPING_PATTERN_PREFIX + mapKey));
|
||||||
|
doReturn(mapValue).when(nifiProperties).getProperty(eq(NiFiProperties.SECURITY_IDENTITY_MAPPING_VALUE_PREFIX + mapKey));
|
||||||
|
doReturn(mapTransform).when(nifiProperties).getProperty(eq(NiFiProperties.SECURITY_IDENTITY_MAPPING_TRANSFORM_PREFIX + mapKey));
|
||||||
|
|
||||||
|
final RootGroupPort port = createRootGroupPort(nifiProperties);
|
||||||
|
|
||||||
|
PortAuthorizationResult authResult = port.checkUserAuthorization("CN=node2, OU=nifi.test");
|
||||||
|
Assert.assertFalse(authResult.isAuthorized());
|
||||||
|
|
||||||
|
authResult = port.checkUserAuthorization("CN=node1, OU=nifi.test");
|
||||||
|
Assert.assertTrue(authResult.isAuthorized());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,6 +117,7 @@ public class LdapUserGroupProvider implements UserGroupProvider {
|
||||||
private static final long MINIMUM_SYNC_INTERVAL_MILLISECONDS = 10_000;
|
private static final long MINIMUM_SYNC_INTERVAL_MILLISECONDS = 10_000;
|
||||||
|
|
||||||
private List<IdentityMapping> identityMappings;
|
private List<IdentityMapping> identityMappings;
|
||||||
|
private List<IdentityMapping> groupMappings;
|
||||||
private NiFiProperties properties;
|
private NiFiProperties properties;
|
||||||
|
|
||||||
private ScheduledExecutorService ldapSync;
|
private ScheduledExecutorService ldapSync;
|
||||||
|
@ -350,6 +351,7 @@ public class LdapUserGroupProvider implements UserGroupProvider {
|
||||||
|
|
||||||
// extract the identity mappings from nifi.properties if any are provided
|
// extract the identity mappings from nifi.properties if any are provided
|
||||||
identityMappings = Collections.unmodifiableList(IdentityMappingUtil.getIdentityMappings(properties));
|
identityMappings = Collections.unmodifiableList(IdentityMappingUtil.getIdentityMappings(properties));
|
||||||
|
groupMappings = Collections.unmodifiableList(IdentityMappingUtil.getGroupMappings(properties));
|
||||||
|
|
||||||
// set the base environment is necessary
|
// set the base environment is necessary
|
||||||
if (!baseEnvironment.isEmpty()) {
|
if (!baseEnvironment.isEmpty()) {
|
||||||
|
@ -708,7 +710,7 @@ public class LdapUserGroupProvider implements UserGroupProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return name;
|
return IdentityMappingUtil.mapIdentity(name, groupMappings);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getReferencedGroupValue(final DirContextOperations ctx) {
|
private String getReferencedGroupValue(final DirContextOperations ctx) {
|
||||||
|
|
|
@ -507,6 +507,49 @@ public class LdapUserGroupProviderTest extends AbstractLdapTestUnit {
|
||||||
assertNotNull(ldapUserGroupProvider.getUserByIdentity("User 1,ou=users"));
|
assertNotNull(ldapUserGroupProvider.getUserByIdentity("User 1,ou=users"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUserIdentityMappingWithTransforms() throws Exception {
|
||||||
|
final Properties props = new Properties();
|
||||||
|
props.setProperty("nifi.security.identity.mapping.pattern.dn1", "^cn=(.*?),ou=(.*?),o=(.*?)$");
|
||||||
|
props.setProperty("nifi.security.identity.mapping.value.dn1", "$1");
|
||||||
|
props.setProperty("nifi.security.identity.mapping.transform.dn1", "UPPER");
|
||||||
|
|
||||||
|
final NiFiProperties 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)", null));
|
||||||
|
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.security.identity.mapping.pattern.dn1", "^cn=(.*?),ou=(.*?),o=(.*?)$");
|
||||||
|
props.setProperty("nifi.security.identity.mapping.value.dn1", "$1");
|
||||||
|
props.setProperty("nifi.security.identity.mapping.transform.dn1", "UPPER");
|
||||||
|
props.setProperty("nifi.security.group.mapping.pattern.dn1", "^cn=(.*?),ou=(.*?),o=(.*?)$");
|
||||||
|
props.setProperty("nifi.security.group.mapping.value.dn1", "$1");
|
||||||
|
props.setProperty("nifi.security.group.mapping.transform.dn1", "UPPER");
|
||||||
|
|
||||||
|
final NiFiProperties 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)", null));
|
||||||
|
when(configurationContext.getProperty(PROP_GROUP_SEARCH_FILTER)).thenReturn(new StandardPropertyValue("(cn=admins)", null));
|
||||||
|
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 = AuthorizerCreationException.class)
|
@Test(expected = AuthorizerCreationException.class)
|
||||||
public void testReferencedGroupAttributeWithoutGroupSearchBase() throws Exception {
|
public void testReferencedGroupAttributeWithoutGroupSearchBase() throws Exception {
|
||||||
final AuthorizerConfigurationContext configurationContext = getBaseConfiguration("ou=users-2,o=nifi", null);
|
final AuthorizerConfigurationContext configurationContext = getBaseConfiguration("ou=users-2,o=nifi", null);
|
||||||
|
|
Loading…
Reference in New Issue