Vault
Active Directory service account check-out
Vault 0.10.2 introduced the Active Directory (AD) secrets engine which was designed to rotate the shared AD passwords dynamically. This allowed companies to reduce the risk of damage from a password leak.
Note
This tutorial focuses on the new Service Account Check-out feature introduced in Vault 1.3.
Challenge
A service account is a user account that is created explicitly to provide a security context for services running on Windows Server operating systems. Often, an organization has a limited number of service accounts based on their Client Access License (CAL) which they share among the team. As a result, credential rotation is a cumbersome process and it's difficult to audit who took what actions with those shared credentials.
Solution
Use the AD service account check-in/check-out feature of the AD secrets engine to allow a team to share a select set of service accounts. To use the shared service accounts, the requester first checks out the account. When done using the account, they simply check the service account back in for others to use. Whenever a service account is checked back in, Vault rotates its password.
This minimizes the number of accounts consumed and ensures that as an organization grows, they do not expand beyond the limit of their Client Access License. At the same time, the credentials are valid per check-out and user actions can be tied to whoever had a service account checked out. This lowers the operational burden and helps an organization meet its security requirements around audibility.
Personas
The end-to-end scenario described in this tutorial involves two personas:
admin
with privileged permissions to configure secrets enginesclient
requests to check-out service account(s)
Prerequisites
This tutorial assumes that you have the following environments:
- Microsoft Active Directory (AD) server with service accounts
- Vault version 1.3.0 or later
Policy requirements
Note
For the purpose of this tutorial, you can use the root
token to work
with Vault. However, it is recommended that root tokens are only used for just
enough initial setup or in emergencies. As a best practice, use tokens with an
appropriate set of policies based on your role in the organization.
To perform all tasks demonstrated in this tutorial, your policy must include the following permissions:
# Mount secrets engines
path "sys/mounts/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
# Configure the ad secrets engine and create roles
path "ad/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
# Write ACL policies
path "sys/policies/acl/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
# Manage tokens for verification
path "auth/token/create" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
# Manage the leases
path "sys/leases/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
If you are not familiar with policies, complete the policies tutorial.
Scenario introduction
You are going to perform the following operations:
- Enable and configure Active Directory secrets engine
- Create a library
- Create a client policy
- Check-out service accounts
Also, this tutorial covers the following:
Step 1: Enable and configure Active Directory secrets engine
Begin by establishing a connection between Vault and Active Directory, which involves creating a user within Active Directory for Vault.
In the Windows Server, click on Search and type dsa.msc
to open Active
Directory Users and Computers.
- Open your ROOT-DOMAIN and add a new user for
vault-admin
under the Users folder. - Left click on Users, and select Delegate Control.
- Type user name, click check name and next.
- Click Create a custom task.
- Click Only the following ... and select Users (the last item).
- Click General and Property specific.
- Click Change Password and Reset Password (near start of the list) and Read userAccountControl and Write userAccountControl (near the end of the list).
Now enable and configure the AD secrets engine at a desired path.
Execute the following command to enable the AD secrets engine at
ad/
path.$ vault secrets enable ad Success! Enabled the ad secrets engine at: ad/
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 isad
in this example, its path becomesad
in absence of-path
parameter.To configure the AD secrets engine, you need to set the following parameters.
parameter Description binddn
Distinguished name of object to bind when performing user and group search bindpass
Password to use along with binddn
when performing user searchurl
The AD sever URL userdn
Base DN under which to perform user search This is a subset of available parameters. Refer to the API documentation for the full list of configuration parameters.
Export the username as a
USERNAME
environment variable.$ export USERNAME=<YOUR-VAULT-USERNAME-IN-AD@YOUR-AD-ROOT-DOMAIN>
Export the password as a
PASSWORD
environment variable.$ export PASSWORD=<YOUR-VAULT-USER-IN-AD-PASSWORD>
Execute the
vault write ad/config
command with correct AD server configuration information.$ vault write ad/config binddn=$USERNAME \ bindpass=$PASSWORD \ url=ldaps://127.0.0.11 \ userdn='dc=example,dc=com' \ insecure_tls=true
Output:
Success! Data written to: ad/config
Note
The insecure_tls
parameter can be used to skip the SSL
certificate validation when you are testing this feature against a development
server. However, this is NOT a recommended practice in a production
environment.
Step 2: Create a library
(Persona: admin)
A library
is a set of service accounts that you want Vault to manage for
check-out.
To demonstrate this feature, assume that you have shared service accounts,
testMSA@example.com
and MSA4SQL@example.com
.
In this step, you are going to create a library named, accounting-team
where testMSA@example.com
and MSA4SQL@example.com
are the shared
accounts that can be checked out for use.
You can control how long a single check-out can last by setting the ttl
and
max_ttl
associated with the library. Vault will automatically check-in the
service account once its TTL expires and not renewed, or its max TTL was
reached and no longer renewable.
Note
You can set the ttl
and max_ttl
value to 0
. In that case, the
system default will be the TTL (which is 32 days by default).
Execute the following command to create a library named
accounting-team
with attl
set to 24 hours andmax_ttl
set to 5 days.$ vault write ad/library/accounting-team \ service_account_names="testMSA@example.com,MSA4SQL@example.com" \ ttl=24h \ max_ttl=120h Success! Data written to: ad/library/accounting-team
Execute the following command to list the existing libraries.
$ vault list ad/library Keys ---- accounting-team
Execute the following command to view the status of the accounts in the library.
$ vault read ad/library/accounting-team/status Key Value --- ----- MSA4SQL@example.com map[available:true] testMSA@example.com map[available:true]
Both service accounts are available for check-out.
Step 3: Create a client policy
(Persona: admin)
In order for the client to check-out the service accounts belong to the
accounting-team
library, the policy must include the following rules.
acct-team.hcl
:
# To check-out a service account which is a part of accounting-team library
path "ad/library/accounting-team/check-out" {
capabilities = [ "update" ]
}
# To allow the extension of TTL
path "sys/leases/renew" {
capabilities = [ "update" ]
}
# To check back in a service account
path "ad/library/accounting-team/check-in" {
capabilities = [ "update" ]
}
# If you want to allow the client to see the library status
path "ad/library/accounting-team/status" {
capabilities = [ "read" ]
}
Execute the following command to create a policy named, acct-team
.
$ vault policy write acct-team acct-team.hcl
Success! Uploaded policy: acct-team
Step 4: Check-out service accounts
(Persona: client)
Once the AD secrets engine is configured by the Vault admin, a client (may be a human user, application or system) can request to check-out a service account.
First, generate a client token with
acct-team
policy attached and store it in aVAULT_TOKEN
environment variable.Example:
$ vault token create -policy=acct-team Key Value --- ----- token s.1jJFckALyEShvimC7kxizd3Y token_accessor JiFqVsH7PKfGeIX8McFqwGgO token_duration 768h token_renewable true token_policies ["acct-team" "default"] identity_policies [] policies ["acct-team" "default"] # Store the generated client token as VAULT_TOKEN env var $ export VAULT_TOKEN=s.1jJFckALyEShvimC7kxizd3Y
Check-out a service account managed by the
accounting-team
library.$ vault write -f ad/library/accounting-team/check-out Key Value --- ----- lease_id ad/library/accounting-team/check-out/SVNimFfpLKwWThHq1eGBG5mj lease_duration 768h lease_renewable true password ?@09AZFIwvunQIThl0RTMI1o3gTGZ7hinlQuUaBJMIPTURin3Ub0n9zkRSgLr0vM service_account_name testMSA@example.com
Now, the
testMSA@example.com
account has been checked out and its password has been dynamically generated by Vault.Note
If no service accounts are available for check-out, Vault will return a
400 Bad Request
. This may be an indication that an organization may need to add more service accounts to the library or reduce the number of requestors trying to use them at the same time.View the library status.
$ vault read ad/library/accounting-team/status Key Value --- ----- MSA4SQL@example.com map[available:true] testMSA@example.com map[available:false borrower_client_token:49aef0b628c06d77d4237da3cedc6ec29e0e51ae]
It is shown that
testMSA@example.com
is now checked out.When you are done, check back in the service account by executing the following command.
$ vault write -f ad/library/accounting-team/check-in Key Value --- ----- check_ins [testMSA@example.com]
NOTE: If you have more than one account checked out, you must pass
the service_account_names
parameter to specify which account(s) to check in.
Try
If you check-out the testMSA@example.com
again, it returns a different
password because Vault automatically rotates the password.
Step 5: Understanding the TTL
(Persona: admin)
In this step, you are going to test and see how the TTL works for those checked out service accounts.
For testing, update the ttl
and max_ttl
set on the accounting-team
library
to be 20 seconds and 40 seconds respectively. Observe what happens when the TTL
expires.
Log back in with your admin token.
Execute the following command to update the
ttl
andmax_ttl
.$ vault write ad/library/accounting-team \ service_account_names="testMSA@example.com,MSA4SQL@example.com" \ ttl=20 \ max_ttl=40
Check-out a service account, wait for 20 seconds and then try renewing the lease.
$ vault write -f ad/library/accounting-team/check-out Key Value --- ----- lease_id ad/library/accounting-team/check-out/cp4X5rcwQrp3w8f4lMj2jhTo lease_duration 20s lease_renewable true password ?@09AZBbCyiLZtx+DPKYducATJ3HH/kZe2BuzCIC+oDpPpoD71PQW9L5iLaLahah service_account_name testMSA@example.com # Wait for 20 seconds # Try renewing the TTL using the lease_id $ vault lease renew ad/library/accounting-team/check-out/cp4X5rcwQrp3w8f4lMj2jhTo
While
ad/library/accounting-team/check-out/cp4X5rcwQrp3w8f4lMj2jhTo
is thelease_id
.The lease renew command returns
lease not found
error.Check the library status.
$ vault read ad/library/accounting-team/status Key Value --- ----- MSA4SQL@example.com map[available:true] testMSA@example.com map[available:true]
Both service accounts are available for check-out. This is because Vault automatically checked in
testMSA@example.com
after the TTL expired.
Considerations for account check-in
During the check-in operation, Vault verifies the identity of the caller to see if it is the same client that checked out the service account. If the client has an associated entity, Vault checks to see if the entity ID matches the borrower's ID. Otherwise, Vault uses the client token to verify its identity. If the identity does not match, the check-in operation fails.
For example, a client authenticated with Vault using AppRole auth method and used the generated token to check-out a shared service account. Then the token expired, so the client re-authenticated to acquire a new token and attempt to invoke the check-in operation. When Vault compares the token value, it does not match; therefore, the check-in operation fails.
The request returns an error: "testMSA@example.com" can't be checked in because it wasn't checked out by the caller
There are three ways to handle this situation in the absence of entity ID:
- Set the
disable_check_in_enforcement
parameter totrue
- Use the
ad/library/manage
endpoint - Revoke the lease
Disable check-in enforcement
When you configure the accounting-team
library, pass the
disable_check_in_enforcement
parameter and set it to true
. This disables the
checking of the client identity during the check-in operation.
Example:
$ vault write ad/library/accounting-team \
service_account_names="testMSA@example.com,MSA4SQL@example.com" \
ttl=24h \
max_ttl=120h \
disable_check_in_enforcement=true
Use the ad/library/manage
endpoint
Alternatively, the ad/library/manage
endpoint can be used to check-in the
service account.
Do not forget that the acct-team
policy must include the following.
path "ad/library/managa/accounting-team/check-in" {
capabilities = [ "update" ]
}
$ vault write -f ad/library/manage/accounting-team/check-in
Revoke the lease
Revoking the lease has the same effect. Again, do not forget that the
acct-team
policy must allow this operation.
path "sys/leases/revoke/*" {
capabilities = [ "update" ]
}
$ vault lease revoke ad/library/accounting-team/check-out/zklrSdycrQnwuxvAqCkIJkaV
While ad/library/accounting-team/check-out/zklrSdycrQnwuxvAqCkIJkaV
is the
lease_id
.