OpenLDAP Secrets Engine
LDAP is a critical protocol commonly in use with UNIX and Linux applications, with OpenLDAP being the most popular implementation.
The OpenLDAP secrets engine provides a centralized workflow for efficiently managing existing LDAP entry passwords, empowering users with access to their own credentials, and the benefits of automatic password rotation.
Challenge
The hardest problems encountered with administration of OpenLDAP and its associated credentials can be summarized as follows.
- The volume of user entries in an OpenLDAP directory can be difficult to efficiently manage
- Access to OpenLDAP is required to empower users with credential management capabilities
- There is a lack of available solutions aimed at automatically rotating OpenLDAP credentials, requiring the use of in house solutions
Solution
Use the OpenLDAP secrets engine with Vault to provide a variety of authentication methods to users for accessing their own LDAP credentials.
Users can be empowered to manage their own LDAP entries, and their passwords can be configured to be automatically rotated based on a time to live value configured by the administrator.
The following diagram illustrates this credential management workflow.
By making the passwords as short-lived as possible, you reduce the chance that they might be compromised. If an credential is compromised, it can be revoked revoked and rotated rather than changing a global set of credentials.
Personas
The end-to-end scenario described in this tutorial involves two personas.
admin
a Vault administrator with privileged permissions to configure secrets enginesalice
a user with existing OpenLDAP credential who needs to access a Secure Shell Daemon (sshd) server with this credential password
Prerequisites
To perform the tasks described in this tutorial, you need to have the following items.
- A Vault version 1.4 or later environment; refer to the Getting Started tutorial to install Vault. Make sure that your Vault server has been initialized and unsealed.
- An OpenLDAP environment you can connect Vault to, or Docker to run an OpenLDAP container.
- Local installation of the
ldapadd
binary; if your operating system distribution does not provide it by default, you can typically find it in a LDAP utilities package (such as ldap-utils on Debian based Linux) or by installing OpenLDAP locally. - Local installation of the curl binary; if you want to follow the HTTP API examples, please be sure to install
curl
. - Local installation of the jq binary; this is optional but makes reading JSON output from the HTTP API operations more friendly to humans.
NOTE: An interactive tutorial is also available if you do not have a Vault environment to perform the steps described in this tutorial. Click the Show Terminal button to start.
Scenario Introduction
In this scenario, you are going to assume two personas, first as admin to configure the OpenLDAP secrets engine, and then as alice to request a new OpenLDAP credential.
- Enable the OpenLDAP secrets engine
- Configure OpenLDAP secrets engine
- Rotate root password
- Create a role
- Request OpenLDAP credentials
Step 1 through 4 need to be performed by the admin persona. Step 5 describes the commands that the user alice performs to get an OpenLDAP credential from Vault.
Step 1: Enable the OpenLDAP secrets engine
(Persona: admin)
The first step is to enable an openldap
secrets engine at the desired path.
1.Execute the following command to enable the openldap
secrets engine at the path openldap/
.
vault secrets enable openldap
If you want to enable the secrets engine at a different path, use the -path
parameter to specify your desired path. Otherwise, the secrets engine gets enabled at a path named after its type. Since the type is openldap
in this example, its path becomes openldap
in absence of any -path
parameter.
Successful output:
Success! Enabled the openldap secrets engine at: openldap/
2. Successful operations against this endpoint are expected to result in no body output. You can confirm that the secrets engine is enabled with a request to the /sys/mounts API.
curl \
--silent \
--header "X-Vault-Token: $VAULT_TOKEN" \
$VAULT_ADDR/v1/sys/mounts \
| jq '.data."openldap/"'
If the secrets engine is enabled, you should observe output like this example.
{
"accessor": "openldap_18a28534",
"config": {
"default_lease_ttl": 0,
"force_no_cache": false,
"max_lease_ttl": 0
},
"description": "",
"external_entropy_access": false,
"local": false,
"options": null,
"seal_wrap": false,
"type": "openldap",
"uuid": "e3ed93a0-f6ad-c100-03c0-745f0f5b41f4"
}
If the output is empty instead, then the openldap secrets engine is not enabled and you should check your API call and try again.
Step 2: Configure OpenLDAP secrets engine
(Persona: admin)
The OpenLDAP secrets engine needs to be configured with valid credentials. It is common to give Vault the superuser credentials and let Vault manage the auditing and lifecycle credentials; it's much better than having one person manage the credentials.
Start an OpenLDAP Server
For the purpose of this tutorial, let's run a community based OpenLDAP Docker image in a container.
NOTE: If you already have an OpenLDAP server that you can connect to, you can ignore this step and modify your values in the examples accordingly.
1.Use docker run
to run an openldap
container; options are detailed after the example.
docker run \
--name vault-openldap \
--network=vaultonenode_default \
--env LDAP_ORGANISATION="learn" \
--env LDAP_DOMAIN="learn.example" \
--env LDAP_ADMIN_PASSWORD="2LearnVault" \
-p 389:389 \
-p 636:636 \
--detach \
--rm \
osixia/openldap:latest
The options we use in the example are as follows.
- Name the container vault-openldap
- Set LDAP organization value to learn
- Set LDAP domain to learn.example
- Set LDAP administrator password to 2LearnVault
- Listen on default LDAP and LDAPS ports TCP/389 and 636
- Expose these ports to the Docker host
- Detach the container from terminal
- Remove the container when it exits
2. After starting the container, you can verify that it is running.
docker ps -f name=vault-openldap --format "table {{.Names}}\t{{.Status}}"
Configure OpenLDAP with example data
3. Login to the Docker Container
docker exec -it CONTAINERNAME /bin/bash
With the OpenLDAP container now available, we can add some initial configuration including groups and the example user, alice.
4. We use the cat
utility here to quickly write file examples for this tutorial in the present working directory. If you wish to edit and write files another way, then remove the first and last lines of the example in each case to use it verbatim.
Example: learn-vault-example.ldif
cat > learn-vault-example.ldif <<EOF
dn: ou=groups,dc=learn,dc=example
objectClass: organizationalunit
objectClass: top
ou: groups
description: groups of users
dn: ou=users,dc=learn,dc=example
objectClass: organizationalunit
objectClass: top
ou: users
description: users
dn: cn=dev,ou=groups,dc=learn,dc=example
objectClass: groupofnames
objectClass: top
description: testing group for dev
cn: dev
member: cn=alice,ou=users,dc=learn,dc=example
dn: cn=alice,ou=users,dc=learn,dc=example
objectClass: person
objectClass: top
cn: learn
sn: learn
memberOf: cn=dev,ou=groups,dc=learn,dc=example
userPassword: 1LearnedVault
EOF
5. Use the ldapadd
utility to add this configuration.
ldapadd -cxWD "cn=admin,dc=learn,dc=example" -f learn-vault-example.ldif
When prompted for password, enter 2LearnVault
which was the value of LDAP_ADMIN_PASSWORD
when starting the docker container. If using an existing OpenLDAP, enter the known administrator password.
Successful output:
adding new entry "ou=groups,dc=learn,dc=example"
adding new entry "ou=users,dc=learn,dc=example"
adding new entry "cn=dev,ou=groups,dc=learn,dc=example"
adding new entry "cn=alice,ou=users,dc=learn,dc=example"
Now you are ready to configure the OpenLDAP secrets engine in Vault.
6. Exit from the Docker Container by typing exit
command
7. The below command will provide you the IP Address of the Ldap Server
docker inspect -f '{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)
8. The following command configures the OpenLDAP secrets engine using the openldap
plugin to communicate with our Docker based OpenLDAP container.
vault write openldap/config \
binddn=cn=admin,dc=learn,dc=example \
bindpass=2LearnVault \
url=ldap://IPADDRESSOFLDAPSERVER
If your OpenLDAP connection URL is different from this example, be sure to replace the example values with correct binddn
, bindpass
, and url
values that match your environment. This user should have the necessary privileges to search and change entry passwords in OpenLDAP.
Successful output:
Success! Data written to: openldap/config
NOTE: While our previous example uses a default OpenLDAP administrator user, it is recommended that a dedicated entry management account be used specifically for Vault in production environments.
Step 3: Create a role
(Persona: admin)
1.Now that you have successfully configured the OpenLDAP secrets engine, the next step is to create a role that maps a name in Vault to an entry in OpenLDAP.
Example:
vault write openldap/static-role/learn \
dn='cn=alice,ou=users,dc=learn,dc=example' \
username='alice' \
rotation_period="24h"
Successfully adding the role results in output like this:
Success! Data written to: openldap/static-role/learn
You can now move on to requesting an OpenLDAP credential from the learn role.
Step 4: Request OpenLDAP credentials
(Persona: alice)
1.Our example user alice has previously authenticated to Vault and her token has a policy attached which provides the capability needed to request a new OpenLDAP credential from the learn role.
# Request OpenLDAP credential from the learn role
path "openldap/static-cred/learn" {
capabilities = [ "read" ]
}
Alice's token id value should be used as the value of VAULT_TOKEN
in the following API steps performed as alice.
2. Finally, using an example application token as previously described, you can use this command to read from the role to request a credential.
vault read openldap/static-cred/learn
Successful output:
Key Value--- -----dn cn=alice,ou=users,dc=learn,dc=examplelast_vault_rotation 2020-03-05T17:06:52.345894964Zpassword pIBLIY9kc2yoiqEFbyibMOlyW0cQCPcKoZ3AC3Nzb8l1fS9Yze7eWtLgMKQqyRg6rotation_period 24httl 23h59m51susername alice
3. Generate another set of credentials from the learn
role and save the password to a variable named LDAP_PASSWORD
.
LDAP_PASSWORD=$(vault read --format=json openldap/static-cred/learn | jq -r ".data.password")
4. Dispaly the LDAP_PASSWORD using echo command
echo $LDAP_PASSWORD
5. Login to the Docker Container
docker exec -it CONTAINERNAME /bin/bash
6. Set the LDAP_PASSWORD variables for searching using ldapsearch tool.
( fill the LDAP_PASSWORD from the above echo output.
export LDAP_PASSOWRD=
7. Perform an LDAP search with the generated dn
and password
.
ldapsearch -b "cn=alice,ou=users,dc=learn,dc=example" \
-D 'cn=alice,ou=users,dc=learn,dc=example' \
-w $LDAP_PASSWORD
The results display the password for this user.