This is an automated email from the ASF dual-hosted git repository.
btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
The following commit(s) were added to refs/heads/master by this push:
new 00c51c98ae [FIX] Enable dynamic translation of LDAP entries (#1932)
00c51c98ae is described below
commit 00c51c98ae002bce3cb346c2163ebe429f74db95
Author: Benoit TELLIER <[email protected]>
AuthorDate: Mon Jan 22 16:40:28 2024 +0100
[FIX] Enable dynamic translation of LDAP entries (#1932)
---
.../user/ldap/LdapRepositoryConfiguration.java | 25 ++++++++++++++++++----
.../james/user/ldap/ReadOnlyLDAPUsersDAO.java | 25 +++++++++++++++-------
2 files changed, 38 insertions(+), 12 deletions(-)
diff --git
a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/LdapRepositoryConfiguration.java
b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/LdapRepositoryConfiguration.java
index 4548d5d01d..33ba7aaa92 100644
---
a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/LdapRepositoryConfiguration.java
+++
b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/LdapRepositoryConfiguration.java
@@ -58,6 +58,7 @@ public class LdapRepositoryConfiguration {
private Optional<String> userIdAttribute;
private Optional<String> resolveLocalPartAttribute;
private Optional<String> userObjectClass;
+ private Optional<String> usernameAttribute;
private Optional<Integer> poolSize;
private Optional<Boolean> trustAllCerts;
private ImmutableMap.Builder<Domain, String> perDomainBaseDN;
@@ -71,6 +72,7 @@ public class LdapRepositoryConfiguration {
userIdAttribute = Optional.empty();
resolveLocalPartAttribute = Optional.empty();
userObjectClass = Optional.empty();
+ usernameAttribute = Optional.empty();
poolSize = Optional.empty();
trustAllCerts = Optional.empty();
perDomainBaseDN = ImmutableMap.builder();
@@ -147,6 +149,7 @@ public class LdapRepositoryConfiguration {
userListBase.orElse(userBase.get()),
userIdAttribute.get(),
resolveLocalPartAttribute,
+ usernameAttribute,
userObjectClass.get(),
NO_CONNECTION_TIMEOUT,
NO_READ_TIME_OUT,
@@ -180,6 +183,7 @@ public class LdapRepositoryConfiguration {
.orElse(userBase);
String userIdAttribute = configuration.getString("[@userIdAttribute]");
Optional<String> resolveLocalPartAttribute =
Optional.ofNullable(configuration.getString("[@resolveLocalPartAttribute]",
null));
+ Optional<String> usernameAttribute =
Optional.ofNullable(configuration.getString("[@usernameAttribute]", null));
String userObjectClass = configuration.getString("[@userObjectClass]");
// Default is to use connection pooling
int connectionTimeout = configuration.getInt("[@connectionTimeout]",
NO_CONNECTION_TIMEOUT);
@@ -223,6 +227,7 @@ public class LdapRepositoryConfiguration {
userBase,
userListBase, userIdAttribute,
resolveLocalPartAttribute,
+ usernameAttribute,
userObjectClass,
connectionTimeout,
readTimeout,
@@ -282,10 +287,16 @@ public class LdapRepositoryConfiguration {
/**
* The value of this field is taken from the configuration attribute
* "userIdAttribute". This is the LDAP attribute type which holds
- * the userId value. Note that this is not the same as the email address
- * attribute.
+ * the userId value. This value is used to identify the LDAP entry used
for authentication,
+ * and by default is used to retrieve the associated username.
*/
private final String userIdAttribute;
+ /**
+ * The value of this field is taken from the configuration attribute
+ * "userIdAttribute". This is the LDAP attribute is used to,
given a LDAP entry,
+ * retrieve the associated username. Defaults to 'userIdAttribute' value.
+ */
+ private final Optional<String> usernameAttribute;
/**
* The value of this field is taken from the configuration attribute
@@ -337,7 +348,7 @@ public class LdapRepositoryConfiguration {
private final ImmutableMap<Domain, String> perDomainBaseDN;
private LdapRepositoryConfiguration(List<URI> ldapHosts, String principal,
String credentials, String userBase, String userListBase, String
userIdAttribute,
- Optional<String>
resolveLocalPartAttribute, String userObjectClass, int connectionTimeout, int
readTimeout,
+ Optional<String>
resolveLocalPartAttribute, Optional<String> usernameAttribute, String
userObjectClass, int connectionTimeout, int readTimeout,
boolean supportsVirtualHosting, int
poolSize, ReadOnlyLDAPGroupRestriction restriction, String filter,
Optional<String> administratorId,
boolean trustAllCerts,
ImmutableMap<Domain, String>
perDomainBaseDN) throws ConfigurationException {
@@ -348,6 +359,7 @@ public class LdapRepositoryConfiguration {
this.userListBase = userListBase;
this.userIdAttribute = userIdAttribute;
this.resolveLocalPartAttribute = resolveLocalPartAttribute;
+ this.usernameAttribute = usernameAttribute;
this.userObjectClass = userObjectClass;
this.connectionTimeout = connectionTimeout;
this.readTimeout = readTimeout;
@@ -402,6 +414,10 @@ public class LdapRepositoryConfiguration {
return resolveLocalPartAttribute;
}
+ public Optional<String> getUsernameAttribute() {
+ return usernameAttribute;
+ }
+
public String getUserObjectClass() {
return userObjectClass;
}
@@ -463,6 +479,7 @@ public class LdapRepositoryConfiguration {
&& Objects.equals(this.poolSize, that.poolSize)
&& Objects.equals(this.administratorId, that.administratorId)
&& Objects.equals(this.trustAllCerts, that.trustAllCerts)
+ && Objects.equals(this.usernameAttribute,
that.usernameAttribute)
&& Objects.equals(this.perDomainBaseDN, that.perDomainBaseDN);
}
return false;
@@ -472,6 +489,6 @@ public class LdapRepositoryConfiguration {
public final int hashCode() {
return Objects.hash(ldapHosts, principal, credentials, userBase,
userListBase, userIdAttribute, resolveLocalPartAttribute, userObjectClass,
connectionTimeout, readTimeout, supportsVirtualHosting,
restriction, filter, administratorId, poolSize,
- trustAllCerts, perDomainBaseDN);
+ trustAllCerts, perDomainBaseDN, usernameAttribute);
}
}
diff --git
a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyLDAPUsersDAO.java
b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyLDAPUsersDAO.java
index f75ca91056..f6ece9d141 100644
---
a/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyLDAPUsersDAO.java
+++
b/server/data/data-ldap/src/main/java/org/apache/james/user/ldap/ReadOnlyLDAPUsersDAO.java
@@ -131,7 +131,6 @@ public class ReadOnlyLDAPUsersDAO implements UsersDAO,
Configurable {
* specified LDAP host.
*/
public void init() throws Exception {
-
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(this.getClass().getName() + ".init()" + '\n' + "LDAP
hosts: " + ldapConfiguration.getLdapHosts()
+ '\n' + "User baseDN: " + ldapConfiguration.getUserBase() +
'\n' + "userIdAttribute: "
@@ -236,7 +235,7 @@ public class ReadOnlyLDAPUsersDAO implements UsersDAO,
Configurable {
return
username.getDomainPart().map(this::userBase).orElse(ldapConfiguration.getUserBase());
}
- private Set<DN> getAllUsersDNFromLDAP() throws LDAPException {
+ private Set<DN> getAllUsersDNFromLDAP() {
return allDNs()
.flatMap(Throwing.<String,
Stream<SearchResultEntry>>function(this::entriesFromDN).sneakyThrow())
.map(Throwing.function(Entry::getParsedDN))
@@ -265,9 +264,10 @@ public class ReadOnlyLDAPUsersDAO implements UsersDAO,
Configurable {
}
private Stream<Username> getAllUsernamesFromLDAP() throws LDAPException {
+ String usernameAttribute =
ldapConfiguration.getUsernameAttribute().orElse(ldapConfiguration.getUserIdAttribute());
return allDNs()
- .flatMap(Throwing.<String, Stream<SearchResultEntry>>function(s ->
entriesFromDN(s, ldapConfiguration.getUserIdAttribute())).sneakyThrow())
- .flatMap(entry ->
Optional.ofNullable(entry.getAttribute(ldapConfiguration.getUserIdAttribute())).stream())
+ .flatMap(Throwing.<String, Stream<SearchResultEntry>>function(s ->
entriesFromDN(s, usernameAttribute)).sneakyThrow())
+ .flatMap(entry ->
Optional.ofNullable(entry.getAttribute(usernameAttribute)).stream())
.map(Attribute::getValue)
.map(Username::of)
.distinct();
@@ -300,12 +300,11 @@ public class ReadOnlyLDAPUsersDAO implements UsersDAO,
Configurable {
private Optional<ReadOnlyLDAPUser> searchAndBuildUser(Username
retrievalName) throws LDAPException {
Optional<String> resolveLocalPartAttribute =
ldapConfiguration.getResolveLocalPartAttribute();
- String[] returnedAttributes = { ldapConfiguration.getUserIdAttribute()
};
SearchResult searchResult =
ldapConnectionPool.search(userBase(retrievalName),
SearchScope.SUB,
createFilter(retrievalName.asString(),
evaluateLdapUserRetrievalAttribute(retrievalName, resolveLocalPartAttribute)),
- returnedAttributes);
+ getReturnedAttributes());
SearchResultEntry result = searchResult.getSearchEntries()
.stream()
@@ -319,12 +318,21 @@ public class ReadOnlyLDAPUsersDAO implements UsersDAO,
Configurable {
if (!ldapConfiguration.getRestriction().isActivated()
|| userInGroupsMembershipList(result.getParsedDN(),
ldapConfiguration.getRestriction().getGroupMembershipLists(ldapConnectionPool)))
{
- Username translatedUsername =
Username.of(result.getAttributeValue(ldapConfiguration.getUserIdAttribute()));
+ String usernameAttribute =
ldapConfiguration.getUsernameAttribute().orElse(ldapConfiguration.getUserIdAttribute());
+ Username translatedUsername =
Username.of(result.getAttributeValue(usernameAttribute));
return Optional.of(new ReadOnlyLDAPUser(translatedUsername,
result.getParsedDN(), ldapConnectionPool));
}
return Optional.empty();
}
+ private String[] getReturnedAttributes() {
+ if (ldapConfiguration.getUsernameAttribute().isPresent()) {
+ return new String[]{ldapConfiguration.getUserIdAttribute(),
ldapConfiguration.getUsernameAttribute().get()};
+ } else {
+ return new String[]{ldapConfiguration.getUserIdAttribute()};
+ }
+ }
+
private String evaluateLdapUserRetrievalAttribute(Username retrievalName,
Optional<String> resolveLocalPartAttribute) {
if (retrievalName.asString().contains("@")) {
return ldapConfiguration.getUserIdAttribute();
@@ -335,7 +343,8 @@ public class ReadOnlyLDAPUsersDAO implements UsersDAO,
Configurable {
private Optional<ReadOnlyLDAPUser> buildUser(DN userDN) throws
LDAPException {
SearchResultEntry userAttributes =
ldapConnectionPool.getEntry(userDN.toString());
- Optional<String> userName =
Optional.ofNullable(userAttributes.getAttributeValue(ldapConfiguration.getUserIdAttribute()));
+ String usernameAttribute =
ldapConfiguration.getUsernameAttribute().orElse(ldapConfiguration.getUserIdAttribute());
+ Optional<String> userName =
Optional.ofNullable(userAttributes.getAttributeValue(usernameAttribute));
return userName
.map(Username::of)
.map(username -> new ReadOnlyLDAPUser(username, userDN,
ldapConnectionPool));
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]