NIFI-5839:

- Introducing case insensitive group membership.
- Ensuring user identity and group name mapping is applied when the user identity or group name is inferred through group membership decisions.

This closes #3657.

Signed-off-by: Bryan Bende <bbende@apache.org>
This commit is contained in:
Matt Gilman 2019-08-16 17:23:26 -04:00 committed by Bryan Bende
parent e32689a602
commit 326bc91405
No known key found for this signature in database
GPG Key ID: A0DDA9ED50711C39
5 changed files with 156 additions and 26 deletions

View File

@ -433,6 +433,7 @@ The LdapUserGroupProvider has the following properties:
|`Read Timeout` | Duration of read timeout. (i.e. `10 secs`).
|`Url` | Space-separated list of URLs of the LDAP servers (i.e. `ldap://<hostname>:<port>`).
|`Page Size` | Sets the page size when retrieving users and groups. If not specified, no paging is performed.
|`Group Membership - Enforce Case Sensitivity` | Sets whether group membership decisions are case sensitive. When a user or group is inferred (by not specifying or user or group search base or user identity attribute or group name attribute) case sensitivity is enforced since the value to use for the user identity or group name would be ambiguous. Defaults to false.
|`Sync Interval` | Duration of time between syncing users and groups. (i.e. `30 mins`). Minimum allowable value is `10 secs`.
|`User Search Base` | Base DN for searching for users (i.e. `ou=users,o=nifi`). Required to search users.
|`User Object Class` | Object class for identifying users (i.e. `person`). Required if searching users.
@ -680,6 +681,7 @@ member: cn=User 2,ou=users,o=nifi
<property name="Url">ldap://localhost:10389</property>
<property name="Page Size"></property>
<property name="Sync Interval">30 mins</property>
<property name="Group Membership - Enforce Case Sensitivity">false</property>
<property name="User Search Base">ou=users,o=nifi</property>
<property name="User Object Class">person</property>
@ -768,6 +770,7 @@ memberUid: user2
<property name="Url">ldap://localhost:10389</property>
<property name="Page Size"></property>
<property name="Sync Interval">30 mins</property>
<property name="Group Membership - Enforce Case Sensitivity">false</property>
<property name="User Search Base">ou=Users,dc=local</property>
<property name="User Object Class">posixAccount</property>
@ -868,6 +871,7 @@ member: cn=User 2,ou=users,o=nifi
<property name="Url">ldap://localhost:10389</property>
<property name="Page Size"></property>
<property name="Sync Interval">30 mins</property>
<property name="Group Membership - Enforce Case Sensitivity">false</property>
<property name="User Search Base">ou=users,o=nifi</property>
<property name="User Object Class">person</property>
@ -2463,7 +2467,7 @@ There are currently three implementations of the FlowFile Repository, which are
|====
|*Property*|*Description*
|`nifi.flowfile.repository.implementation`|The FlowFile Repository implementation. The default value is `org.apache.nifi.controller.repository.WriteAheadFlowFileRepository`. The other current options are `org.apache.nifi.controller.repository.VolatileFlowFileRepository` and `org.apache.nifi.controller.repository.RocksDBFlowFileRepository`.
|`nifi.flowfile.repository.implementation`|The FlowFile Repository implementation. The default value is `org.apache.nifi.controller.repository.WriteAheadFlowFileRepository`. The other current options are `org.apache.nifi.controller.repository.VolatileFlowFileRepository` and `org.apache.nifi.controller.repository.RocksDBFlowFileRepository`.
|====
NOTE: Switching repository implementations should only be done on an instance with zero queued FlowFiles, and should only be done with caution.

View File

@ -87,6 +87,9 @@
'Url' - Space-separated list of URLs of the LDAP servers (i.e. ldap://<hostname>:<port>).
'Page Size' - Sets the page size when retrieving users and groups. If not specified, no paging is performed.
'Sync Interval' - Duration of time between syncing users and groups (i.e. 30 mins). Minimum allowable value is 10 secs.
'Group Membership - Enforce Case Sensitivity' - Sets whether group membership decisions are case sensitive. When a user or group
is inferred (by not specifying or user or group search base or user identity attribute or group name attribute) case sensitivity
is enforced since the value to use for the user identity or group name would be ambiguous. Defaults to false.
'User Search Base' - Base DN for searching for users (i.e. ou=users,o=nifi). Required to search users.
'User Object Class' - Object class for identifying users (i.e. person). Required if searching users.
@ -147,6 +150,7 @@
<property name="Url"></property>
<property name="Page Size"></property>
<property name="Sync Interval">30 mins</property>
<property name="Group Membership - Enforce Case Sensitivity">false</property>
<property name="User Search Base"></property>
<property name="User Object Class">person</property>

View File

@ -96,6 +96,7 @@ public class LdapUserGroupProvider implements UserGroupProvider {
public static final String PROP_REFERRAL_STRATEGY = "Referral Strategy";
public static final String PROP_URL = "Url";
public static final String PROP_PAGE_SIZE = "Page Size";
public static final String PROP_GROUP_MEMBERSHIP_ENFORCE_CASE_SENSITIVITY = "Group Membership - Enforce Case Sensitivity";
public static final String PROP_USER_SEARCH_BASE = "User Search Base";
public static final String PROP_USER_OBJECT_CLASS = "User Object Class";
@ -145,6 +146,8 @@ public class LdapUserGroupProvider implements UserGroupProvider {
private Integer pageSize;
private boolean groupMembershipEnforceCaseSensitivity;
@Override
public void initialize(final UserGroupProviderInitializationContext initializationContext) throws AuthorizerCreationException {
ldapSync = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
@ -349,6 +352,10 @@ public class LdapUserGroupProvider implements UserGroupProvider {
pageSize = rawPageSize.asInteger();
}
// get whether group membership should be case sensitive
final String rawGroupMembershipEnforceCaseSensitivity = configurationContext.getProperty(PROP_GROUP_MEMBERSHIP_ENFORCE_CASE_SENSITIVITY).getValue();
groupMembershipEnforceCaseSensitivity = Boolean.parseBoolean(rawGroupMembershipEnforceCaseSensitivity);
// extract the identity mappings from nifi.properties if any are provided
identityMappings = Collections.unmodifiableList(IdentityMappingUtil.getIdentityMappings(properties));
groupMappings = Collections.unmodifiableList(IdentityMappingUtil.getGroupMappings(properties));
@ -512,8 +519,22 @@ public class LdapUserGroupProvider implements UserGroupProvider {
try {
final NamingEnumeration<String> groupValues = (NamingEnumeration<String>) attributeGroups.getAll();
while (groupValues.hasMoreElements()) {
// store the group -> user identifier mapping
groupToUserIdentifierMappings.computeIfAbsent(groupValues.next(), g -> new HashSet<>()).add(user.getIdentifier());
final String groupValue = groupValues.next();
// if we are performing a group search, then we need to normalize the group value so that each
// user associating with it can be matched. if we are not performing a group search then these
// values will be used to actually build the group itself. case sensitivity is for group
// membership, not group identification.
final String groupValueNormalized;
if (performGroupSearch) {
groupValueNormalized = groupMembershipEnforceCaseSensitivity ? groupValue : groupValue.toLowerCase();
} else {
groupValueNormalized = groupValue;
}
// store the group -> user identifier mapping... if case sensitivity is disabled, the group reference value will
// be lowercased when adding to groupToUserIdentifierMappings
groupToUserIdentifierMappings.computeIfAbsent(groupValueNormalized, g -> new HashSet<>()).add(user.getIdentifier());
}
} catch (NamingException e) {
throw new AuthorizationAccessException("Error while retrieving user group name attribute [" + userIdentityAttribute + "].");
@ -572,8 +593,11 @@ public class LdapUserGroupProvider implements UserGroupProvider {
final String userValue = userValues.next();
if (performUserSearch) {
// find the user by it's referenced attribute and add the identifier to this group
final User user = userLookup.get(userValue);
// find the user by it's referenced attribute and add the identifier to this group.
// need to normalize here based on the desired case sensitivity. if case sensitivity
// is disabled, the user reference value will be lowercased when adding to userLookup
final String userValueNormalized = groupMembershipEnforceCaseSensitivity ? userValue : userValue.toLowerCase();
final User user = userLookup.get(userValueNormalized);
// ensure the user is known
if (user != null) {
@ -583,13 +607,16 @@ public class LdapUserGroupProvider implements UserGroupProvider {
+ "to a misconfiguration or it's possible the user is not a NiFi user. Ignoring group membership.", name, userValue));
}
} else {
// since performUserSearch is false, then the referenced group attribute must be blank... the user value must be the dn
// since performUserSearch is false, then the referenced group attribute must be blank... the user value must be the dn.
// no need to normalize here since group membership is driven solely through this group (not through the userLookup
// populated above). we are either going to use this value directly as the user identity or we are going to query
// the directory server again which should handle the case sensitivity accordingly.
final String userDn = userValue;
final String userIdentity;
if (useDnForUserIdentity) {
// use the user value to avoid the unnecessary look up
userIdentity = userDn;
userIdentity = IdentityMappingUtil.mapIdentity(userDn, identityMappings);
} else {
// lookup the user to extract the user identity
userIdentity = getUserIdentity((DirContextAdapter) ldapTemplate.lookup(userDn));
@ -635,7 +662,7 @@ public class LdapUserGroupProvider implements UserGroupProvider {
final String groupName;
if (useDnForGroupName) {
// use the dn to avoid the unnecessary look up
groupName = groupDn;
groupName = IdentityMappingUtil.mapIdentity(groupDn, groupMappings);
} else {
groupName = getGroupName((DirContextAdapter) ldapTemplate.lookup(groupDn));
}
@ -711,7 +738,7 @@ public class LdapUserGroupProvider implements UserGroupProvider {
}
}
return referencedUserValue;
return groupMembershipEnforceCaseSensitivity ? referencedUserValue : referencedUserValue.toLowerCase();
}
private String getGroupName(final DirContextOperations ctx) {
@ -753,7 +780,7 @@ public class LdapUserGroupProvider implements UserGroupProvider {
}
}
return referencedGroupValue;
return groupMembershipEnforceCaseSensitivity ? referencedGroupValue : referencedGroupValue.toLowerCase();
}
@AuthorizerContext

View File

@ -43,6 +43,7 @@ import java.util.Set;
import static org.apache.nifi.ldap.tenants.LdapUserGroupProvider.PROP_AUTHENTICATION_STRATEGY;
import static org.apache.nifi.ldap.tenants.LdapUserGroupProvider.PROP_CONNECT_TIMEOUT;
import static org.apache.nifi.ldap.tenants.LdapUserGroupProvider.PROP_GROUP_MEMBERSHIP_ENFORCE_CASE_SENSITIVITY;
import static org.apache.nifi.ldap.tenants.LdapUserGroupProvider.PROP_GROUP_MEMBER_ATTRIBUTE;
import static org.apache.nifi.ldap.tenants.LdapUserGroupProvider.PROP_GROUP_MEMBER_REFERENCED_USER_ATTRIBUTE;
import static org.apache.nifi.ldap.tenants.LdapUserGroupProvider.PROP_GROUP_NAME_ATTRIBUTE;
@ -202,12 +203,22 @@ public class LdapUserGroupProviderTest extends AbstractLdapTestUnit {
ldapUserGroupProvider.onConfigured(configurationContext);
assertEquals(8, ldapUserGroupProvider.getUsers().size());
assertEquals(2, ldapUserGroupProvider.getGroups().size());
assertEquals(3, ldapUserGroupProvider.getGroups().size());
final UserAndGroups userAndGroups = ldapUserGroupProvider.getUserAndGroups("user4");
assertNotNull(userAndGroups.getUser());
assertEquals(1, userAndGroups.getGroups().size());
assertEquals("cn=team1,ou=groups,o=nifi", userAndGroups.getGroups().iterator().next().getName());
final UserAndGroups user4AndGroups = ldapUserGroupProvider.getUserAndGroups("user4");
assertNotNull(user4AndGroups.getUser());
assertEquals(1, user4AndGroups.getGroups().size());
assertEquals("cn=team1,ou=groups,o=nifi", user4AndGroups.getGroups().iterator().next().getName());
final UserAndGroups user7AndGroups = ldapUserGroupProvider.getUserAndGroups("user7");
assertNotNull(user7AndGroups.getUser());
assertEquals(1, user7AndGroups.getGroups().size());
assertEquals("cn=team2,ou=groups,o=nifi", user7AndGroups.getGroups().iterator().next().getName());
final UserAndGroups user8AndGroups = ldapUserGroupProvider.getUserAndGroups("user8");
assertNotNull(user8AndGroups.getUser());
assertEquals(1, user8AndGroups.getGroups().size());
assertEquals("cn=Team2,ou=groups,o=nifi", user8AndGroups.getGroups().iterator().next().getName());
}
@Test
@ -264,7 +275,7 @@ public class LdapUserGroupProviderTest extends AbstractLdapTestUnit {
ldapUserGroupProvider.onConfigured(configurationContext);
final Set<Group> groups = ldapUserGroupProvider.getGroups();
assertEquals(4, groups.size());
assertEquals(5, groups.size());
assertEquals(1, groups.stream().filter(group -> "cn=admins,ou=groups,o=nifi".equals(group.getName())).count());
}
@ -275,7 +286,7 @@ public class LdapUserGroupProviderTest extends AbstractLdapTestUnit {
when(configurationContext.getProperty(PROP_PAGE_SIZE)).thenReturn(new StandardPropertyValue("1", null, ParameterLookup.EMPTY));
ldapUserGroupProvider.onConfigured(configurationContext);
assertEquals(4, ldapUserGroupProvider.getGroups().size());
assertEquals(5, ldapUserGroupProvider.getGroups().size());
}
@Test
@ -296,7 +307,7 @@ public class LdapUserGroupProviderTest extends AbstractLdapTestUnit {
when(configurationContext.getProperty(PROP_GROUP_SEARCH_SCOPE)).thenReturn(new StandardPropertyValue(SearchScope.SUBTREE.name(), null, ParameterLookup.EMPTY));
ldapUserGroupProvider.onConfigured(configurationContext);
assertEquals(4, ldapUserGroupProvider.getGroups().size());
assertEquals(5, ldapUserGroupProvider.getGroups().size());
}
@Test
@ -307,7 +318,7 @@ public class LdapUserGroupProviderTest extends AbstractLdapTestUnit {
ldapUserGroupProvider.onConfigured(configurationContext);
final Set<Group> groups = ldapUserGroupProvider.getGroups();
assertEquals(4, groups.size());
assertEquals(5, groups.size());
final Group admins = groups.stream().filter(group -> "admins".equals(group.getName())).findFirst().orElse(null);
assertNotNull(admins);
@ -325,7 +336,7 @@ public class LdapUserGroupProviderTest extends AbstractLdapTestUnit {
ldapUserGroupProvider.onConfigured(configurationContext);
final Set<Group> groups = ldapUserGroupProvider.getGroups();
assertEquals(4, groups.size());
assertEquals(5, groups.size());
final Group admins = groups.stream().filter(group -> "cn=admins,ou=groups,o=nifi".equals(group.getName())).findFirst().orElse(null);
assertNotNull(admins);
@ -344,7 +355,7 @@ public class LdapUserGroupProviderTest extends AbstractLdapTestUnit {
ldapUserGroupProvider.onConfigured(configurationContext);
final Set<Group> groups = ldapUserGroupProvider.getGroups();
assertEquals(4, groups.size());
assertEquals(5, groups.size());
final Group admins = groups.stream().filter(group -> "admins".equals(group.getName())).findFirst().orElse(null);
assertNotNull(admins);
@ -374,7 +385,7 @@ public class LdapUserGroupProviderTest extends AbstractLdapTestUnit {
assertEquals(8, ldapUserGroupProvider.getUsers().size());
final Set<Group> groups = ldapUserGroupProvider.getGroups();
assertEquals(4, groups.size());
assertEquals(5, groups.size());
groups.forEach(group -> assertTrue(group.getUsers().isEmpty()));
}
@ -389,7 +400,7 @@ public class LdapUserGroupProviderTest extends AbstractLdapTestUnit {
assertEquals(8, ldapUserGroupProvider.getUsers().size());
final Set<Group> groups = ldapUserGroupProvider.getGroups();
assertEquals(4, groups.size());
assertEquals(5, groups.size());
final Group team1 = groups.stream().filter(group -> "team1".equals(group.getName())).findFirst().orElse(null);
assertNotNull(team1);
@ -417,7 +428,7 @@ public class LdapUserGroupProviderTest extends AbstractLdapTestUnit {
assertEquals(8, ldapUserGroupProvider.getUsers().size());
final Set<Group> groups = ldapUserGroupProvider.getGroups();
assertEquals(4, groups.size());
assertEquals(5, groups.size());
final Group admins = groups.stream().filter(group -> "admins".equals(group.getName())).findFirst().orElse(null);
assertNotNull(admins);
@ -460,7 +471,7 @@ public class LdapUserGroupProviderTest extends AbstractLdapTestUnit {
assertEquals(8, ldapUserGroupProvider.getUsers().size());
final Set<Group> groups = ldapUserGroupProvider.getGroups();
assertEquals(4, groups.size());
assertEquals(5, groups.size());
final Group admins = groups.stream().filter(group -> "admins".equals(group.getName())).findFirst().orElse(null);
assertNotNull(admins);
@ -643,6 +654,81 @@ public class LdapUserGroupProviderTest extends AbstractLdapTestUnit {
user -> "User9".equals(user.getIdentity())).count());
}
@Test
public void testSearchUsersAndGroupsMembershipThroughGroupsCaseInsensitive() throws Exception {
final AuthorizerConfigurationContext configurationContext = getBaseConfiguration(USER_SEARCH_BASE, GROUP_SEARCH_BASE);
when(configurationContext.getProperty(PROP_USER_IDENTITY_ATTRIBUTE)).thenReturn(new StandardPropertyValue("uid", null, ParameterLookup.EMPTY));
when(configurationContext.getProperty(PROP_GROUP_MEMBER_ATTRIBUTE)).thenReturn(new StandardPropertyValue("member", null, ParameterLookup.EMPTY));
when(configurationContext.getProperty(PROP_GROUP_NAME_ATTRIBUTE)).thenReturn(new StandardPropertyValue("cn", null, ParameterLookup.EMPTY));
when(configurationContext.getProperty(PROP_GROUP_MEMBERSHIP_ENFORCE_CASE_SENSITIVITY)).thenReturn(new StandardPropertyValue("false", null, ParameterLookup.EMPTY));
ldapUserGroupProvider.onConfigured(configurationContext);
assertEquals(8, ldapUserGroupProvider.getUsers().size());
final Set<Group> groups = ldapUserGroupProvider.getGroups();
assertEquals(5, groups.size());
final Group team4 = groups.stream().filter(group -> "team4".equals(group.getName())).findFirst().orElse(null);
assertNotNull(team4);
assertEquals(2, team4.getUsers().size());
assertEquals(1, team4.getUsers().stream().map(
userIdentifier -> ldapUserGroupProvider.getUser(userIdentifier)).filter(
user -> "user1".equals(user.getIdentity())).count());
assertEquals(1, team4.getUsers().stream().map(
userIdentifier -> ldapUserGroupProvider.getUser(userIdentifier)).filter(
user -> "user2".equals(user.getIdentity())).count());
}
@Test
public void testSearchUsersAndGroupsMembershipThroughGroupsCaseSensitive() throws Exception {
final AuthorizerConfigurationContext configurationContext = getBaseConfiguration(USER_SEARCH_BASE, GROUP_SEARCH_BASE);
when(configurationContext.getProperty(PROP_USER_IDENTITY_ATTRIBUTE)).thenReturn(new StandardPropertyValue("uid", null, ParameterLookup.EMPTY));
when(configurationContext.getProperty(PROP_GROUP_MEMBER_ATTRIBUTE)).thenReturn(new StandardPropertyValue("member", null, ParameterLookup.EMPTY));
when(configurationContext.getProperty(PROP_GROUP_NAME_ATTRIBUTE)).thenReturn(new StandardPropertyValue("cn", null, ParameterLookup.EMPTY));
ldapUserGroupProvider.onConfigured(configurationContext);
assertEquals(8, ldapUserGroupProvider.getUsers().size());
final Set<Group> groups = ldapUserGroupProvider.getGroups();
assertEquals(5, groups.size());
final Group team4 = groups.stream().filter(group -> "team4".equals(group.getName())).findFirst().orElse(null);
assertNotNull(team4);
assertEquals(1, team4.getUsers().size());
assertEquals(1, team4.getUsers().stream().map(
userIdentifier -> ldapUserGroupProvider.getUser(userIdentifier)).filter(
user -> "user1".equals(user.getIdentity())).count());
}
@Test
public void testSearchUsersAndGroupsMembershipThroughUsersCaseInsensitive() throws Exception {
final AuthorizerConfigurationContext configurationContext = getBaseConfiguration(USER_SEARCH_BASE, GROUP_SEARCH_BASE);
when(configurationContext.getProperty(PROP_USER_IDENTITY_ATTRIBUTE)).thenReturn(new StandardPropertyValue("uid", null, ParameterLookup.EMPTY));
when(configurationContext.getProperty(PROP_USER_GROUP_ATTRIBUTE)).thenReturn(new StandardPropertyValue("description", null, ParameterLookup.EMPTY)); // using description in lieu of memberof
when(configurationContext.getProperty(PROP_GROUP_NAME_ATTRIBUTE)).thenReturn(new StandardPropertyValue("cn", null, ParameterLookup.EMPTY));
when(configurationContext.getProperty(PROP_GROUP_MEMBERSHIP_ENFORCE_CASE_SENSITIVITY)).thenReturn(new StandardPropertyValue("false", null, ParameterLookup.EMPTY));
ldapUserGroupProvider.onConfigured(configurationContext);
assertEquals(8, ldapUserGroupProvider.getUsers().size());
final Set<Group> groups = ldapUserGroupProvider.getGroups();
assertEquals(5, groups.size());
final Group team1 = groups.stream().filter(group -> "team1".equals(group.getName())).findFirst().orElse(null);
assertNotNull(team1);
assertEquals(2, team1.getUsers().size());
assertEquals(2, team1.getUsers().stream().map(
userIdentifier -> ldapUserGroupProvider.getUser(userIdentifier)).filter(
user -> "user4".equals(user.getIdentity()) || "user5".equals(user.getIdentity())).count());
final Group team2 = groups.stream().filter(group -> "team2".equals(group.getName())).findFirst().orElse(null);
assertNotNull(team2);
assertEquals(3, team2.getUsers().size());
assertEquals(3, team2.getUsers().stream().map(
userIdentifier -> ldapUserGroupProvider.getUser(userIdentifier)).filter(
user -> "user6".equals(user.getIdentity()) || "user7".equals(user.getIdentity()) || "user8".equals(user.getIdentity())).count());
}
private AuthorizerConfigurationContext getBaseConfiguration(final String userSearchBase, final String groupSearchBase) {
final AuthorizerConfigurationContext configurationContext = mock(AuthorizerConfigurationContext.class);
when(configurationContext.getProperty(PROP_URL)).thenReturn(new StandardPropertyValue("ldap://127.0.0.1:" + getLdapServer().getPort(), null, ParameterLookup.EMPTY));
@ -651,6 +737,7 @@ public class LdapUserGroupProviderTest extends AbstractLdapTestUnit {
when(configurationContext.getProperty(PROP_REFERRAL_STRATEGY)).thenReturn(new StandardPropertyValue(ReferralStrategy.FOLLOW.name(), null, ParameterLookup.EMPTY));
when(configurationContext.getProperty(PROP_PAGE_SIZE)).thenReturn(new StandardPropertyValue(null, null, ParameterLookup.EMPTY));
when(configurationContext.getProperty(PROP_SYNC_INTERVAL)).thenReturn(new StandardPropertyValue("30 mins", null, ParameterLookup.EMPTY));
when(configurationContext.getProperty(PROP_GROUP_MEMBERSHIP_ENFORCE_CASE_SENSITIVITY)).thenReturn(new StandardPropertyValue("true", null, ParameterLookup.EMPTY));
when(configurationContext.getProperty(PROP_AUTHENTICATION_STRATEGY)).thenReturn(new StandardPropertyValue(LdapAuthenticationStrategy.SIMPLE.name(), null, ParameterLookup.EMPTY));
when(configurationContext.getProperty(PROP_MANAGER_DN)).thenReturn(new StandardPropertyValue("uid=admin,ou=system", null, ParameterLookup.EMPTY));
@ -681,4 +768,4 @@ public class LdapUserGroupProviderTest extends AbstractLdapTestUnit {
when(nifiProperties.getProperty(anyString())).then(invocationOnMock -> properties.getProperty((String) invocationOnMock.getArguments()[0]));
return nifiProperties;
}
}
}

View File

@ -110,6 +110,7 @@ objectClass: inetOrgPerson
objectClass: top
cn: User 8
sn: User8
description: cn=Team2,ou=groups,o=nifi
uid: user8
dn: cn=User 9,ou=users-2,o=nifi
@ -157,6 +158,13 @@ objectClass: top
cn: team2
member: cn=User 1,ou=users,o=nifi
dn: cn=team4,ou=groups,o=nifi
objectClass: groupOfNames
objectClass: top
cn: team4
member: cn=User 1,ou=users,o=nifi
member: cn=user 2,ou=users,o=nifi
## since the embedded ldap requires member to be fqdn, we are simulating using room and description
dn: cn=team3,ou=groups-2,o=nifi