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
userfilter
parameter. - Limiting users from the same LDAP group using the
userfilter
parameter.
- 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: