359 lines
15 KiB
Plaintext
359 lines
15 KiB
Plaintext
---
|
|
layout: docs
|
|
page_title: Active Directory - Secrets Engines
|
|
description: >-
|
|
The Active Directory secrets engine allowing Vault to generate dynamic credentials.
|
|
---
|
|
|
|
# Active Directory Secrets Engine
|
|
|
|
The Active Directory (AD) secrets engine is a plugin residing [here](https://github.com/hashicorp/vault-plugin-secrets-active-directory).
|
|
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](/api-docs/auth/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](/api-docs/secret/ad#rotate-role-credentials) 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](/docs/concepts/password-policies)
|
|
2. `length` and `formatter` fields within the [configuration](/api-docs/secret/ad#password-parameters)
|
|
|
|
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](https://www.ietf.org/rfc/rfc4514.txt) and this
|
|
[TechNet post on characters to escape in Active
|
|
Directory](http://social.technet.microsoft.com/wiki/contents/articles/5312.active-directory-characters-to-escape.aspx).
|
|
|
|
### 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:
|
|
|
|
```text
|
|
$ vault secrets enable ad
|
|
Success! 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:
|
|
|
|
```text
|
|
$ 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.
|
|
|
|
```text
|
|
$ 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](/api-docs/auth/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.
|
|
|
|
```shell-session
|
|
$ 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'
|
|
```
|
|
|
|
Our next step is to designate a set of service accounts for check-out.
|
|
|
|
```shell-session
|
|
$ 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.
|
|
|
|
```shell-session
|
|
$ vault read ad/library/accounting-team/status
|
|
Key Value
|
|
--- -----
|
|
buzz@example.com map[available:true]
|
|
fizz@example.com map[available:true]
|
|
```
|
|
|
|
To check out any service account that's available, simply execute:
|
|
|
|
```shell-session
|
|
$ 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
|
|
```
|
|
|
|
If the default `ttl` for the check-out is higher than needed, set the check-out to last
|
|
for a shorter time by using:
|
|
|
|
```shell-session
|
|
$ 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
|
|
```
|
|
|
|
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.
|
|
|
|
```shell-session
|
|
$ vault write -f ad/library/accounting-team/check-out
|
|
Error writing data to ad/library/accounting-team/check-out: Error making API request.
|
|
|
|
URL: POST http://localhost:8200/v1/ad/library/accounting-team/check-out
|
|
Code: 400. Errors:
|
|
|
|
* No service accounts available for check-out.
|
|
```
|
|
|
|
To extend a check-out, renew its lease.
|
|
|
|
```shell-session
|
|
$ 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
|
|
```
|
|
|
|
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:
|
|
|
|
```shell-session
|
|
$ vault write -f ad/library/accounting-team/check-in
|
|
Key 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.
|
|
|
|
```shell-session
|
|
$ vault write ad/library/accounting-team/check-in service_account_names=fizz@example.com
|
|
Key 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](https://learn.hashicorp.com/vault/identity-access-management/iam-identity)
|
|
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:
|
|
|
|
```shell-session
|
|
$ vault write -f ad/library/manage/accounting-team/check-in
|
|
Key Value
|
|
--- -----
|
|
check_ins [fizz@example.com]
|
|
```
|
|
|
|
Or, alternatively, revoking the secret's lease has the same effect.
|
|
|
|
```shell-session
|
|
$ vault lease revoke ad/library/accounting-team/check-out/PvBVG0m7pEg2940Cb3Jw3KpJ
|
|
All 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](https://support.microsoft.com/en-us/help/906305/new-setting-modifies-ntlm-network-authentication-behavior)
|
|
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:
|
|
|
|
```shell-session
|
|
$ 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.
|
|
|
|
## Tutorial
|
|
|
|
Refer to the [Active Directory Service Account Check-out](https://learn.hashicorp.com/vault/secrets-management/ad-secrets) tutorial to learn how to enable a team to share a select set of service accounts.
|
|
|
|
## API
|
|
|
|
The Active Directory secrets engine has a full HTTP API. Please see the
|
|
[Active Directory secrets engine API](/api-docs/secret/ad) for more
|
|
details.
|