From 6cab7c3b961096d3eae48a8e65854ac4a41f07d9 Mon Sep 17 00:00:00 2001 From: Maxime Dor Date: Sun, 12 Feb 2017 00:00:16 +0100 Subject: [PATCH] Overall improvement - Configuration file is documented - Give more flexibility to the LDAP lookup - Various suggestions in errors to help new users --- application.example.yaml | 37 ++++++++++++++-- .../io/kamax/mxisd/config/LdapConfig.groovy | 9 ++++ .../io/kamax/mxisd/config/ServerConfig.groovy | 2 +- .../io/kamax/mxisd/lookup/LdapProvider.groovy | 42 ++++++++++++++++++- 4 files changed, 84 insertions(+), 6 deletions(-) diff --git a/application.example.yaml b/application.example.yaml index 960ab4b..a9b6bdf 100644 --- a/application.example.yaml +++ b/application.example.yaml @@ -1,15 +1,46 @@ server: + + # Indicate on which port the Identity Server will listen. This is an unencrypted port. + # HTTPS can be configured using Tomcat configuration properties. port: 8090 + + # Realm under which this Identity Server is authoritative, e.g. domain name in e-mails. + # This is used in some recursive lookups to avoid endless loops and avoid bothering other Identity Servers. name: 'example.org' + key: + + # Where the Identity Server signing key will be stored. + # + # /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ + # /!\ CHANGE THIS TO A MORE PERMANENT LOCATION! /!\ + # /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ /!\ path: '/var/tmp/mxis-signing.key' + ldap: host: 'localhost' port: 389 + bindDn: 'CN=Matrix Identity Server,CN=Users,DC=example,DC=org' + bindPassword: 'password' baseDn: 'CN=Users,DC=example,DC=org' query: '(|(mailPrimaryAddress=%3pid)(mail=%3pid)(otherMailbox=%3pid))' - attribute: 'pager' - bindDn: 'CN=Identity Server,CN=Users,DC=example,DC=org' - bindPassword: 'password' + + # How should we resolve the Matrix ID in case of a match using the attribute. + # + # The following type are supported: + # - uid : the attribute only contains the UID part of the Matrix ID. e.g. 'john.doe' in @john.doe:example.org + # - mxid : the attribute contains the full Matrix ID - e.g. '@john.doe:example.org' + type: 'uid' + + # The attribute containing the binding itself. This value will be used differently depending on the type. + # + # Typical values: + # - For type 'uid': + # - Samba/AD: sAMAccountName + # - LDAP: If someone knows the most appropriate value, please open an issue + # + # - For type 'mxid', regardless of the directory type, we recommend using 'pager' as it is a standard attribute but + # shouldn't be used in infrastructures. + attribute: 'sAMAccountName' diff --git a/src/main/groovy/io/kamax/mxisd/config/LdapConfig.groovy b/src/main/groovy/io/kamax/mxisd/config/LdapConfig.groovy index 6125929..e9710d8 100644 --- a/src/main/groovy/io/kamax/mxisd/config/LdapConfig.groovy +++ b/src/main/groovy/io/kamax/mxisd/config/LdapConfig.groovy @@ -31,6 +31,7 @@ class LdapConfig { private int port private String baseDn private String query + private String type private String attribute private String bindDn private String bindPassword @@ -67,6 +68,14 @@ class LdapConfig { this.query = query } + String getType() { + return type + } + + void setType(String type) { + this.type = type + } + String getAttribute() { return attribute } diff --git a/src/main/groovy/io/kamax/mxisd/config/ServerConfig.groovy b/src/main/groovy/io/kamax/mxisd/config/ServerConfig.groovy index b14d4b8..800cc5a 100644 --- a/src/main/groovy/io/kamax/mxisd/config/ServerConfig.groovy +++ b/src/main/groovy/io/kamax/mxisd/config/ServerConfig.groovy @@ -42,7 +42,7 @@ class ServerConfig implements InitializingBean { @Override void afterPropertiesSet() throws Exception { if (StringUtils.isBlank(getName())) { - throw new RuntimeException("Server name must be configured!") + throw new RuntimeException("Server name must be configured. Use the same realm as your Homeserver") } } diff --git a/src/main/groovy/io/kamax/mxisd/lookup/LdapProvider.groovy b/src/main/groovy/io/kamax/mxisd/lookup/LdapProvider.groovy index 81e3968..75ef6ec 100644 --- a/src/main/groovy/io/kamax/mxisd/lookup/LdapProvider.groovy +++ b/src/main/groovy/io/kamax/mxisd/lookup/LdapProvider.groovy @@ -22,6 +22,8 @@ package io.kamax.mxisd.lookup import io.kamax.mxisd.api.ThreePidType import io.kamax.mxisd.config.LdapConfig +import io.kamax.mxisd.config.ServerConfig +import org.apache.commons.lang.StringUtils import org.apache.directory.api.ldap.model.cursor.EntryCursor import org.apache.directory.api.ldap.model.entry.Attribute import org.apache.directory.api.ldap.model.message.SearchScope @@ -29,14 +31,21 @@ import org.apache.directory.ldap.client.api.LdapConnection import org.apache.directory.ldap.client.api.LdapNetworkConnection import org.slf4j.Logger import org.slf4j.LoggerFactory +import org.springframework.beans.factory.InitializingBean import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Component @Component -class LdapProvider implements ThreePidProvider { +class LdapProvider implements ThreePidProvider, InitializingBean { + + public static final String UID = "uid" + public static final String MATRIX_ID = "mxid" private Logger log = LoggerFactory.getLogger(LdapProvider.class) + @Autowired + private ServerConfig srvCfg + @Autowired private LdapConfig ldapCfg @@ -45,6 +54,13 @@ class LdapProvider implements ThreePidProvider { return 20 } + @Override + void afterPropertiesSet() throws Exception { + if (!Arrays.asList(UID, MATRIX_ID).contains(ldapCfg.getType())) { + throw new IllegalArgumentException(ldapCfg.getType() + " is not a valid LDAP lookup type") + } + } + @Override Optional find(ThreePidType type, String threePid) { log.info("Performing LDAP lookup ${threePid} of type ${type}") @@ -59,10 +75,30 @@ class LdapProvider implements ThreePidProvider { if (cursor.next()) { Attribute attribute = cursor.get().get(ldapCfg.getAttribute()) if (attribute != null) { + String data = attribute.get().toString() + if (data.length() < 1) { + log.warn("Bind was found but value is empty") + return Optional.empty() + } + + StringBuilder matrixId = new StringBuilder() + // TODO Should we turn this block into a map of functions? + if (StringUtils.equals("uid", ldapCfg.getType())) { + matrixId.append("@").append(data).append(":").append(srvCfg.getName()) + } + if (StringUtils.equals("mxid", ldapCfg.getType())) { + matrixId.append(data) + } + + if (matrixId.length() < 1) { + log.warn("Bind was found but type ${ldapCfg.getType()} is not supported") + return Optional.empty() + } + return Optional.of([ address : threePid, medium : type, - mxid : attribute.get().toString(), + mxid : matrixId.toString(), not_before: 0, not_after : 9223372036854775807, ts : 0 @@ -76,7 +112,9 @@ class LdapProvider implements ThreePidProvider { conn.close() } + log.info("No match found") return Optional.empty() } + }