Support for Active Directory multidomain forest
In AD forest samAccountName (or uid) may not be unique in the entire forest and userPrincipalName contains "@" symbol disallowed in Matrix User Identifiers. This commit reflects changes in ldap_auth_provider that adds mxid generation logic for Active Directory. Signed-off-by: Yuri Konotopov <ykonotopov@gnome.org>
This commit is contained in:
@@ -165,6 +165,8 @@ threepid:
|
|||||||
# ldap:
|
# ldap:
|
||||||
# enabled: true
|
# enabled: true
|
||||||
# lookup: true # hash lookup
|
# lookup: true # hash lookup
|
||||||
|
# activeDirectory: false
|
||||||
|
# defaultDomain: ''
|
||||||
# connection:
|
# connection:
|
||||||
# host: 'ldap.domain.tld'
|
# host: 'ldap.domain.tld'
|
||||||
# port: 389
|
# port: 389
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
package io.kamax.mxisd.backend.ldap;
|
package io.kamax.mxisd.backend.ldap;
|
||||||
|
|
||||||
|
import io.kamax.matrix.MatrixID;
|
||||||
import io.kamax.matrix._MatrixID;
|
import io.kamax.matrix._MatrixID;
|
||||||
import io.kamax.mxisd.config.MatrixConfig;
|
import io.kamax.mxisd.config.MatrixConfig;
|
||||||
import io.kamax.mxisd.config.ldap.LdapConfig;
|
import io.kamax.mxisd.config.ldap.LdapConfig;
|
||||||
@@ -116,10 +117,16 @@ public abstract class LdapBackend {
|
|||||||
|
|
||||||
public String buildMatrixIdFromUid(String uid) {
|
public String buildMatrixIdFromUid(String uid) {
|
||||||
String uidType = getCfg().getAttribute().getUid().getType();
|
String uidType = getCfg().getAttribute().getUid().getType();
|
||||||
|
String localpart = uid;
|
||||||
|
|
||||||
if (StringUtils.equals(UID, uidType)) {
|
if (StringUtils.equals(UID, uidType)) {
|
||||||
return "@" + uid + ":" + mxCfg.getDomain();
|
if(getCfg().isActiveDirectory()) {
|
||||||
|
localpart = new UPN(uid).getMXID();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "@" + localpart + ":" + mxCfg.getDomain();
|
||||||
} else if (StringUtils.equals(MATRIX_ID, uidType)) {
|
} else if (StringUtils.equals(MATRIX_ID, uidType)) {
|
||||||
return uid;
|
return localpart;
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Bind type " + uidType + " is not supported");
|
throw new IllegalArgumentException("Bind type " + uidType + " is not supported");
|
||||||
}
|
}
|
||||||
@@ -128,6 +135,10 @@ public abstract class LdapBackend {
|
|||||||
public String buildUidFromMatrixId(_MatrixID mxId) {
|
public String buildUidFromMatrixId(_MatrixID mxId) {
|
||||||
String uidType = getCfg().getAttribute().getUid().getType();
|
String uidType = getCfg().getAttribute().getUid().getType();
|
||||||
if (StringUtils.equals(UID, uidType)) {
|
if (StringUtils.equals(UID, uidType)) {
|
||||||
|
if(getCfg().isActiveDirectory()) {
|
||||||
|
return new UPN(mxId).getUPN();
|
||||||
|
}
|
||||||
|
|
||||||
return mxId.getLocalPart();
|
return mxId.getLocalPart();
|
||||||
} else if (StringUtils.equals(MATRIX_ID, uidType)) {
|
} else if (StringUtils.equals(MATRIX_ID, uidType)) {
|
||||||
return mxId.getId();
|
return mxId.getId();
|
||||||
@@ -169,4 +180,58 @@ public abstract class LdapBackend {
|
|||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class UPN {
|
||||||
|
private String login;
|
||||||
|
private String domain;
|
||||||
|
|
||||||
|
public UPN(String userPrincipalName) {
|
||||||
|
String[] uidParts = userPrincipalName.split("@");
|
||||||
|
|
||||||
|
if (uidParts.length != 2) {
|
||||||
|
throw new IllegalArgumentException(String.format("Wrong userPrincipalName provided: %s", userPrincipalName));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.login = uidParts[0];
|
||||||
|
this.domain = uidParts[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
public UPN(_MatrixID mxid) {
|
||||||
|
String[] idParts = mxid.getLocalPart().split("/");
|
||||||
|
|
||||||
|
if (idParts.length != 2) {
|
||||||
|
if(idParts.length == 1 && !StringUtils.isEmpty(getCfg().getDefaultDomain())) {
|
||||||
|
throw new IllegalArgumentException(String.format(
|
||||||
|
"Local part of mxid %s does not contains domain separator and default domain is not configured",
|
||||||
|
mxid.getLocalPart()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.domain = getCfg().getDefaultDomain();
|
||||||
|
} else {
|
||||||
|
this.domain = idParts[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.login = idParts[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLogin() {
|
||||||
|
return login;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDomain() {
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMXID() {
|
||||||
|
if(StringUtils.equalsIgnoreCase(getCfg().getDefaultDomain(), this.domain)) {
|
||||||
|
return this.login;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new StringBuilder(this.login).append("/").append(this.domain).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUPN() {
|
||||||
|
return new StringBuilder(this.login).append("@").append(this.domain).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -291,6 +291,9 @@ public abstract class LdapConfig {
|
|||||||
private boolean enabled;
|
private boolean enabled;
|
||||||
private String filter;
|
private String filter;
|
||||||
|
|
||||||
|
private boolean activeDirectory;
|
||||||
|
private String defaultDomain;
|
||||||
|
|
||||||
private Connection connection = new Connection();
|
private Connection connection = new Connection();
|
||||||
private Attribute attribute = new Attribute();
|
private Attribute attribute = new Attribute();
|
||||||
private Auth auth = new Auth();
|
private Auth auth = new Auth();
|
||||||
@@ -316,6 +319,22 @@ public abstract class LdapConfig {
|
|||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isActiveDirectory() {
|
||||||
|
return activeDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setActiveDirectory(boolean activeDirectory) {
|
||||||
|
this.activeDirectory = activeDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDefaultDomain() {
|
||||||
|
return defaultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefaultDomain(String defaultDomain) {
|
||||||
|
this.defaultDomain = defaultDomain;
|
||||||
|
}
|
||||||
|
|
||||||
public Connection getConnection() {
|
public Connection getConnection() {
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
@@ -407,6 +426,15 @@ public abstract class LdapConfig {
|
|||||||
throw new ConfigurationException("ldap.identity.token");
|
throw new ConfigurationException("ldap.identity.token");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(isActiveDirectory()) {
|
||||||
|
if(!StringUtils.equals(LdapBackend.UID, uidType)) {
|
||||||
|
throw new IllegalArgumentException(String.format(
|
||||||
|
"Attribute UID type should be set to %s in Active Directory mode",
|
||||||
|
LdapBackend.UID
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Build queries
|
// Build queries
|
||||||
attribute.getThreepid().forEach((k, v) -> {
|
attribute.getThreepid().forEach((k, v) -> {
|
||||||
if (StringUtils.isBlank(identity.getMedium().get(k))) {
|
if (StringUtils.isBlank(identity.getMedium().get(k))) {
|
||||||
|
Reference in New Issue
Block a user