From ef98dd580e2023ff083846f378509395190098cc Mon Sep 17 00:00:00 2001 From: Becca Petrin Date: Wed, 16 Oct 2019 15:41:11 -0700 Subject: [PATCH] Add docs for Active Directory secret check-out (#7664) --- website/source/api/secret/ad/index.html.md | 216 +++++++++++++++++++ website/source/docs/secrets/ad/index.html.md | 216 ++++++++++++++++++- 2 files changed, 421 insertions(+), 11 deletions(-) diff --git a/website/source/api/secret/ad/index.html.md b/website/source/api/secret/ad/index.html.md index 840dd891d5..d921b9ebba 100644 --- a/website/source/api/secret/ad/index.html.md +++ b/website/source/api/secret/ad/index.html.md @@ -191,6 +191,222 @@ $ curl \ "username": "my-application" } ``` + +## Library management + +The `library` endpoint configures the sets of service accounts that Vault will offer for check-out. + +### Parameters + +* `name` (string: "", required): The name of the set of service accounts. +* `service_account_names` (string: "", or list: [] required): The names of all the service accounts that can be +checked out from this set. These service accounts must only be used by Vault, and may only be in one set. These +service accounts must already exist in Active Directory. +* `ttl` (duration: "24h", optional): The maximum amount of time a single check-out lasts before Vault +automatically checks it back in. Defaults to 24 hours. Setting it to zero reflects an unlimited lending period. +* `max_ttl` (duration: "24h", optional): The maximum amount of time a check-out last with renewal before Vault +automatically checks it back in. Defaults to 24 hours. Setting it to zero reflects an unlimited lending period. +* `disable_check_in_enforcement` (bool: false, optional): Disable enforcing that service accounts must be +checked in by the entity or client token that checked them out. Defaults to false. + +When adding a service account to the library, Vault verifies it already exists in Active Directory. + +| Method | Path | +| :------- | :---------------------- | +| `LIST` | `/ad/library` | +| `POST` | `/ad/library/:set_name` | +| `GET` | `/ad/library/:set_name` | +| `DELETE` | `/ad/library/:set_name` | + +### Sample Post Request + +``` +$ curl \ + --header "X-Vault-Token: ..." \ + --request POST \ + --data @payload.json \ + http://127.0.0.1:8200/v1/ad/library/accounting-team +``` + +### Sample Post Payload + +```json +{ + "service_account_names": ["fizz@example.com", "buzz@example.com"], + "ttl": "10h", + "max_ttl": "20h", + "disable_check_in_enforcement": false +} +``` + +### Sample Get Response + +```json +{ + "service_account_names": ["fizz@example.com", "buzz@example.com"], + "ttl": "10h", + "max_ttl": "20h", + "disable_check_in_enforcement": false +} +``` + +### Sample List Response + +Performing a `LIST` on the `/ad/library` endpoint will list the names of all the sets of service accounts Vault contains. + +```json +[ + "accounting-team" +] +``` + +## Check-out management + +These endpoints help manage check-outs. + +### Check a credential out + +Returns a `200` if a credential is available, and a `400` if no credential is available. + +* `name` (string: "", required): The name of the set of service accounts. +* `ttl` (duration: "", optional): The maximum amount of time a check-out lasts before Vault +automatically checks it back in. Setting it to zero reflects an unlimited lending period. +Defaults to the set's `ttl`. If the requested `ttl` is higher than the set's, the set's will be used. + +| Method | Path | +| :------- | :-------------------------------- | +| `POST` | `/ad/library/:set_name/check-out` | + +### Sample Post Request + +``` +$ curl \ + --header "X-Vault-Token: ..." \ + --request POST \ + --data @payload.json \ + http://127.0.0.1:8200/v1/ad/library/accounting-team/check-out +``` + +### Sample Post Payload + +```json +{ + "ttl": "1h" +} +``` + +### Sample Post Response +```json +{ + "request_id": "364a17d4-e5ab-998b-ceee-b49929229e0c", + "lease_id": "ad/library/accounting-team/check-out/aoBsaBEI4PK96VnukubvYDlZ", + "renewable": true, + "lease_duration": 36000, + "data": { + "password": "?@09QW0KZ8DSBu3deIu7XLY1NZqzwhozmMAZ6v0IcZJGOjs5GvpVMvOeW7/duls2", + "service_account_name": "fizz@example.com" + }, + "wrap_info": null, + "warnings": null, + "auth": null +} +``` + +### Check a credential in + +By default, check-in must be called by the same entity or client token used for check-out. +To disable this behavior, use the `disable_check_in_enforcement` toggle on the library set. Or, use +the `ad/library/manage/:set_name/check-in` behavior to force check-in of the account. Access to the +"manage" endpoint should only be granted to highly privileged Vault users, like Vault operators. + +If a caller attempts to check in a service account they're not authorized to check in, they will +receive an error response. If they attempt to check in a service account they _are_ authorized to +check in, but it's _already_ checked in, they will receive a successful response but the account +will not be included in the `check_ins` listed. `check_ins` shows which service accounts were checked +in _by this particular call_. + +* `name` (string: "", required): The name of the set of service accounts. +* `service_account_names` (string: "", or list: [] optional): The names of all the service accounts to be +checked in. May be omitted if only one is checked out. + +| Method | Path | +| :------- | :-------------------------------------- | +| `POST` | `/ad/library/:set_name/check-in` | +| `POST` | `/ad/library/manage/:set_name/check-in` | + +### Sample Post Request + +``` +$ curl \ + --header "X-Vault-Token: ..." \ + --request POST \ + --data @payload.json \ + http://127.0.0.1:8200/v1/ad/library/accounting-team/check-in +``` + +### Sample Post Payload + +```json +{ + "service_account_names": ["fizz@example.com"] +} +``` + +### Sample Post Response +```json +{ + "request_id": "db45c714-3f68-b748-95bc-8f7467637a52", + "lease_id": "", + "renewable": false, + "lease_duration": 0, + "data": { + "check_ins": ["fizz@example.com"] + }, + "wrap_info": null, + "warnings": null, + "auth": null +} +``` + +### Check the status of service accounts + +| Method | Path | +| :------- | :----------------------------- | +| `GET` | `/ad/library/:set_name/status` | + +### Sample Get Request + +``` +$ curl \ + --header "X-Vault-Token: ..." \ + --request GET \ + --data @payload.json \ + http://127.0.0.1:8200/v1/ad/library/accounting-team/status +``` + +### Sample Get Response +```json +{ + "request_id": "9e44c8b5-d142-5867-2a11-49f3ba71215a", + "lease_id": "", + "renewable": false, + "lease_duration": 0, + "data": { + "buzz@example.com": { + "available": true + }, + "fizz@example.com": { + "available": false, + "borrower_client_token": "4c653e473bf7e27c6759fccc3def20c44d776279", + "borrower_entity_id": "631256b1-8523-9838-5501-d0a1e2cdad9c" + } + }, + "wrap_info": null, + "warnings": null, + "auth": null +} +``` + ## Rotate Root Credentials Rotate the `bindpass` to a new one known only to Vault. diff --git a/website/source/docs/secrets/ad/index.html.md b/website/source/docs/secrets/ad/index.html.md index ea7df6ca74..409adfea74 100644 --- a/website/source/docs/secrets/ad/index.html.md +++ b/website/source/docs/secrets/ad/index.html.md @@ -11,18 +11,24 @@ description: |- # 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 AD secrets engine rotates AD passwords dynamically, -and is designed for a high-load environment where many instances may be accessing +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](https://www.vaultproject.io/api/auth/approle/index.html), they're available. +[AppRole](https://www.vaultproject.io/api/auth/approle/index.html), they're available. Passwords are +lazily rotated based on preset TTLs and can have a length configured to meet your needs. -Passwords are lazily rotated based on preset TTLs and can have a length configured to meet -your needs. +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. -## A Note on Lazy Rotation +## Password Rotation + +### A Note on Lazy Rotation To drive home the point that passwords are rotated "lazily", consider this scenario: @@ -41,7 +47,7 @@ Therefore, the AD TTL can be considered a soft contract. It's fulfilled when the 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 +### 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. @@ -62,7 +68,7 @@ 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 +### 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 @@ -110,9 +116,9 @@ this role. 4. Grant "my-application" access to its creds at `ad/creds/my-application` using an auth method like [AppRole](https://www.vaultproject.io/api/auth/approle/index.html). -## FAQ +### FAQ -### What if someone directly rotates an Active Directory password that Vault is managing? +#### 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 @@ -132,7 +138,7 @@ 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? +#### 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 @@ -140,6 +146,194 @@ 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. + +```text +$ 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. + +```text +$ 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. + +```text +$ 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: + +```text +$ 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: + +```text +$ 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. + +```text +$ 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. +``` + +To extend a check-out, renew its lease. + +```text +$ 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: + +```text +$ 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. + +```text +$ 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: + +```text +$ 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. + +```text +$ 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: + +```text +$ 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. + ## API The Active Directory secrets engine has a full HTTP API. Please see the