»Active Directory Secrets Engine

The Active Directory (AD) secrets engine is a plugin residing here. It has two main features.

The first feature (password rotation) is where the AD secrets engine rotates AD passwords dynamically. This is designed for a high-load environment where many instances may be accessing a shared password simultaneously. With a simple set up and a simple creds API, it doesn't require instances to be manually registered in advance to gain access. As long as access has been granted to the creds path via a method like AppRole, they're available. Passwords are lazily rotated based on preset TTLs and can have a length configured to meet your needs. Additionally, passwords can be manually rotated using the rotate-role endpoint.

The second feature (service account check-out) is where a library of service accounts can be checked out by a person or by machines. Vault will automatically rotate the password each time a service account is checked in. Service accounts can be voluntarily checked in, or Vault will check them in when their lending period (or, "ttl", in Vault's language) ends.

»Password Rotation

»Customizing Password Generation

There are two ways of customizing how passwords are generated in the Active Directory secret engine:

  1. Password Policies
  2. length and formatter fields within the configuration

Utilizing password policies is the recommended path as the length and formatter fields have been deprecated in favor of password policies. The password_policy field within the configuration cannot be specified alongside either length or formatter to prevent a confusing configuration.

»A Note on Lazy Rotation

To drive home the point that passwords are rotated "lazily", consider this scenario:

  • A password is configured with a TTL of 1 hour.
  • All instances of a service using this password are off for 12 hours.
  • Then they wake up and again request the password.

In this scenario, although the password TTL was set to 1 hour, the password wouldn't be rotated for 12 hours when it was next requested. "Lazy" rotation means passwords are rotated when all of the following conditions are true:

  • They are over their TTL
  • They are requested

Therefore, the AD TTL can be considered a soft contract. It's fulfilled when the given password is next requested.

To ensure your passwords are rotated as expected, we'd recommend you configure services to request each password at least twice as often as its TTL.

»A Note on Escaping

It is up to the administrator to provide properly escaped DNs. This includes the user DN, bind DN for search, and so on.

The only DN escaping performed by this method is on usernames given at login time when they are inserted into the final bind DN, and uses escaping rules defined in RFC 4514.

Additionally, Active Directory has escaping rules that differ slightly from the RFC; in particular it requires escaping of '#' regardless of position in the DN (the RFC only requires it to be escaped when it is the first character), and '=', which the RFC indicates can be escaped with a backslash, but does not contain in its set of required escapes. If you are using Active Directory and these appear in your usernames, please ensure that they are escaped, in addition to being properly escaped in your configured DNs.

For reference, see RFC 4514 and this TechNet post on characters to escape in Active Directory.

»Quick Setup

Most secrets engines must be configured in advance before they can perform their functions. These steps are usually completed by an operator or configuration management tool.

  1. Enable the Active Directory secrets engine:

    $ vault secrets enable ad
    Success! Enabled the ad secrets engine at: ad/
    
    $ vault secrets enable adSuccess! Enabled the ad secrets engine at: ad/

    By default, the secrets engine will mount at the name of the engine. To enable the secrets engine at a different path, use the -path argument.

  2. Configure the credentials that Vault uses to communicate with Active Directory to generate passwords:

    $ vault write ad/config \
        binddn=$USERNAME \
        bindpass=$PASSWORD \
        url=ldaps://138.91.247.105 \
        userdn='dc=example,dc=com'
    
    $ vault write ad/config \    binddn=$USERNAME \    bindpass=$PASSWORD \    url=ldaps://138.91.247.105 \    userdn='dc=example,dc=com'

    The $USERNAME and $PASSWORD given must have access to modify passwords for the given account. It is possible to delegate access to change passwords for these accounts to the one Vault is in control of, and this is usually the highest-security solution.

    If you'd like to do a quick, insecure evaluation, also set insecure_tls to true. However, this is NOT RECOMMENDED in a production environment. In production, we recommend insecure_tls is false (its default) and is used with a valid certificate.

  3. Configure a role that maps a name in Vault to an account in Active Directory. When applications request passwords, password rotation settings will be managed by this role.

    $ vault write ad/roles/my-application \
        service_account_name="my-application@example.com"
    
    $ vault write ad/roles/my-application \    service_account_name="my-application@example.com"
  4. Grant "my-application" access to its creds at ad/creds/my-application using an auth method like AppRole.

»FAQ

»What if someone directly rotates an Active Directory password that Vault is managing?

If an administrator at your company rotates a password that Vault is managing, the next time an application asks Vault for that password, Vault won't know it.

To maintain that application's up-time, Vault will need to return to a state of knowing the password. Vault will generate a new password, update it, and return it to the application(s) asking for it. This all occurs automatically, without human intervention.

Thus, we wouldn't recommend that administrators directly rotate the passwords for accounts that Vault is managing. This may lead to behavior the administrator wouldn't expect, like finding very quickly afterwards that their new password has already been changed.

The password ttl on a role can be updated at any time to ensure that the responsibility of updating passwords can be left to Vault, rather than requiring manual administrator updates.

»Why does Vault return the last password in addition to the current one?

Active Directory promises eventual consistency, which means that new passwords may not be propagated to all instances immediately. To deal with this, Vault returns the current password with the last password if it's known. That way, if a new password isn't fully operational, the last password can also be used.

»Service Account Check-Out

Vault offers the ability to check service accounts in and out. This is a separate, different set of functionality from the password rotation feature above. Let's walk through how to use it, with explanation at each step.

First we'll need to enable the AD secrets engine and tell it how to talk to our AD server just as we did above.

$ vault secrets enable ad
Success! Enabled the ad secrets engine at: ad/

$ vault write ad/config \
    binddn=$USERNAME \
    bindpass=$PASSWORD \
    url=ldaps://138.91.247.105 \
    userdn='dc=example,dc=com'
$ vault secrets enable adSuccess! Enabled the ad secrets engine at: ad/
$ vault write ad/config \    binddn=$USERNAME \    bindpass=$PASSWORD \    url=ldaps://138.91.247.105 \    userdn='dc=example,dc=com'

Our next step is to designate a set of service accounts for check-out.

$ vault write ad/library/accounting-team \
    service_account_names=fizz@example.com,buzz@example.com \
    ttl=10h \
    max_ttl=20h \
    disable_check_in_enforcement=false
$ vault write ad/library/accounting-team \    service_account_names=fizz@example.com,buzz@example.com \    ttl=10h \    max_ttl=20h \    disable_check_in_enforcement=false

In this example, the service account names of fizz@example.com and buzz@example.com have already been created on the remote AD server. They've been set aside solely for Vault to handle. The ttl is how long each check-out will last before Vault checks in a service account, rotating its password during check-in. The max_ttl is the maximum amount of time it can live if it's renewed. These default to 24h. Also by default, a service account must be checked in by the same Vault entity or client token that checked it out. However, if this behavior causes problems, set disable_check_in_enforcement=true.

When a library of service accounts has been created, view their status at any time to see if they're available or checked out.

$ vault read ad/library/accounting-team/status
Key                 Value
---                 -----
buzz@example.com    map[available:true]
fizz@example.com    map[available:true]
$ vault read ad/library/accounting-team/statusKey                 Value---                 -----buzz@example.com    map[available:true]fizz@example.com    map[available:true]

To check out any service account that's available, simply execute:

$ vault write -f ad/library/accounting-team/check-out
Key                     Value
---                     -----
lease_id                ad/library/accounting-team/check-out/EpuS8cX7uEsDzOwW9kkKOyGW
lease_duration          10h
lease_renewable         true
password                ?@09AZKh03hBORZPJcTDgLfntlHqxLy29tcQjPVThzuwWAx/Twx4a2ZcRQRqrZ1w
service_account_name    fizz@example.com
$ vault write -f ad/library/accounting-team/check-outKey                     Value---                     -----lease_id                ad/library/accounting-team/check-out/EpuS8cX7uEsDzOwW9kkKOyGWlease_duration          10hlease_renewable         truepassword                ?@09AZKh03hBORZPJcTDgLfntlHqxLy29tcQjPVThzuwWAx/Twx4a2ZcRQRqrZ1wservice_account_name    fizz@example.com

If the default ttl for the check-out is higher than needed, set the check-out to last for a shorter time by using:

$ vault write ad/library/accounting-team/check-out ttl=30m
Key                     Value
---                     -----
lease_id                ad/library/accounting-team/check-out/gMonJ2jB6kYs6d3Vw37WFDCY
lease_duration          30m
lease_renewable         true
password                ?@09AZerLLuJfEMbRqP+3yfQYDSq6laP48TCJRBJaJu/kDKLsq9WxL9szVAvL/E1
service_account_name    buzz@example.com
$ vault write ad/library/accounting-team/check-out ttl=30mKey                     Value---                     -----lease_id                ad/library/accounting-team/check-out/gMonJ2jB6kYs6d3Vw37WFDCYlease_duration          30mlease_renewable         truepassword                ?@09AZerLLuJfEMbRqP+3yfQYDSq6laP48TCJRBJaJu/kDKLsq9WxL9szVAvL/E1service_account_name    buzz@example.com

This can be a nice way to say, "Although I can have a check-out for 24 hours, if I haven't checked it in after 30 minutes, I forgot or I'm a dead instance, so you can just check it back in."

If no service accounts are available for check-out, Vault will return a 400 Bad Request.

$ vault write -f ad/library/accounting-team/check-out
Error writing data to ad/library/accounting-team/check-out: Error making API request.

URL: PUT http://localhost:8200/v1/ad/library/accounting-team/check-out
Code: 400. Errors:

* No service accounts available for check-out.
$ vault write -f ad/library/accounting-team/check-outError writing data to ad/library/accounting-team/check-out: Error making API request.
URL: PUT http://localhost:8200/v1/ad/library/accounting-team/check-outCode: 400. Errors:
* No service accounts available for check-out.

To extend a check-out, renew its lease.

$ vault lease renew ad/library/accounting-team/check-out/0C2wmeaDmsToVFc0zDiX9cMq
Key                Value
---                -----
lease_id           ad/library/accounting-team/check-out/0C2wmeaDmsToVFc0zDiX9cMq
lease_duration     10h
lease_renewable    true
$ vault lease renew ad/library/accounting-team/check-out/0C2wmeaDmsToVFc0zDiX9cMqKey                Value---                -----lease_id           ad/library/accounting-team/check-out/0C2wmeaDmsToVFc0zDiX9cMqlease_duration     10hlease_renewable    true

Renewing a check-out means its current password will live longer, since passwords are rotated anytime a password is checked in either by a caller, or by Vault because the check-out ttl ends.

To check a service account back in for others to use, call:

$ vault write -f ad/library/accounting-team/check-in
Key          Value
---          -----
check_ins    [fizz@example.com]
$ vault write -f ad/library/accounting-team/check-inKey          Value---          -----check_ins    [fizz@example.com]

Most of the time this will just work, but if multiple service accounts checked out by the same caller, Vault will need to know which one(s) to check in.

$ vault write ad/library/accounting-team/check-in service_account_names=fizz@example.com
Key          Value
---          -----
check_ins    [fizz@example.com]
$ vault write ad/library/accounting-team/check-in service_account_names=fizz@example.comKey          Value---          -----check_ins    [fizz@example.com]

To perform a check-in, Vault verifies that the caller should be able to check in a given service account. To do this, Vault looks for either the same entity ID used to check out the service account, or the same client token.

If a caller is unable to check in a service account, or simply doesn't try, Vault will check it back in automatically when the ttl expires. However, if that is too long, service accounts can be forcibly checked in by a highly privileged user through:

$ vault write -f ad/library/manage/accounting-team/check-in
Key          Value
---          -----
check_ins    [fizz@example.com]
$ vault write -f ad/library/manage/accounting-team/check-inKey          Value---          -----check_ins    [fizz@example.com]

Or, alternatively, revoking the secret's lease has the same effect.

$ vault lease revoke ad/library/accounting-team/check-out/PvBVG0m7pEg2940Cb3Jw3KpJ
All revocation operations queued successfully!
$ vault lease revoke ad/library/accounting-team/check-out/PvBVG0m7pEg2940Cb3Jw3KpJAll revocation operations queued successfully!

»Troubleshooting

»Old passwords are still valid for a period of time.

During testing, we found that by default, many versions of Active Directory perpetuate old passwords for a short while. After we discovered this behavior, we found articles discussing it by searching for "AD password caching" and "OldPasswordAllowedPeriod". We also found an article from Microsoft discussing how to configure this behavior. This behavior appears to vary by AD version. We recommend you test the behavior of your particular AD server, and edit its settings to gain the desired behavior.

»I get a lot of 400 Bad Request's when trying to check out service accounts.

This will occur when there aren't enough service accounts for those requesting them. Let's suppose our "accounting-team" service accounts are the ones being requested. When Vault receives a check-out call but none are available, Vault will log at debug level: "'accounting-team' had no check-outs available". Vault will also increment a metric containing the strings "active directory", "check-out", "unavailable", and "accounting-team".

Once it's known which library needs more service accounts for checkout, fix this issue by merely creating a new service account for it to use in Active Directory, then adding it to Vault like so:

$ vault write ad/library/accounting-team \
    service_account_names=fizz@example.com,buzz@example.com,new@example.com
$ vault write ad/library/accounting-team \    service_account_names=fizz@example.com,buzz@example.com,new@example.com

In this example, fizz and buzz were pre-existing but were still included in the call because we'd like them to exist in the resulting set. The new account was appended to the end.

»Sometimes Vault gives me a password but then AD says it's not valid.

Active Directory is eventually consistent, meaning that it can take some time for word of a new password to travel across all AD instances in a cluster. In larger clusters, we have observed the password taking over 10 seconds to propagate fully. The simplest way to handle this is to simply wait and retry using the new password.

»When trying to read credentials I get 'LDAP Result Code 53 "Unwilling To Perform"'

Active Directory will only support password changes over a secure connection. Ensure that your configuration block is not using an unsecured LDAP connection.

»Learn

Refer to the Active Directory Service Account Check-out guide for a step-by-step tutorial.

»API

The Active Directory secrets engine has a full HTTP API. Please see the Active Directory secrets engine API for more details.