/
RoleLDAPFederationMapperFactory.java
118 lines (95 loc) · 5.92 KB
/
RoleLDAPFederationMapperFactory.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package org.keycloak.federation.ldap.mappers;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.keycloak.mappers.MapperConfigValidationException;
import org.keycloak.mappers.UserFederationMapper;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.LDAPConstants;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationMapperModel;
import org.keycloak.provider.ProviderConfigProperty;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class RoleLDAPFederationMapperFactory extends AbstractLDAPFederationMapperFactory {
public static final String PROVIDER_ID = "role-ldap-mapper";
protected static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
static {
ProviderConfigProperty rolesDn = createConfigProperty(RoleLDAPFederationMapper.ROLES_DN, "LDAP Roles DN",
"LDAP DN where are roles of this tree saved. For example 'ou=finance,dc=example,dc=org' ", ProviderConfigProperty.STRING_TYPE, null);
configProperties.add(rolesDn);
ProviderConfigProperty roleNameLDAPAttribute = createConfigProperty(RoleLDAPFederationMapper.ROLE_NAME_LDAP_ATTRIBUTE, "Role Name LDAP Attribute",
"Name of LDAP attribute, which is used in role objects for name and RDN of role. Usually it will be 'cn' . In this case typical group/role object may have DN like 'cn=role1,ou=finance,dc=example,dc=org' ",
ProviderConfigProperty.STRING_TYPE, LDAPConstants.CN);
configProperties.add(roleNameLDAPAttribute);
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 classes of the role object divided by comma (if more values needed). In typical LDAP deployment it could be 'groupOfNames' or 'groupOfEntries' ",
ProviderConfigProperty.STRING_TYPE, LDAPConstants.GROUP_OF_NAMES);
configProperties.add(roleObjectClasses);
List<String> modes = new LinkedList<String>();
for (RoleLDAPFederationMapper.Mode mode : RoleLDAPFederationMapper.Mode.values()) {
modes.add(mode.toString());
}
ProviderConfigProperty mode = createConfigProperty(RoleLDAPFederationMapper.MODE, "Mode",
"LDAP_ONLY means that all role mappings are retrieved from LDAP and saved into LDAP. READ_ONLY is Read-only LDAP mode where role mappings are " +
"retrieved from both LDAP and DB and merged together. New role grants are not saved to LDAP but to DB. IMPORT is Read-only LDAP mode where role mappings are retrieved from LDAP just at the time when user is imported from LDAP and then " +
"they are saved to local keycloak DB.",
ProviderConfigProperty.LIST_TYPE, modes);
configProperties.add(mode);
ProviderConfigProperty useRealmRolesMappings = createConfigProperty(RoleLDAPFederationMapper.USE_REALM_ROLES_MAPPING, "Use Realm Roles Mapping",
"If true, then LDAP role mappings will be mapped to realm role mappings in Keycloak. Otherwise it will be mapped to client role mappings", ProviderConfigProperty.BOOLEAN_TYPE, "true");
configProperties.add(useRealmRolesMappings);
// NOTE: ClientID will be computed dynamically from available clients
}
@Override
public String getHelpText() {
return "Used to map role mappings of roles from some LDAP DN to Keycloak role mappings of either realm roles or client roles of particular client";
}
@Override
public String getDisplayCategory() {
return ROLE_MAPPER_CATEGORY;
}
@Override
public String getDisplayType() {
return "Role mappings";
}
@Override
public List<ProviderConfigProperty> getConfigProperties(RealmModel realm) {
List<ProviderConfigProperty> props = new ArrayList<ProviderConfigProperty>(configProperties);
Map<String, ClientModel> clients = realm.getClientNameMap();
List<String> clientIds = new ArrayList<String>(clients.keySet());
ProviderConfigProperty clientIdProperty = createConfigProperty(RoleLDAPFederationMapper.CLIENT_ID, "Client ID",
"Client ID of client to which LDAP role mappings will be mapped. Applicable just if 'Use Realm Roles Mapping' is false",
ProviderConfigProperty.LIST_TYPE, clientIds);
props.add(clientIdProperty);
return props;
}
@Override
public String getId() {
return PROVIDER_ID;
}
@Override
public void validateConfig(UserFederationMapperModel mapperModel) throws MapperConfigValidationException {
checkMandatoryConfigAttribute(RoleLDAPFederationMapper.ROLES_DN, "LDAP Roles DN", mapperModel);
String realmMappings = mapperModel.getConfig().get(RoleLDAPFederationMapper.USE_REALM_ROLES_MAPPING);
boolean useRealmMappings = Boolean.parseBoolean(realmMappings);
if (!useRealmMappings) {
String clientId = mapperModel.getConfig().get(RoleLDAPFederationMapper.CLIENT_ID);
if (clientId == null || clientId.trim().isEmpty()) {
throw new MapperConfigValidationException("Client ID needs to be provided in config when Realm Roles Mapping is not used");
}
}
}
@Override
public UserFederationMapper create(KeycloakSession session) {
return new RoleLDAPFederationMapper();
}
}