From ca0dc33cb779f0e6fc0faed7fb5470b33d0201a0 Mon Sep 17 00:00:00 2001 From: Simon Markus Haller Date: Tue, 25 May 2021 15:35:13 +0200 Subject: [PATCH] Merged pull reqeust #9. Added missing adaptions in ContactController. Generally moved GROUP_FILTER to USER_FILTER. Added some comments to the readme. --- README.md | 6 ++++ docker-compose.certbot.yml | 32 +++++++++++-------- docker-compose.traefik.yml | 20 ++++++++---- .../sharelatex/AuthenticationManager.js | 3 +- .../sharelatex/ContactController.js | 12 ++++++- 5 files changed, 50 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 42dd24f..5336dba 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,12 @@ The inital idea for this implementation was taken from NEW: This version provides the possibility to use a separate ldap bind user. It does this just to find the proper BIND DN and record for the provided email, so it is possible that users from different groups / OUs can login. Afterwards it tries to bind to the ldap (using ldapts) with the user DN and credentials of the user which tries to login. No hassle of password hashing for LDAP pwds! +If you upgrade from an older commit: +**Note**: + - you have to add: uid=%u to your BIND_DN + - LDAP_GROUP_FILTER is now named LDAP_USER_FILTER + + Only valid LDAP users or email users registered by an admin can login. This module authenticates against the local DB if `ALLOW_EMAIL_LOGIN` is set to `true` if this fails it tries to authenticate against the specified LDAP server. diff --git a/docker-compose.certbot.yml b/docker-compose.certbot.yml index 4b3ec6e..51989b5 100644 --- a/docker-compose.certbot.yml +++ b/docker-compose.certbot.yml @@ -54,24 +54,30 @@ services: SHARELATEX_SECURE_COOKIE: 'true' SHARELATEX_BEHIND_PROXY: 'true' - LDAP_SERVER: ldaps://LDAPSERVER:636 LDAP_SERVER: ldaps://LDAPSERVER:636 LDAP_BASE: ou=people,dc=DOMAIN,dc=TLD - LDAP_BINDDN: ou=someunit,ou=people,dc=DOMAIN,dc=TLS - # Binds with the LDAP_BIND_USER and searches for users matching this filter: - LDAP_USER_FILTER: '(memberof=cn=GROUPNAME,ou=groups,dc=DOMAIN,dc=TLD)(uid=%u)' - # If user is in ADMIN_GROUP on user creation (first login) isAdmin is set to true. - # Admin Users can invite external (non ldap) users. This feature makes only sense - # when ALLOW_EMAIL_LOGIN is set to 'true'. Additionally adminsy can send + ### There are to ways get users from the ldap server + + ## NO LDAP BIND USER: + # Tries directly to bind with the login user (as uid) + # LDAP_BINDDN: uid=%u,ou=someunit,ou=people,dc=DOMAIN,dc=TLD + + ## Or you can use ai global LDAP_BIND_USER + # LDAP_BIND_USER: + # LDAP_BIND_PW: + + # Only allow users matching LDAP_USER_FILTER + LDAP_USER_FILTER: '(memberof=cn=GROUPNAME,ou=groups,dc=DOMAIN,dc=TLD)' + + # If user is in ADMIN_GROUP on user creation (first login) isAdmin is set to true. + # Admin Users can invite external (non ldap) users. This feature makes only sense + # when ALLOW_EMAIL_LOGIN is set to 'true'. Additionally admins can send # system wide messages. - #LDAP_ADMIN_GROUP_FILTER: '(memberof=cn=ADMINGROUPNAME,ou=groups,dc=DOMAIN,dc=TLD)' - ALLOW_EMAIL_LOGIN: 'false' + LDAP_ADMIN_GROUP_FILTER: '(memberof=cn=ADMINGROUPNAME,ou=groups,dc=DOMAIN,dc=TLD)' + ALLOW_EMAIL_LOGIN: 'true' - # All users in the LDAP_GROUP_FILTER are loaded from the ldap server into contacts. - # This LDAP search happens without bind. If you want this and your LDAP needs a bind you can - # adapt this in the function getLdapContacts() in ContactsController.js (lines 82 - 107) - LDAP_GROUP_FILTER: '(memberof=cn=GROUPNAME,ou=groups,dc=DOMAIN,dc=TLD)' + # All users in the LDAP_USER_FILTER are loaded from the ldap server into contacts. LDAP_CONTACTS: 'false' # Same property, unfortunately with different names in diff --git a/docker-compose.traefik.yml b/docker-compose.traefik.yml index 500ec19..5391fe2 100644 --- a/docker-compose.traefik.yml +++ b/docker-compose.traefik.yml @@ -135,10 +135,19 @@ services: LDAP_SERVER: ldaps://LDAPSERVER:636 LDAP_BASE: ou=people,dc=DOMAIN,dc=TLD - #LDAP_BINDDN: ou=someunit,ou=people,dc=DOMAIN,dc=TLS - # # Binds with the LDAP_BIND_USER and searches for users matching this filter: - LDAP_USER_FILTER: '(memberof=cn=GROUPNAME,ou=groups,dc=DOMAIN,dc=TLD)(uid=%u)' + ### There are to ways get users from the ldap server + + ## NO LDAP BIND USER: + # Tries to bind with login-user (as uid) to LDAP_BINDDN + # LDAP_BINDDN: uid=%u,ou=someunit,ou=people,dc=DOMAIN,dc=TLD + + ## Using a LDAP_BIND_USER/PW + # LDAP_BIND_USER: + # LDAP_BIND_PW: + + # Only allow users matching LDAP_USER_FILTER + LDAP_USER_FILTER: '(memberof=cn=GROUPNAME,ou=groups,dc=DOMAIN,dc=TLD)' # If user is in ADMIN_GROUP on user creation (first login) isAdmin is set to true. # Admin Users can invite external (non ldap) users. This feature makes only sense @@ -147,10 +156,7 @@ services: LDAP_ADMIN_GROUP_FILTER: '(memberof=cn=ADMINGROUPNAME,ou=groups,dc=DOMAIN,dc=TLD)' ALLOW_EMAIL_LOGIN: 'true' - # All users in the LDAP_GROUP_FILTER are loaded from the ldap server into contacts. - # This LDAP search happens without bind. If you want this and your LDAP needs a bind you can - # adapt this in the function getLdapContacts() in ContactsController.js (lines 82 - 107) - LDAP_GROUP_FILTER: '(memberof=cn=GROUPNAME,ou=groups,dc=DOMAIN,dc=TLD)' + # All users in the LDAP_USER_FILTER are loaded from the ldap server into contacts. LDAP_CONTACTS: 'false' # Same property, unfortunately with different names in diff --git a/ldap-overleaf-sl/sharelatex/AuthenticationManager.js b/ldap-overleaf-sl/sharelatex/AuthenticationManager.js index cbfd5a1..fdd046f 100644 --- a/ldap-overleaf-sl/sharelatex/AuthenticationManager.js +++ b/ldap-overleaf-sl/sharelatex/AuthenticationManager.js @@ -285,7 +285,6 @@ const AuthenticationManager = { const replacerUid = new RegExp("%u", "g") const replacerMail = new RegExp("%m","g") const filterstr = process.env.LDAP_USER_FILTER.replace(replacerUid, ldapEscape.filter`${uid}`).replace(replacerMail, ldapEscape.filter`${mail}`) //replace all appearances - // check bind try { if(process.env.LDAP_BINDDN){ //try to bind directly with the user trying to log in @@ -317,7 +316,7 @@ const AuthenticationManager = { firstname = searchEntries[0].givenName lastname = searchEntries[0].sn if(!process.env.LDAP_BINDDN){ //dn is already correctly assembled - userDn = searchEntries[0].dn + userDn = searchEntries[0].dn } console.log("Found user: " + mail + " Name: " + firstname + " " + lastname + " DN: " + userDn) } diff --git a/ldap-overleaf-sl/sharelatex/ContactController.js b/ldap-overleaf-sl/sharelatex/ContactController.js index b9e6d2b..4c548e6 100644 --- a/ldap-overleaf-sl/sharelatex/ContactController.js +++ b/ldap-overleaf-sl/sharelatex/ContactController.js @@ -86,11 +86,21 @@ module.exports = ContactsController = { const client = new Client({ url: process.env.LDAP_SERVER, }); + + // if we need a ldap user try to bind + if (process.env.LDAP_BIND_USER) { + try { + await client.bind(process.env.LDAP_BIND_USER, process.env.LDAP_BIND_PW); + } catch (ex) { + console.log("Could not bind LDAP reader user: " + String(ex) ) + } + } + const ldap_base = process.env.LDAP_BASE // get user data try { // if you need an client.bind do it here. - const {searchEntries,searchReferences,} = await client.search(ldap_base, {scope: 'sub',filter: process.env.LDAP_GROUP_FILTER ,}); + const {searchEntries,searchReferences,} = await client.search(ldap_base, {scope: 'sub',filter: process.env.LDAP_USER_FILTER ,}); await searchEntries; for (var i = 0; i < searchEntries.length; i++) { var entry = new Map()