Closed nhoffman closed 6 years ago
I can definitely add this. Although I have a few questions/comments:
Singularity.3.4.3
?I also think your Bind DN is too strict, for example I am unable to get it to work with the LDAP we use at at my work. Maybe performing an LDAP "search & bind" for authentication would be more universal (stolen from Apache's docs):
- Generate a search filter by combining the attribute and filter provided in the
AuthLDAPURL
directive with the username passed by the HTTP client.- Search the directory using the generated filter. If the search does not return exactly one entry, deny or decline access.
- Fetch the distinguished name of the entry retrieved from the search and attempt to bind to the LDAP server using that DN and the password passed by the HTTP client. If the bind is unsuccessful, deny or decline access.
Although you can take some liberties with step 1 for naming the basedn, filter, and attribute.
Here is an example using the ldapsearch
command since I am not experienced enough to use Python and the ldap3
package:
$ # First search for DN of uid=nickjer
$ ldapsearch -x -H 'ldaps://xxxxxx:636' -b 'ou=People,ou=xxx,o=xxx' uid=nickjer
dn: uid=nickjer,ou=People,ou=xxx,o=xxx
uidNumber: 12345
uid: nickjer
cn: nickjer
loginShell: /bin/bash
...
$ # We found an entry...
$ # Now we bind to the DN found previously and read in password from STDIN
$ ldapsearch -x -H 'ldaps://xxxxxx:636' -b 'ou=People,ou=xxx,o=xxx' -D 'uid=nickjer,ou=People,ou=xxx,o=xxx' -W uid=nickjer
Enter LDAP Password:
dn: uid=nickjer,ou=People,ou=xxx,o=xxx
uidNumber: 12345
uid: nickjer
cn: nickjer
loginShell: /bin/bash
...
@nickjer - sorry for the delay in responding to this, and thanks for reviewing. I attempted to rebase your changes in the interim; hopefully I did this correctly.
LDAP_USER_DN
(my error was to assume that the CN would always be of the form "CN=" + username + "$LDAP_USER_DN"
). Now the user can specify the form of the leading elements of the CN. Using your example: uid=%s,ou=People,ou=xxx,o=xxx
. If you are willing to test this, I think that it should provide a fairly general solution without introducing additional dependencies. If need be I can provide environment variables for other parameters such as the port used by the ldap host (by default 636), but I doubt that this is frequently necessary.
Note that you can also test the LDAP auth in isolation:
cd singularity-rstudio
python3 -m venv py3-env
source py3-env/bin/activate
pip install ldap3 # may require python3-pip
export LDAP_HOST=...
export LDAP_USER_DN=...
./ldap_auth.py <user> --cert-file /path/to/cert.pem
Password:
Success
Thanks for updating it. I'll test it later this week with the LDAP server we use here and if all goes well merge it in. Although I did notice you are missing:
pip3 install ldap3
in the Singularity.3.4.3
file.
missing
pip3 install ldap3
in the Singularity.3.4.3 file.
Thanks, fixed.
Thanks @nhoffman this works great! But I do have one last suggestion. The place I work at uses valid SSL certificates so it is not necessary to supply a certificate file, as the system-wide certificate store supplied by Linux will work out of the box.
So would it be better to fallback to the default SSL certificate store if LDAP_CERT_FILE
or its corresponding argument are not defined?
Otherwise I will need to run...
export LDAP_CERT_FILE=/etc/ssl/certs/ca-certificates.crt
to use the system's certificates. I believe you can use system store if you specify None
in the Python script.
@nickjer - great suggestion - I pushed a change to my fork that I think should work. Unfortunately the instructions for LDAP auth in the readme have become somewhat verbose - I hope they make sense.
Here is a solution that I came up with to provide authentication to RStudio sessions using LDAP. I completely understand if you'd prefer not to add (or field questions about) this functionality - if not, I can most likely find a way to provide the LDAP authentication script separately, or just maintain a fork that provides it.
Thanks a lot, Noah