Skip to main content

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 engines
  • alice 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.

  1. Enable the OpenLDAP secrets engine
  2. Configure OpenLDAP secrets engine
  3. Rotate root password
  4. Create a role
  5. 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.