hashicorp / vault

A tool for secrets management, encryption as a service, and privileged access management
https://www.vaultproject.io/
Other
30.97k stars 4.19k forks source link

LDAP auth method: support client certificate authentication #6670

Open mberhault opened 5 years ago

mberhault commented 5 years ago

Is your feature request related to a problem? Please describe. Using GSuite Secure LDAP as the LDAP server for the LDAP auth method is not currently possible directly due the use of client certificates for client authentication with the LDAP server. Use of the system pool for server certificate verification may also be an issue (I have not checked).

Describe the solution you'd like The following additional fields in the /auth/ldap/config endpoint should be sufficient:

Describe alternatives you've considered It is possible to use stunnel to get around this restriction. This is the workaround included in the gsuite LDAP connection docs.

Explain any additional use-cases Unsure about client certificate authentication for other LDAP server. I suspect this may be useful elsewhere.

Additional context Username and password are not required but can still be provided. Please see the linked gsuite docs for more details about client configuration.

GSuite secure LDAP is for enterprise GSuite accounts only. I am happy to provide an environment to help develop/test this.

AeroNotix commented 5 years ago

I've been trying to get this working for the last day using Gsuite LDAP and Vault. I have not yet succeeded.

Did you manage to get this to work?

What I tried:

vault write auth/ldap/config \
  url="ldap://127.0.0.1:1636" \
  discoverdn=true \
  userdn="ou=Users,dc=ourcompanyname,dc=com"
  starttls=false \
  userattr="uid" \
  deny_null_bind=true

Stunnel conf:

debug = 7
output = /etc/stunnel/google-ldap.log
[ldap]
client = yes
accept = 127.0.0.1:1636
connect = ldap.google.com:636
cert = /etc/ssl/ldap-cert.crt
key = /etc/ssl/ldap-key.key

Outcome:

There's a small bit of information on the Google docs for this:

ldapsearch returns status 0 (success) but no users are outputs

Specifying ldapsearch option -x (use SASL authentication) with client certificates will successfully authenticate but will not list users in the domain.

Recommendation: Remove the option -x and try again.

But in order to test with ldapsearch with the version I have on my system, I must pass the -x parameter in order for ldapsearch to test due to the fact the certs Google provide you are self-signed. I will build ldapsearch locally with different compile flags enabled which could change how self-signed certs are handled.

I built vault v1.2.0 locally to insert some additional debugging and I can confirm it is attempting to use anonymous binds (go-ldap library in the vendor libs).

At a loss as to what to try next.

stephenrjohnson commented 5 years ago

@AeroNotix did you get this to work?

AeroNotix commented 5 years ago

Hi,

Kinda sorta.

I can get authentication working with vault and google groups:

This will authenticate users. (If the above doesn't work for you then I can get you my config to make it work). However, it will not allow groups to work. I've tried various configuration to get groups working but when accessing Google LDAP through Stunnel, it seems some operations don't work as expected? At least that what it seems like.

stephenrjohnson commented 5 years ago

That's a shame the whole reason we paid for google cloud identity was to get vault ldap working with groups in there.

AeroNotix commented 5 years ago

@stephenrjohnson I am not saying it is impossible - I am saying I couldn't figure out how to do it.

omar-nahhas commented 4 years ago

I managed to get this working including group belonging/mapping. These are the steps I have followed:

Setting up an LDAP application on Gsuite and giving it the following access

ldap-app

I created a set of LDAP access credentials (not sure if this is needed, but I had some issues that were fixed when doing this)

access-creds

Configured stunnel as per google documentation

Verify connectivity with ldapsearch command

This command should list you all the users on your organization:

ldapsearch -x -H ldap://127.0.0.1:1636 -D "cn=LDAPUSER-HERE" -b ou=Users,dc=example,dc=com -w LDAPPASSWORD-HERE

Note: dc=example,dc=com is for the domain example.com, replace accordingly.

Launch a local vault in dev mode:

export VAULT_DEV_ROOT_TOKEN_ID=myroot

export VAULT_LOG_LEVEL=debug

docker run --rm --name vault --net=host -d --cap-add=IPC_LOCK -e "VAULT_DEV_ROOT_TOKEN_ID=$VAULT_DEV_ROOT_TOKEN_ID" -e "VAULT_LOG_LEVEL=$VAULT_LOG_LEVEL" -e 'VAULT_DEV_LISTEN_ADDRESS=0.0.0.0:8200' "vault:1.2.2"

Note: LDAP logging error messages will be visible if you use docker logs command

Login and config local vault:

export VAULT_ADDR=http://0.0.0.0:8200 vault login --method token (user myroot here)

Configure ldap auth-backend

vault auth enable ldap

vault write auth/ldap/config url="ldap://127.0.0.1:1636" binddn="cn=LDAPUSER-HERE" bindpass="LDAPPASSWORD-HERE" userdn="ou=Users,dc=example,dc=com" userattr="uid" groupdn="ou=Groups,dc=example,dc=com" groupattr="cn" starttls=false

Note: dc=example,dc=com is for the domain example.com, replace accordingly.

Configure an LDAP group mapping

vault write auth/ldap/groups/group2 policies=default,group2

Note: This command assumes you have a group named "group2" in Gsuite

Authenticate with a user that belongs to "group2" in Gsuite

vault login -method=ldap username=<GSUITE_USER_WITHOUT @example.com> password=<GSUITE_PASSWORD>

token Note: This output assumes you have a policy named "group2" in vault

AeroNotix commented 4 years ago

@omar-nahhas does that work with users which aren't used for the binddn though? We recently finished a large portion of work to get this to actually work properly, which is now in master.

I suggest to you look deeper into your setup to ensure it works as expected. It looks like it will only work for the single user you set up in the ldap configuration.

omar-nahhas commented 4 years ago

The user used on binddn is the access credentials you set up in GSuite when you set up the LDAP application, is not a user on your Gsuite account. Is worth to mention that the creds used for ldap auth were not used on any configuration step. Also, the "token_meta_username" field (after authenticating) shows the Gsuite user name not the binddn user.

I have carried out the following tests:

I hope this makes things a bit clearer

AeroNotix commented 4 years ago

Interesting, thanks for information. Now it looks like there are multiple ways that GSuite LDAP can be used with vault. The additional pieces myself and @Gisson added, in order for it to work with unauthenticated binds and the client certificates - and apparently, your method here.

omar-nahhas commented 4 years ago

This is an extract from the debug logs (redacted) if that helps

2020-03-31T11:40:36.746Z [DEBUG] auth.ldap.auth_ldap_e72aXXXb: discovering user: userdn=ou=Users,dc=example,dc=net filter=(uid=gsuite_user)
2020-03-31T11:40:37.366Z [DEBUG] auth.ldap.auth_ldap_e72aXXXb: user binddn fetched: username=gsuite_user binddn=uid=gsuite_user,ou=Users,dc=example,dc=net
2020-03-31T11:40:38.544Z [DEBUG] auth.ldap.auth_ldap_e72aXXXb: re-bound to original binddn
2020-03-31T11:40:38.544Z [DEBUG] auth.ldap.auth_ldap_e72aXXXb: compiling group filter: group_filter=(|(memberUid={{.Username}})(member={{.UserDN}})(uniqueMember={{.UserDN}}))
2020-03-31T11:40:38.544Z [DEBUG] auth.ldap.auth_ldap_e72aXXXb: searching: groupdn=ou=Groups,dc=example,dc=net rendered_query=(|(memberUid=gsuite_user)(member=uid=gsuite_user,ou=Users,dc=example,dc=net)(uniqueMember=uid=gsuite_user,ou=Users,dc=example,dc=net))
2020-03-31T11:40:39.515Z [DEBUG] auth.ldap.auth_ldap_e72aXXXb: groups fetched from server: num_server_groups=3 server_groups=[ou=Groups,dc=example,dc=net, group2, group1]
2020-03-31T11:40:39.515Z [DEBUG] identity: refreshing external group memberships: entity_id=XXXXXXX-a92f-2247-9ee3-XXXXXXXXX group_aliases=["mount_accessor:"auth_ldap_e72aXXXb" name:"ou=Groups,dc=example,dc=net" ", "mount_accessor:"auth_ldap_e72aXXXb" name:"group2" ", "mount_accessor:"auth_ldap_e72aXXXb" name:"group1" "]
AeroNotix commented 4 years ago

Yes, I believe you that it works :)

The piece I was originally missing is that I wasn't aware you needed to use some extra credentials in order to access GSuite LDAP. It's not documented at all (unless you can point me to it?)

Therefore I added flags/features to vault in order for it to work as the GSuite documentation suggests, by using client certificates, unauthenticated binds. That work is in master, now.

omar-nahhas commented 4 years ago

You are right, that is not documented, I just happened to try both ways, thank you guys for the work on master, does it allow us to avoid using stunnel?

omar-nahhas commented 4 years ago

I have found this on Google docs, I think this is where I got the hint.

AeroNotix commented 4 years ago

Yes, you don't need to use stunnel.

prajwalkirankumar commented 4 years ago

Is there a way to replicate the same on an OpenLDAP server and use client certificates to authenticate?

stephenrjohnson commented 4 years ago

Any eta when this will be released?

mister2d commented 4 years ago

Is there a way to replicate the same on an OpenLDAP server and use client certificates to authenticate?

I'm able to have vault work successfully with OpenLDAP by setting the LDAP_TLS_VERIFY_CLIENT=try environment variable using the osixia/docker-openldap docker image.

prajwalkirankumar commented 4 years ago

Is there a way to replicate the same on an OpenLDAP server and use client certificates to authenticate?

I'm able to have vault work successfully with OpenLDAP by setting the LDAP_TLS_VERIFY_CLIENT=try environment variable using the osixia/docker-openldap docker image. @mister2d I enabled the environment variable LDAP_TLS_VERIFY_CLIENT=try with the following output on the osixia/docker-openldap :

root@ldap:/# ldapsearch  -ZZ -Y EXTERNAL -b dc=example,dc=org
SASL/EXTERNAL authentication started
SASL username: cn=admin
SASL SSF: 0
# extended LDIF
#
# LDAPv3
# base <dc=example,dc=org> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# search result
search: 3
result: 32 No such object

I have set my hostname to ldap.example.org while running the image.

This is what I get when i do the authentication with username and password (which I should get when using the certificate as well) :

root@ldap:/# ldapsearch -x -H ldaps://localhost -b dc=example,dc=org -D "cn=admin,dc=example,dc=org" -w admin
# extended LDIF
#
# LDAPv3
# base <dc=example,dc=org> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# example.org
dn: dc=example,dc=org
objectClass: top
objectClass: dcObject
objectClass: organization
o: Example Inc.
dc: example

# admin, example.org
dn: cn=admin,dc=example,dc=org
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
userPassword:: e1NTSEF9K0tqZ1hZV2NKZ2ptZnZSQ1kyMnI1SXRRREt6bWtyeTg=

# search result
search: 2
result: 0 Success

# numResponses: 3
# numEntries: 2

Is the certificate I have generated wrong? It looks like this :

Certificate: Data: Version: 3 (0x2) Serial Number: c5:86:23:9d:17:87:08:d7:4d:6c:0d:c1:ca:57:2d:b4 Signature Algorithm: sha256WithRSAEncryption Issuer: CN=Root CA Validity Not Before: Jul 11 16:39:01 2020 GMT Not After : Oct 14 16:39:01 2022 GMT Subject: CN=admin Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: //Modulus Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE X509v3 Subject Key Identifier: D2:08:40:2F:0C:E9:D2:A9:30:AA:8E:D8:FA:D1:12:DF:F1:4A:D5:E2 X509v3 Authority Key Identifier: keyid:01:CF:48:3D:BD:15:AA:81:D1:AF:5E:72:DF:34:2D:4C:7A:A8:1C:82 DirName:/CN=Root CA serial:91:42:E6:57:2A:93:47:A7

        X509v3 Extended Key Usage:
            TLS Web Client Authentication
        X509v3 Key Usage:
            Digital Signature
Signature Algorithm: sha256WithRSAEncryption
    //Key

Am i missing something here?