KEYCLOAK-2053 Memberships based on memberUid like attribute
This commit is contained in:
parent
2b409b3462
commit
215d59b1e5
2 changed files with 67 additions and 16 deletions
|
@ -39,11 +39,14 @@ public class RoleLDAPFederationMapper extends AbstractLDAPFederationMapper {
|
|||
// Name of LDAP attribute, which is used in role objects for name and RDN of role. Usually it will be "cn"
|
||||
public static final String ROLE_NAME_LDAP_ATTRIBUTE = "role.name.ldap.attribute";
|
||||
|
||||
// Object classes of the role object.
|
||||
public static final String ROLE_OBJECT_CLASSES = "role.object.classes";
|
||||
|
||||
// Name of LDAP attribute on role, which is used for membership mappings. Usually it will be "member"
|
||||
public static final String MEMBERSHIP_LDAP_ATTRIBUTE = "membership.ldap.attribute";
|
||||
|
||||
// Object classes of the role object.
|
||||
public static final String ROLE_OBJECT_CLASSES = "role.object.classes";
|
||||
// See docs for MembershipType enum
|
||||
public static final String MEMBERSHIP_ATTRIBUTE_TYPE = "membership.attribute.type";
|
||||
|
||||
// Boolean option. If true, we will map LDAP roles to realm roles. If false, we will map to client roles (client specified by option CLIENT_ID)
|
||||
public static final String USE_REALM_ROLES_MAPPING = "use.realm.roles.mapping";
|
||||
|
@ -179,6 +182,15 @@ public class RoleLDAPFederationMapper extends AbstractLDAPFederationMapper {
|
|||
return membershipAttrName!=null ? membershipAttrName : LDAPConstants.MEMBER;
|
||||
}
|
||||
|
||||
protected MembershipType getMembershipTypeLdapAttribute(UserFederationMapperModel mapperModel) {
|
||||
String membershipType = mapperModel.getConfig().get(MEMBERSHIP_ATTRIBUTE_TYPE);
|
||||
return membershipType!=null ? Enum.valueOf(MembershipType.class, membershipType) : MembershipType.DN;
|
||||
}
|
||||
|
||||
private String getMembershipFromUser(LDAPObject ldapUser, MembershipType membershipType) {
|
||||
return membershipType == MembershipType.DN ? ldapUser.getDn().toString() : ldapUser.getAttributeAsString(ldapUser.getRdnAttributeName());
|
||||
}
|
||||
|
||||
protected Collection<String> getRoleObjectClasses(UserFederationMapperModel mapperModel, LDAPFederationProvider ldapProvider) {
|
||||
String objectClasses = mapperModel.getConfig().get(ROLE_OBJECT_CLASSES);
|
||||
if (objectClasses == null) {
|
||||
|
@ -228,17 +240,23 @@ public class RoleLDAPFederationMapper extends AbstractLDAPFederationMapper {
|
|||
ldapRole = createLDAPRole(mapperModel, roleName, ldapProvider);
|
||||
}
|
||||
|
||||
MembershipType membershipType = getMembershipTypeLdapAttribute(mapperModel);
|
||||
|
||||
Set<String> memberships = getExistingMemberships(mapperModel, ldapRole);
|
||||
|
||||
// Remove membership placeholder if present
|
||||
if (membershipType == MembershipType.DN) {
|
||||
for (String membership : memberships) {
|
||||
if (LDAPConstants.EMPTY_MEMBER_ATTRIBUTE_VALUE.equals(membership)) {
|
||||
memberships.remove(membership);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memberships.add(ldapUser.getDn().toString());
|
||||
String membership = getMembershipFromUser(ldapUser, membershipType);
|
||||
|
||||
memberships.add(membership);
|
||||
ldapRole.setAttribute(getMembershipLdapAttribute(mapperModel), memberships);
|
||||
|
||||
ldapProvider.getLdapIdentityStore().update(ldapRole);
|
||||
|
@ -246,10 +264,14 @@ public class RoleLDAPFederationMapper extends AbstractLDAPFederationMapper {
|
|||
|
||||
public void deleteRoleMappingInLDAP(UserFederationMapperModel mapperModel, LDAPFederationProvider ldapProvider, LDAPObject ldapUser, LDAPObject ldapRole) {
|
||||
Set<String> memberships = getExistingMemberships(mapperModel, ldapRole);
|
||||
memberships.remove(ldapUser.getDn().toString());
|
||||
|
||||
MembershipType membershipType = getMembershipTypeLdapAttribute(mapperModel);
|
||||
String userMembership = getMembershipFromUser(ldapUser, membershipType);
|
||||
|
||||
memberships.remove(userMembership);
|
||||
|
||||
// Some membership placeholder needs to be always here as "member" is mandatory attribute on some LDAP servers. But not on active directory! (Placeholder, which not matches any real object is not allowed here)
|
||||
if (memberships.size() == 0 && !ldapProvider.getLdapIdentityStore().getConfig().isActiveDirectory()) {
|
||||
if (memberships.size() == 0 && membershipType==MembershipType.DN && !ldapProvider.getLdapIdentityStore().getConfig().isActiveDirectory()) {
|
||||
memberships.add(LDAPConstants.EMPTY_MEMBER_ATTRIBUTE_VALUE);
|
||||
}
|
||||
|
||||
|
@ -276,7 +298,10 @@ public class RoleLDAPFederationMapper extends AbstractLDAPFederationMapper {
|
|||
protected List<LDAPObject> getLDAPRoleMappings(UserFederationMapperModel mapperModel, LDAPFederationProvider ldapProvider, LDAPObject ldapUser) {
|
||||
LDAPQuery ldapQuery = createRoleQuery(mapperModel, ldapProvider);
|
||||
String membershipAttr = getMembershipLdapAttribute(mapperModel);
|
||||
Condition membershipCondition = new LDAPQueryConditionsBuilder().equal(membershipAttr, ldapUser.getDn().toString());
|
||||
|
||||
String userMembership = getMembershipFromUser(ldapUser, getMembershipTypeLdapAttribute(mapperModel));
|
||||
|
||||
Condition membershipCondition = new LDAPQueryConditionsBuilder().equal(membershipAttr, userMembership);
|
||||
ldapQuery.addWhereCondition(membershipCondition);
|
||||
return ldapQuery.getResultList();
|
||||
}
|
||||
|
@ -437,7 +462,8 @@ public class RoleLDAPFederationMapper extends AbstractLDAPFederationMapper {
|
|||
LDAPQuery ldapQuery = createRoleQuery(mapperModel, ldapProvider);
|
||||
LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder();
|
||||
Condition roleNameCondition = conditionsBuilder.equal(getRoleNameLdapAttribute(mapperModel), role.getName());
|
||||
Condition membershipCondition = conditionsBuilder.equal(getMembershipLdapAttribute(mapperModel), ldapUser.getDn().toString());
|
||||
String membershipUserAttr = getMembershipFromUser(ldapUser, getMembershipTypeLdapAttribute(mapperModel));
|
||||
Condition membershipCondition = conditionsBuilder.equal(getMembershipLdapAttribute(mapperModel), membershipUserAttr);
|
||||
ldapQuery.addWhereCondition(roleNameCondition).addWhereCondition(membershipCondition);
|
||||
LDAPObject ldapRole = ldapQuery.getFirstResult();
|
||||
|
||||
|
@ -462,6 +488,7 @@ public class RoleLDAPFederationMapper extends AbstractLDAPFederationMapper {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public enum Mode {
|
||||
/**
|
||||
* All role mappings are retrieved from LDAP and saved into LDAP
|
||||
|
@ -484,4 +511,18 @@ public class RoleLDAPFederationMapper extends AbstractLDAPFederationMapper {
|
|||
*/
|
||||
READ_ONLY
|
||||
}
|
||||
|
||||
|
||||
public enum MembershipType {
|
||||
|
||||
/**
|
||||
* Used if LDAP role has it's members declared in form of their full DN. For example ( "member: uid=john,ou=users,dc=example,dc=com" )
|
||||
*/
|
||||
DN,
|
||||
|
||||
/**
|
||||
* Used if LDAP role has it's members declared in form of pure user uids. For example ( "memberUid: john" )
|
||||
*/
|
||||
UID
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,15 +42,25 @@ public class RoleLDAPFederationMapperFactory extends AbstractLDAPFederationMappe
|
|||
ProviderConfigProperty.STRING_TYPE, LDAPConstants.CN);
|
||||
configProperties.add(roleNameLDAPAttribute);
|
||||
|
||||
ProviderConfigProperty roleObjectClasses = createConfigProperty(RoleLDAPFederationMapper.ROLE_OBJECT_CLASSES, "Role Object Classes",
|
||||
"Object class (or classes) of the role object. It's divided by comma if more classes needed. In typical LDAP deployment it could be 'groupOfNames' . In Active Directory it's usually 'group' ",
|
||||
ProviderConfigProperty.STRING_TYPE, null);
|
||||
configProperties.add(roleObjectClasses);
|
||||
|
||||
ProviderConfigProperty membershipLDAPAttribute = createConfigProperty(RoleLDAPFederationMapper.MEMBERSHIP_LDAP_ATTRIBUTE, "Membership LDAP Attribute",
|
||||
"Name of LDAP attribute on role, which is used for membership mappings. Usually it will be 'member' ",
|
||||
ProviderConfigProperty.STRING_TYPE, LDAPConstants.MEMBER);
|
||||
configProperties.add(membershipLDAPAttribute);
|
||||
|
||||
ProviderConfigProperty roleObjectClasses = createConfigProperty(RoleLDAPFederationMapper.ROLE_OBJECT_CLASSES, "Role Object Classes",
|
||||
"Object class (or classes) of the role object. It's divided by comma if more classes needed. In typical LDAP deployment it could be 'groupOfNames' . In Active Directory it's usually 'group' ",
|
||||
ProviderConfigProperty.STRING_TYPE, null);
|
||||
configProperties.add(roleObjectClasses);
|
||||
List<String> membershipTypes = new LinkedList<>();
|
||||
for (RoleLDAPFederationMapper.MembershipType membershipType : RoleLDAPFederationMapper.MembershipType.values()) {
|
||||
membershipTypes.add(membershipType.toString());
|
||||
}
|
||||
ProviderConfigProperty membershipType = createConfigProperty(RoleLDAPFederationMapper.MEMBERSHIP_ATTRIBUTE_TYPE, "Membership Attribute Type",
|
||||
"DN means that LDAP role has it's members declared in form of their full DN. For example ( 'member: uid=john,ou=users,dc=example,dc=com' . " +
|
||||
"UID means that LDAP role has it's members declared in form of pure user uids. For example ( 'memberuid: john' ))",
|
||||
ProviderConfigProperty.LIST_TYPE, membershipTypes);
|
||||
configProperties.add(membershipType);
|
||||
|
||||
ProviderConfigProperty ldapFilter = createConfigProperty(RoleLDAPFederationMapper.ROLES_LDAP_FILTER,
|
||||
"LDAP Filter",
|
||||
|
@ -58,7 +68,7 @@ public class RoleLDAPFederationMapperFactory extends AbstractLDAPFederationMappe
|
|||
ProviderConfigProperty.STRING_TYPE, null);
|
||||
configProperties.add(ldapFilter);
|
||||
|
||||
List<String> modes = new LinkedList<String>();
|
||||
List<String> modes = new LinkedList<>();
|
||||
for (RoleLDAPFederationMapper.Mode mode : RoleLDAPFederationMapper.Mode.values()) {
|
||||
modes.add(mode.toString());
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue