Introduction
The ldap authentication method may be used with LDAP (Identity Provider) servers for username and password type credentials. This allows Vault to be integrated into environments with existing use of LDAP without duplicating user configurations in multiple places. The mapping of groups and users in LDAP to Vault policies is managed by using the two related:
We'll demonstrate example scenarios on vault 1.10.3 with LDAP auth method that's restricting user access on the basis of the userfilter parameter that was introduced in vault 1.9.x.
Scenario's
- A common challenge is restricting user abilities to log into Vault - which will be exemplify in two parts:
- Limiting users from a particular LDAP group on the basis of
userfilterparameter. - Limiting users from the same LDAP group using the
userfilterparameter.
- Limiting users from a particular LDAP group on the basis of
- Mapping Groups and Users in LDAP to Vault specific policies by using the paths:
auth/ldap/users/...andauth/ldaps/groups/....
Example Setup & Configuration
LDAP
An OpenLDAP docker image provided by osixia/OpenLDAP as well vault 1.10.3 is used in this demo.
# Set 'osixia/openldap:1.3.0' for specific versions.
docker run -p 389:389 --detach osixia/openldap ;
docker ps | grep ldap ; # find the current running ldap CONTAINER_ID
docker exec -it 84e11491b255 /bin/bash ; # attach to container using its bash prompt
Within docker container process attached to:
# // on LDAP docker:
printf "%s" """\
dn: ou=groups,dc=example,dc=org
objectClass: organizationalunit
objectClass: top
ou: groups
description: groups of users
dn: ou=users,dc=example,dc=org
objectClass: organizationalunit
objectClass: top
ou: users
description: users
dn: cn=dev,ou=groups,dc=example,dc=org
objectClass: groupofnames
objectClass: top
description: testing group for dev
cn: dev
member: cn=laura,ou=users,dc=example,dc=org
member: cn=laxman,ou=users,dc=example,dc=org
member: cn=lucky,ou=users,dc=example,dc=org
dn: cn=prod,ou=groups,dc=example,dc=org
objectClass: groupofnames
objectClass: top
description: testing group for prod
cn: prod
member: cn=ashish,ou=users,dc=example,dc=org
member: cn=ankit,ou=users,dc=example,dc=org
member: cn=ashu,ou=users,dc=example,dc=org
dn: cn=laura,ou=users,dc=example,dc=org
objectClass: person
objectClass: top
cn: laura
sn: laura
memberOf: cn=dev,ou=groups,dc=example,dc=org
userPassword: laura
dn: cn=laxman,ou=users,dc=example,dc=org
objectClass: person
objectClass: top
cn: laxman
sn: laxman
memberOf: cn=dev,ou=groups,dc=example,dc=org
userPassword: laxman
dn: cn=lucky,ou=users,dc=example,dc=org
objectClass: person
objectClass: top
cn: lucky
sn: lucky
memberOf: cn=dev,ou=groups,dc=example,dc=org
userPassword: lucky
dn: cn=ashish,ou=users,dc=example,dc=org
objectClass: person
objectClass: top
cn: ashish
sn: ashish
memberOf: cn=prod,ou=groups,dc=example,dc=org
userPassword: ashish
dn: cn=ankit,ou=users,dc=example,dc=org
objectClass: person
objectClass: top
cn: ankit
sn: ankit
memberOf: cn=prod,ou=groups,dc=example,dc=org
userPassword: ankit
dn: cn=ashu,ou=users,dc=example,dc=org
objectClass: person
objectClass: top
cn: ashu
sn: ashu
memberOf: cn=prod,ou=groups,dc=example,dc=org
userPassword: ashu
""" > ldap_seed.ldif ; # // an example ldif with changes to apply
ldapadd -x -W -D "cn=admin,dc=example,dc=org" -f ldap_seed.ldif
# Enter LDAP Password:
# adding new entry "ou=groups,dc=example,dc=org"
# adding new entry "ou=users,dc=example,dc=org"
# adding new entry "cn=dev,ou=groups,dc=example,dc=org"
# adding new entry "cn=prod,ou=groups,dc=example,dc=org"
# adding new entry "cn=laura,ou=users,dc=example,dc=org"
# adding new entry "cn=laxman,ou=users,dc=example,dc=org"
# adding new entry "cn=lucky,ou=users,dc=example,dc=org"
# adding new entry "cn=ashish,ou=users,dc=example,dc=org"
# adding new entry "cn=ankit,ou=users,dc=example,dc=org"
# adding new entry "cn=ashu,ou=users,dc=example,dc=org"
exit ; # // Exit Container
The LDIF file (ldap_seed.ldif) results two branches of groups & users within the suffix example.org within two groups named dev & prod inside the branch groups and assigned to their respective users. So the users: laura, laxman, lucky are a member of dev group while the users ashish, ankit, ashu are a member of the prod group which are created in users branch.
Vault
# // on Vault host
vault auth enable ldap ;
# Success! Enabled ldap auth method at: ldap/
LDAP_ADDR='ldap://192.168.64.6:389' ;
vault write auth/ldap/config url="${LDAP_ADDR}" \
bindpass="admin" \
starttls=false \
userdn="ou=users,dc=example,dc=org" \
groupdn="ou=groups,dc=example,dc=org" \
binddn="cn=admin,dc=example,dc=org" \
userfilter="(&(objectClass=Person)({{.UserAttr}}={{.Username}})(memberOf=cn=prod,ou=groups,dc=example,dc=org))" ;
# Success! Data written to: auth/ldap/config
# // attempt login with LDIF defined credentials ('laura')
vault login -method=ldap username=ashish ;
# Password (will be hidden):
# Success! You are now authenticated. The token information displayed below
# ...
# token_meta_username ashish
We'll proceed to configure users from prod group to be permitted to login while all other users from will encounter an expected login error.
vault write auth/ldap/config url="${LDAP_ADDR}" \
bindpass="admin" \
starttls=false \
userdn="ou=users,dc=example,dc=org" \
groupdn="ou=groups,dc=example,dc=org" \
binddn="cn=admin,dc=example,dc=org" \
userfilter="(&(objectClass=Person)({{.UserAttr}}={{.Username}})(memberOf=cn=prod,ou=groups,dc=example,dc=org))" ;
# // user 'ashish' is a memberOf prod group
vault login -method=ldap username=ashish ;
# Password (will be hidden):
# Success! You are now authenticated. The token information displayed below
# ...
# token_duration 768h
# token_renewable true
# token_policies ["default"]
# identity_policies []
# policies ["default"]
# token_meta_username ashish
# // user 'laura' is not a memberOf prod group
vault login -method=ldap username=laura ;
# Password (will be hidden):
# Error authenticating: Error making API request.
# URL: PUT http://192.168.64.6:8200/v1/auth/ldap/login/laura
# Code: 400. Errors:
# * ldap operation failed: failed to bind as user
Here's another userfilter that restricts a specific user from the predefined prod group and whose name must start with: as*:
vault write auth/ldap/config url="${LDAP_ADDR}" \
bindpass="admin" \
starttls=false \
userdn="ou=users,dc=example,dc=org" \
groupdn="ou=groups,dc=example,dc=org" \
binddn="cn=admin,dc=example,dc=org" \
userfilter="(&(objectClass=Person)({{.UserAttr}}={{.Username}})(memberOf=cn=prod,ou=groups,dc=example,dc=org)(cn=as*))" ;
vault login -method=ldap username=ashish ; #user ashish is a memberOf prod group
# Password (will be hidden):
# Success! You are now authenticated. The token information displayed below
# ...
# token_duration 768h
# token_renewable true
# token_policies ["default"]
# identity_policies []
# policies ["default"]
# token_meta_username ashish
vault login -method=ldap username=ankit ; #user ankit is a memberOf prod group but start from "an" instead of "as"
# Password (will be hidden):
# Error authenticating: Error making API request.
# URL: PUT http://192.168.64.6:8200/v1/auth/ldap/login/ankit
# Code: 400. Errors:
# * ldap operation failed: failed to bind as user
Vault Policy Mapping
Policy mapping can link LDAP users/groups to what resources they can access.
If there are requirement to apply a policy to a specific LDAP group then the same named group must also exist in Vault.
This demonstration has had two groups dev & prod defined on the LDAP server and if Vault administrator privileges were to be granted to the prod group then the existing policy that's related ( admin_root) would need to mapped - like:
vault write auth/ldap/groups/prod policies=admin_auth;
# Success! Data written to: auth/ldap/groups/prod
Additional or specific groups can also be added to for each LDAP user. Note that the parameter policies may also be specified for individual LDAP users as well.
vault write auth/ldap/groups/test policies=list_policy
vault write auth/ldap/users/ankit groups=test policies=admin_auth
The above example adds the LDAP user ankit to the test group (non-LDAP), which maps to the list_policy of Vault. The user ankit itself is associated with the Vault admin_auth policy. Re-login with Vault LDAP auth in order to verify the policy membership that's expected after the prior change was applied:
# // user 'ankit' is a memberOf prod group in LDAP server
vault login -method=ldap username=ankit
# ...
# token_policies ["admin_auth" "default" "list_policy"]
# identity_policies []
# policies ["admin_auth" "default" "list_policy"]
# token_meta_username ankit
Reference Links: