open-vault/website/content/guides/secret-mgmt/dynamic-secrets.mdx

485 lines
15 KiB
Plaintext
Raw Normal View History

2018-01-11 01:28:00 +00:00
---
layout: guides
page_title: Secret as a Service - Guides
description: Vault can dynamically generate secrets on-demand for some systems.
2018-01-11 01:28:00 +00:00
---
# Secret as a Service: Dynamic Secrets
2018-02-01 18:00:18 +00:00
Vault can generate secrets on-demand for some systems. For example, when an app
2018-01-11 01:28:00 +00:00
needs to access an Amazon S3 bucket, it asks Vault for AWS credentials. Vault
will generate an AWS credential granting permissions to access the S3 bucket. In
addition, Vault will automatically revoke this credential after the TTL is
expired.
The [Getting Started](/intro/getting-started/dynamic-secrets) guide walks
2018-01-11 01:28:00 +00:00
you through the generation of dynamic AWS credentials.
## Reference Material
- [Getting Started - Dynamic Secrets](/intro/getting-started/dynamic-secrets)
- [Secret Engines - Databases](/docs/secrets/databases)
- [Role API](/api/secret/databases#create-role)
2018-01-11 01:28:00 +00:00
## Estimated Time to Complete
10 minutes
2018-01-19 01:40:35 +00:00
## Personas
The end-to-end scenario described in this guide involves two personas:
- **`admin`** with privileged permissions to configure secret engines
2018-02-01 17:50:59 +00:00
- **`apps`** read the secrets from Vault
2018-01-19 01:40:35 +00:00
2018-01-11 01:28:00 +00:00
## Challenge
Data protection is a top priority which means that the database credential
2018-02-01 17:50:59 +00:00
rotation is a critical part of any data protection initiative. Each role has a
different set of permissions granted to access the database. When a system is
attacked by hackers, continuous credential rotation becomes necessary and needs
to be automated.
2018-01-11 01:28:00 +00:00
## Solution
2018-02-01 17:50:59 +00:00
Applications ask Vault for database credential rather than setting them as
2018-01-17 01:16:20 +00:00
environment variables. The administrator specifies the TTL of the database
credentials to enforce its validity so that they are automatically revoked when
they are no longer used.
2018-01-11 01:28:00 +00:00
New Docs Website (#5535) * conversion stage 1 * correct image paths * add sidebar title to frontmatter * docs/concepts and docs/internals * configuration docs and multi-level nav corrections * commands docs, index file corrections, small item nav correction * secrets converted * auth * add enterprise and agent docs * add extra dividers * secret section, wip * correct sidebar nav title in front matter for apu section, start working on api items * auth and backend, a couple directory structure fixes * remove old docs * intro side nav converted * reset sidebar styles, add hashi-global-styles * basic styling for nav sidebar * folder collapse functionality * patch up border length on last list item * wip restructure for content component * taking middleman hacking to the extreme, but its working * small css fix * add new mega nav * fix a small mistake from the rebase * fix a content resolution issue with middleman * title a couple missing docs pages * update deps, remove temporary markup * community page * footer to layout, community page css adjustments * wip downloads page * deps updated, downloads page ready * fix community page * homepage progress * add components, adjust spacing * docs and api landing pages * a bunch of fixes, add docs and api landing pages * update deps, add deploy scripts * add readme note * update deploy command * overview page, index title * Update doc fields Note this still requires the link fields to be populated -- this is solely related to copy on the description fields * Update api_basic_categories.yml Updated API category descriptions. Like the document descriptions you'll still need to update the link headers to the proper target pages. * Add bottom hero, adjust CSS, responsive friendly * Add mega nav title * homepage adjustments, asset boosts * small fixes * docs page styling fixes * meganav title * some category link corrections * Update API categories page updated to reflect the second level headings for api categories * Update docs_detailed_categories.yml Updated to represent the existing docs structure * Update docs_detailed_categories.yml * docs page data fix, extra operator page remove * api data fix * fix makefile * update deps, add product subnav to docs and api landing pages * Rearrange non-hands-on guides to _docs_ Since there is no place for these on learn.hashicorp, we'll put them under _docs_. * WIP Redirects for guides to docs * content and component updates * font weight hotfix, redirects * fix guides and intro sidenavs * fix some redirects * small style tweaks * Redirects to learn and internally to docs * Remove redirect to `/vault` * Remove `.html` from destination on redirects * fix incorrect index redirect * final touchups * address feedback from michell for makefile and product downloads
2018-10-19 15:40:11 +00:00
![Dynamic Secret Workflow](/img/vault-dynamic-secrets.png)
2018-01-11 01:28:00 +00:00
2018-01-17 01:16:20 +00:00
Each app instance can get unique credentials that they don't have to share. By
making those credentials to be short-lived, you reduced the change of the secret
to being compromised. If an app was compromised, the credentials used by the app
can be revoked rather than changing more global set of credentials.
2018-01-11 01:28:00 +00:00
## Prerequisites
To perform the tasks described in this guide, you need to have a Vault
environment. Refer to the [Getting
Started](/intro/getting-started/install) guide to install Vault. Make sure
2018-01-19 01:40:35 +00:00
that your Vault server has been [initialized and
unsealed](/intro/getting-started/deploy).
2018-01-18 01:39:21 +00:00
2018-01-19 01:40:35 +00:00
### PostgreSQL
2018-01-18 01:39:21 +00:00
This guide requires that you have a PostgreSQL server to connect to. If you
don't have one, install [PostgreSQL](https://www.postgresql.org/download/) to
perform the steps described in this guide.
2018-01-18 01:39:21 +00:00
- Refer to the [PostgreSQL documentation](https://www.postgresql.org/docs/online-resources/) for details
- [PostgreSQL Wiki](https://wiki.postgresql.org/wiki/First_steps) gives you a
summary of basic commands to get started.
### Policy requirements
2018-01-23 02:14:23 +00:00
-> **NOTE:** For the purpose of this guide, you can use **`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
appropriate set of policies based on your role in the organization.
To perform all tasks demonstrated in this guide, your policy must include the
following permissions:
2018-01-19 01:40:35 +00:00
```shell
# Mount secret engines
2018-01-19 01:40:35 +00:00
path "sys/mounts/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
# Configure the database secret engine and create roles
2018-01-19 01:40:35 +00:00
path "database/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
# Write ACL policies
path "sys/policy/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
2018-01-25 02:10:56 +00:00
# Manage tokens for verification
path "auth/token/create" {
2018-01-25 02:10:56 +00:00
capabilities = [ "create", "read", "update", "delete", "list", "sudo" ]
}
2018-01-19 01:40:35 +00:00
```
If you are not familiar with policies, complete the
[policies](/guides/identity/policies) guide.
2018-01-11 01:28:00 +00:00
## Steps
In this guide, you are going to configure PostgreSQL secret engine, and create
2018-01-11 01:28:00 +00:00
a read-only database role. The Vault generated PostgreSQL credentials will only
have read permission.
1. [Mount the database secret engine](#step1)
2. [Configure PostgreSQL secret engine](#step2)
2018-01-11 01:28:00 +00:00
3. [Create a role](#step3)
2018-01-19 01:40:35 +00:00
4. [Request PostgreSQL credentials](#step4)
5. [Validation](#validation)
Step 1 through 3 need to be performed by an `admin` user. Step 4 describes
2018-01-19 01:40:35 +00:00
the commands that an `app` runs to get a database credentials from Vault.
2018-01-11 01:28:00 +00:00
### Step 1: Mount the database secret engine ((#step1))
2018-01-19 01:40:35 +00:00
(**Persona:** admin)
2018-01-11 01:28:00 +00:00
As most of the secret engines, the [database secret engine](/docs/secrets/databases)
2018-01-11 01:28:00 +00:00
must be mounted.
#### CLI command
To mount a database secret engine:
2018-01-23 23:43:07 +00:00
```shell-session
$ vault secrets enable <PATH>
2018-01-23 23:43:07 +00:00
```
**Example:**
```shell-session
$ vault secrets enable database
2018-01-11 01:28:00 +00:00
```
**NOTE:** In this guide, the database secret engine is mounted at the `/database path` in
Vault. However, it is possible to mount your secret engines at any location.
2018-01-23 23:43:07 +00:00
2018-01-11 01:28:00 +00:00
#### API call using cURL
Mount `database` secret engine using `/sys/mounts` endpoint:
2018-01-18 01:39:21 +00:00
```shell-session
2018-01-23 02:14:23 +00:00
$ curl --header "X-Vault-Token: <TOKEN>" \
--request POST \
--data <PARAMETERS> \
2018-01-23 23:43:07 +00:00
<VAULT_ADDRESS>/v1/sys/mounts/<PATH>
2018-01-23 02:14:23 +00:00
```
2018-01-18 01:39:21 +00:00
2018-01-23 02:14:23 +00:00
Where `<TOKEN>` is your valid token, and `<PARAMETERS>` holds [configuration
parameters](/api/system/mounts#enable-secrets-engine) of the secret engine.
2018-01-18 01:39:21 +00:00
2018-01-23 02:14:23 +00:00
**Example:**
2018-01-18 01:39:21 +00:00
The following example mounts database secret engine at `sys/mounts/database`
path, and passed the secret engine type ("database") in the request payload.
2018-01-18 01:39:21 +00:00
```shell-session
2018-01-23 02:14:23 +00:00
$ curl --header "X-Vault-Token: ..." \
--request POST \
--data '{"type":"database"}' \
2018-03-26 19:02:22 +00:00
https://127.0.0.1:8200/v1/sys/mounts/database
2018-01-11 01:28:00 +00:00
```
**NOTE:** It is possible to mount your database secret engines at any location.
2018-01-23 23:43:07 +00:00
### Step 2: Configure PostgreSQL secret engine ((#step2))
2018-01-19 01:40:35 +00:00
(**Persona:** admin)
2018-01-11 01:28:00 +00:00
The PostgreSQL secret engine needs to be configured with valid credentials. It
is very common to give Vault the **root** credentials and let Vault manage the
auditing and lifecycle credentials; it's much better than having one person
manage the credentials.
2018-01-11 01:28:00 +00:00
The following command configures the database secret engine using
2018-01-18 01:39:21 +00:00
`postgresql-database-plugin` where the database connection URL is
`postgresql://root:rootpassword@localhost:5432/myapp`. The allowed role is
2018-01-18 01:39:21 +00:00
`readonly` which you will create in [Step 3](#step3).
**NOTE:** If your
database connection URL is different from this example, be sure to replace the
command with correct URL to match your environment.
2018-01-11 01:28:00 +00:00
#### CLI command
**Example:**
```shell-session
$ vault write database/config/postgresql \
plugin_name=postgresql-database-plugin \
allowed_roles=readonly \
connection_url=postgresql://root:rootpassword@localhost:5432/myapp
2018-01-11 01:28:00 +00:00
```
#### API call using cURL
**Example:**
```shell-session
2018-01-23 23:43:07 +00:00
$ curl --header "X-Vault-Token: ..." --request POST --data @payload.json \
2018-03-23 15:41:51 +00:00
http://127.0.0.1:8200/v1/database/config/postgresql
2018-01-11 01:28:00 +00:00
2018-01-23 23:43:07 +00:00
$ cat payload.json
2018-01-11 01:28:00 +00:00
{
"plugin_name": "postgresql-database-plugin",
"allowed_roles": "readonly",
"connection_url": "postgresql://root:rootpassword@localhost:5432/myapp"
}
```
~> **NOTE:** Read the [Database Root Credential Rotation](/guides/secret-mgmt/db-root-rotation)
guide to learn about rotating the root credential immediately after the initial
configuration of each database.
### Step 3: Create a role ((#step3))
2018-01-19 01:40:35 +00:00
(**Persona:** admin)
2018-01-11 01:28:00 +00:00
In [Step 2](#step2), you configured the PostgreSQL secret engine by passing **`readonly`** role
2018-01-19 01:40:35 +00:00
as an allowed member. The next step is to define the `readonly` role. A role is
2018-01-11 01:28:00 +00:00
a logical name that maps to a policy used to generate credentials.
-> Vault does not know what kind of PostgreSQL users you want to create. So,
supply the information in SQL to create desired users.
**Example:** `readonly.sql`
```plaintext
CREATE ROLE "{{name}}" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';
GRANT SELECT ON ALL TABLES IN SCHEMA public TO "{{name}}";
```
The values within the `{{<value>}}` will be filled in by Vault. Notice that
**`VALID_UNTIL`** clause. This tells PostgreSQL to revoke the credentials even
if Vault is offline or unable to communicate with it.
#### CLI command
**Example:**
```shell-session
2018-01-23 02:14:23 +00:00
$ vault write database/roles/readonly db_name=postgresql creation_statements=@readonly.sql \
2018-01-11 01:28:00 +00:00
default_ttl=1h max_ttl=24h
```
The above command creates a role named, `readonly` with default TTL of 1
hour, and max TTL of the credential is set to 24 hours. The `readonly.sql`
statement is passed as the role creation statement.
#### API call using cURL
**Example:**
```shell-session
2018-01-23 23:43:07 +00:00
$ curl --header "X-Vault-Token: ..." --request POST --data @payload.json \
2018-03-23 15:41:51 +00:00
http://127.0.0.1:8200/v1/database/roles/readonly
2018-01-11 01:28:00 +00:00
2018-01-23 23:43:07 +00:00
$ cat payload.json
2018-01-11 01:28:00 +00:00
{
"db_name": "postgres",
"creation_statements": ["CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}';
GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";"],
2018-01-11 01:28:00 +00:00
"default_ttl": "1h",
"max_ttl": "24h"
}
```
2018-01-19 01:40:35 +00:00
The `db_name`, `creation_statements`, `default_ttl`, and `max_ttl` are set in
the `role-payload.json`.
2018-01-11 01:28:00 +00:00
### Step 4: Request PostgreSQL credentials ((#step4))
2018-01-23 23:43:07 +00:00
(**Persona:** apps)
2018-01-11 01:28:00 +00:00
2018-01-23 23:43:07 +00:00
Now, you are switching to [`apps` persona](#personas). To get a new set of
2018-01-19 01:40:35 +00:00
PostgreSQL credentials, the client app needs to be able to **read** from the
`readonly` role endpoint. Therefore, the app's token must have a policy granting
the read permission.
2018-01-11 01:28:00 +00:00
2018-01-19 01:40:35 +00:00
`apps-policy.hcl`
2018-01-11 01:28:00 +00:00
2018-01-19 01:40:35 +00:00
```shell
# Get credentials from the database secret engine
2018-01-11 01:28:00 +00:00
path "database/creds/readonly" {
2018-01-19 01:40:35 +00:00
capabilities = [ "read" ]
2018-01-11 01:28:00 +00:00
}
```
#### CLI command
2018-01-19 01:40:35 +00:00
First create an `apps` policy, and generate a token so that you can authenticate
2018-01-23 23:43:07 +00:00
as an `apps` persona.
2018-01-19 01:40:35 +00:00
**Example:**
2018-01-11 01:28:00 +00:00
```shell
2018-01-23 23:43:07 +00:00
# Create "apps" policy
$ vault policy write apps apps-policy.hcl
2018-01-19 01:40:35 +00:00
Policy 'apps' written.
2018-01-23 23:43:07 +00:00
# Create a new token with app policy
$ vault token create -policy="apps"
2018-01-19 01:40:35 +00:00
Key Value
--- -----
token e4bdf7dc-cbbf-1bb1-c06c-6a4f9a826cf2
2018-03-08 16:01:46 +00:00
token_accessor 54700b7e-d828-a6c4-6141-96e71e002bd7
2018-01-19 01:40:35 +00:00
token_duration 768h0m0s
token_renewable true
token_policies [apps default]
```
Use the returned token to perform the remaining.
**NOTE:** [AppRole Pull Authentication](/guides/identity/authentication) guide
2018-01-19 01:40:35 +00:00
demonstrates more sophisticated way of generating a token for your apps.
```shell
2018-01-23 23:43:07 +00:00
# Authenticate with Vault using the generated token first
2018-01-31 17:27:14 +00:00
$ vault login e4bdf7dc-cbbf-1bb1-c06c-6a4f9a826cf2
2018-01-19 01:40:35 +00:00
Successfully authenticated! You are now logged in.
token: e4bdf7dc-cbbf-1bb1-c06c-6a4f9a826cf2
token_duration: 2764277
token_policies: [apps default]
2018-01-23 23:43:07 +00:00
# Invoke the vault command
2018-01-19 01:40:35 +00:00
$ vault read database/creds/readonly
2018-01-11 01:28:00 +00:00
Key Value
--- -----
2018-03-08 16:01:46 +00:00
lease_id database/creds/readonly/4b5c6e82-df88-0dec-c0cb-f07eee8f0329
2018-01-11 01:28:00 +00:00
lease_duration 1h0m0s
lease_renewable true
password A1a-4urzp0wu92r5s1q0
username v-token-readonly-9x3qrw452wwz4w6421xt-1515625519
```
2018-01-17 01:16:20 +00:00
**NOTE:** Re-run the command and notice that Vault returns a different set of
credentials each time. This means that each app instance can acquire a unique
set of credentials.
2018-01-11 01:28:00 +00:00
#### API call using cURL
2018-01-19 01:40:35 +00:00
First create an `apps` policy, and generate a token so that you can authenticate
as an `app` persona.
2018-01-23 02:14:23 +00:00
```shell
2018-01-23 23:43:07 +00:00
# Payload to pass in the API call
2018-01-19 01:40:35 +00:00
$ cat payload.json
{
"policy": "path \"database/creds/readonly\" {capabilities = [ \"read\" ]}"
}
2018-01-23 23:43:07 +00:00
# Create "apps" policy
$ curl --header "X-Vault-Token: ..." --request PUT \
--data @payload.json \
2018-03-23 15:41:51 +00:00
http://127.0.0.1:8200/v1/sys/policy/apps
2018-01-23 23:43:07 +00:00
# Generate a new token with apps policy
2018-01-23 02:14:23 +00:00
$ curl --header "X-Vault-Token: ..." --request POST \
--data '{"policies": ["apps"]}' \
2018-03-23 15:41:51 +00:00
http://127.0.0.1:8200/v1/auth/token/create | jq
2018-01-19 01:40:35 +00:00
{
"request_id": "e1737bc8-7e51-3943-42a0-2dbd6cb40e3e",
"lease_id": "",
"renewable": false,
"lease_duration": 0,
"data": null,
"wrap_info": null,
"warnings": null,
"auth": {
"client_token": "1c97b03a-6098-31cf-9d8b-b404e52dcb4a",
"accessor": "b10a3eb7-15fe-1924-600e-403cfda34c28",
"policies": [
"apps",
"default"
],
"metadata": null,
"lease_duration": 2764800,
"renewable": true,
"entity_id": ""
}
}
```
Be sure to use the returned token to perform the remaining.
**NOTE:** [AppRole Pull Authentication](/guides/identity/authentication) guide
2018-01-19 01:40:35 +00:00
demonstrates more sophisticated way of generating a token for your apps.
```shell-session
2018-01-23 02:14:23 +00:00
$ curl --header "X-Vault-Token: 1c97b03a-6098-31cf-9d8b-b404e52dcb4a" \
--request GET \
2018-03-23 15:41:51 +00:00
http://127.0.0.1:8200/v1/database/creds/readonly | jq
2018-01-11 01:28:00 +00:00
{
"request_id": "e0e5a6c1-5e69-5cf3-c9d2-020af192de36",
"lease_id": "database/creds/readonly/7aa462ab-98cb-fdcb-b226-f0a0d37644cc",
"renewable": true,
"lease_duration": 3600,
"data": {
"password": "A1a-2680ut032xqt16tq",
"username": "v-token-readonly-6s4su6z93472x0r2787t-1515625742"
},
"wrap_info": null,
"warnings": null,
"auth": null
}
```
### Validation
(1) Generate a new set of credentials.
```shell-session
2018-01-23 02:14:23 +00:00
$ vault read database/creds/readonly
2018-01-11 01:28:00 +00:00
Key Value
--- -----
lease_id database/creds/readonly/3e8174da-6ca0-143b-aa8c-4c238aa02809
lease_duration 1h0m0s
lease_renewable true
password A1a-w2xv2zsq4r5ru940
username v-token-readonly-48rt0t36sxp4wy81x8x1-1515627434
```
The generated username is `v-token-readonly-48rt0t36sxp4wy81x8x1-1515627434`.
(2) Connect to the postgres as an admin user, and run the following psql commands.
```shell-session
2018-01-11 01:28:00 +00:00
$ psql -U postgres
postgres > \du
List of roles
Role name | Attributes | Member of
--------------------------------------------------+------------------------------------------------------------+-----------
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
v-token-readonly-48rt0t36sxp4wy81x8x1-1515627434 | Password valid until 2018-01-11 00:37:14+00 | {}
postgres > \q
```
2018-01-11 01:28:00 +00:00
The `\du` command lists all users. You should be able to verify that the username generated by Vault exists.
(3) Renew the lease for this credential by passing its **`lease_id`**.
```shell-session
2018-01-23 02:14:23 +00:00
$ vault renew database/creds/readonly/3e8174da-6ca0-143b-aa8c-4c238aa02809
2018-01-11 01:28:00 +00:00
Key Value
--- -----
lease_id database/creds/readonly/3e8174da-6ca0-143b-aa8c-4c238aa02809
lease_duration 1h0m0s
lease_renewable true
```
(4) Revoke the generated credentials.
```shell-session
$ vault lease revoke database/creds/readonly/3e8174da-6ca0-143b-aa8c-4c238aa02809
2018-01-11 01:28:00 +00:00
```
**NOTE:** If you run the command with **`-prefix=true`** flag, it revokes all
secrets under `database/creds/readonly`.
Now, when you check the list of users in PostgreSQL, none of the Vault generated
user name exists.
## Next steps
2018-01-17 01:16:20 +00:00
2018-03-08 16:01:46 +00:00
This guide discussed how to generate credentials on-demand so that the access
2018-01-17 01:16:20 +00:00
credentials no longer need to be written to disk. Next, learn about the
[Tokens and Leases](/guides/identity/lease) so that you can control the
lifecycle of those credentials.