2018-01-09 23:06:00 +00:00
|
|
|
---
|
|
|
|
layout: "guides"
|
2018-01-17 01:16:20 +00:00
|
|
|
page_title: "Static Secrets - Guides"
|
|
|
|
sidebar_current: "guides-static-secrets"
|
2018-01-09 23:06:00 +00:00
|
|
|
description: |-
|
|
|
|
Vault supports generating new unseal keys as well as rotating the underlying
|
|
|
|
encryption keys. This guide covers rekeying and rotating Vault's encryption
|
|
|
|
keys.
|
|
|
|
---
|
|
|
|
|
2018-01-17 01:16:20 +00:00
|
|
|
# Static Secrets
|
2018-01-09 23:06:00 +00:00
|
|
|
|
|
|
|
Vault can be used to store any secrets in a secure manner. The secrets may be
|
|
|
|
SSL certificates and keys for your organization's domain, credentials to connect
|
|
|
|
to a corporate database server, etc. Storing such sensitive information in a
|
|
|
|
plaintext is not desirable. This guide demonstrates the use case of Vault as a
|
|
|
|
Secret Storage.
|
|
|
|
|
|
|
|
|
|
|
|
## Reference Material
|
|
|
|
|
|
|
|
- [Key/Value Secret Backend](/docs/secrets/kv/index.html)
|
|
|
|
- [Key/Value Secret Backend API](/apikey/secret/kv/index.html)
|
|
|
|
- [Client libraries](/apikey/libraries.html) for Vault API for commonly used languages
|
|
|
|
|
|
|
|
## Estimated Time to Complete
|
|
|
|
|
|
|
|
10 minutes
|
|
|
|
|
|
|
|
## Challenge
|
|
|
|
|
|
|
|
Consider the following situations:
|
|
|
|
|
|
|
|
- Developers use a single admin account to access a third-party app
|
|
|
|
(e.g. Splunk) and anyone who knows the user ID and password can log in as an
|
|
|
|
admin
|
|
|
|
- SSH keys to connect to remote machines are shared and stored as a plaintext
|
|
|
|
- API keys to invoke external system APIs are stored as a plaintext
|
|
|
|
- An app integrates with LDAP, and its configuration information is in a
|
|
|
|
plaintext
|
|
|
|
|
|
|
|
Organizations often seek an uniform solution to store any sensitive information
|
|
|
|
securely.
|
|
|
|
|
|
|
|
## Solution
|
|
|
|
|
|
|
|
Leverage Vault as a centralized secret storage to secure any sensitive
|
2018-01-17 01:16:20 +00:00
|
|
|
information. Vault encrypts these secrets using 256-bit AES in GCM mode with a
|
|
|
|
randomly generated nonce prior to writing them to its persistent storage. The
|
|
|
|
storage backend never sees the unencrypted value, so gaining access to the raw
|
2018-01-18 01:39:21 +00:00
|
|
|
storage isn't enough to access your secrets.
|
2018-01-17 01:16:20 +00:00
|
|
|
|
2018-01-09 23:06:00 +00:00
|
|
|
|
|
|
|
## Prerequisites
|
|
|
|
|
|
|
|
To perform the tasks described in this guide, you need to have a Vault
|
2018-01-18 01:39:21 +00:00
|
|
|
environment. Refer to the [Getting
|
2018-01-24 00:22:17 +00:00
|
|
|
Started](/intro/getting-started/install.html) guide to install Vault. Make sure
|
|
|
|
that your Vault server has been [initialized and
|
2018-01-18 01:39:21 +00:00
|
|
|
unsealed](/intro/getting-started/deploy.html).
|
2018-01-09 23:06:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
## Steps
|
|
|
|
|
|
|
|
This guide demonstrates the basic steps to store secrets using Vault. The
|
|
|
|
scenario here is to store the following secrets:
|
|
|
|
|
|
|
|
- API key (Google API)
|
|
|
|
- Root certificate of a production database (MySQL)
|
|
|
|
|
|
|
|
To store your API key within the configured physical storage for Vault, use the
|
|
|
|
key/value secret backend via **`secret/`** prefixed.
|
|
|
|
|
|
|
|
-> Key/Value secret backend passes through any operation back to the configured
|
|
|
|
storage backend for Vault. For example, if your Vault server is configured with
|
|
|
|
Consul as its storage backend, a "read" operation turns into a read from Consul
|
|
|
|
at the same path.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
You will perform the following:
|
|
|
|
|
|
|
|
1. [Store the Google API key](#step1)
|
|
|
|
2. [Store the root certificate for MySQL](#step2)
|
|
|
|
3. [Retrieve the secrets](#step3)
|
|
|
|
|
|
|
|
### <a name="step1"></a>Step 1: Store the Google API key
|
|
|
|
|
2018-01-24 00:22:17 +00:00
|
|
|
If the secret path convention is **`secret/<OWNER>/apikey/<APP>`**, store the
|
|
|
|
Google API key in `secret/eng/apikey/Googl`. If you have an API key for New Relic
|
|
|
|
owned by the DevOps team, the path may look like
|
|
|
|
`secret/devops/apikey/New_Relic`.
|
|
|
|
|
2018-01-09 23:06:00 +00:00
|
|
|
#### CLI command
|
|
|
|
|
2018-01-24 00:22:17 +00:00
|
|
|
To create key/value secrets:
|
|
|
|
|
2018-01-09 23:06:00 +00:00
|
|
|
```shell
|
2018-01-24 00:22:17 +00:00
|
|
|
$ vault write secret/<PATH> <KEY>=VALUE>
|
2018-01-09 23:06:00 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
The `<PATH>` can be anything you want it to be, and your organization should
|
|
|
|
decide on the naming convention that makes most sense.
|
|
|
|
|
|
|
|
**Example:**
|
|
|
|
|
|
|
|
```shell
|
2018-01-24 00:22:17 +00:00
|
|
|
$ vault write secret/eng/apikey/Google key=AAaaBBccDDeeOTXzSMT1234BB_Z8JzG7JkSVxI
|
2018-01-09 23:06:00 +00:00
|
|
|
Success! Data written to: secret/eng/apikey/Google
|
|
|
|
```
|
|
|
|
|
2018-01-24 00:22:17 +00:00
|
|
|
The secret key is "key" and its value is "AAaaBBccDDeeOTXzSMT1234BB_Z8JzG7JkSVxI" in
|
|
|
|
this example.
|
2018-01-09 23:06:00 +00:00
|
|
|
|
|
|
|
#### API call using cURL
|
|
|
|
|
2018-01-24 00:22:17 +00:00
|
|
|
Use `/secret/<PATH>` endpoint to create secrets:
|
2018-01-18 01:39:21 +00:00
|
|
|
|
2018-01-24 00:22:17 +00:00
|
|
|
```shell
|
|
|
|
$ curl --header "X-Vault-Token: <TOKEN>" \
|
|
|
|
--request POST \
|
|
|
|
--data <SECRETS> \
|
|
|
|
<VAULT_ADDRESS>/v1/secret/<PATH>
|
2018-01-18 01:39:21 +00:00
|
|
|
```
|
|
|
|
|
2018-01-24 00:22:17 +00:00
|
|
|
Where `<TOKEN>` is your valid token, `<SECRETS>` is the key-value pair(s) of your
|
|
|
|
secrets, and `secret/<PATH>` is the path to your secrets.
|
2018-01-09 23:06:00 +00:00
|
|
|
|
|
|
|
**Example:**
|
|
|
|
|
|
|
|
```shell
|
2018-01-24 00:22:17 +00:00
|
|
|
$ curl --header "X-Vault-Token: ..." --request POST \
|
|
|
|
--data '{"key": "AAaaBBccDDeeOTXzSMT1234BB_Z8JzG7JkSVxI"}' \
|
|
|
|
https://vault.rocks/v1/secret/eng/apikey/Google
|
2018-01-09 23:06:00 +00:00
|
|
|
```
|
|
|
|
|
2018-01-24 00:22:17 +00:00
|
|
|
The secret key is "key" and its value is
|
|
|
|
"AAaaBBccDDeeOTXzSMT1234BB_Z8JzG7JkSVxI" in this example.
|
2018-01-09 23:06:00 +00:00
|
|
|
|
2018-01-18 01:39:21 +00:00
|
|
|
|
2018-01-09 23:06:00 +00:00
|
|
|
### <a name="step2"></a>Step 2: Store the root certificate for MySQL
|
|
|
|
|
2018-01-24 00:22:17 +00:00
|
|
|
For the purpose of this guide, generate a new self-sign certificate using
|
|
|
|
[OpenSSL](https://www.openssl.org/source/).
|
2018-01-18 01:39:21 +00:00
|
|
|
|
|
|
|
```shell
|
2018-01-24 00:22:17 +00:00
|
|
|
$ openssl req --request509 -sha256 -nodes -newkey rsa:2048 -keyout selfsigned.key -out cert.pem
|
2018-01-18 01:39:21 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
Generated `cert.pem` file:
|
|
|
|
|
|
|
|
```plaintext
|
|
|
|
-----BEGIN CERTIFICATE-----
|
|
|
|
MIIDSjCCAjICCQC47CQCg4u0kDANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJV
|
|
|
|
UzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xFDASBgNVBAMM
|
|
|
|
C2V4YW1wbGUuY29tMR0wGwYJKoZIhvcNAQkBFg5tZUBleGFtcGxlLmNvbTAeFw0x
|
|
|
|
ODAxMTcwMTMzNThaFw0xODAyMTYwMTMzNThaMGcxCzAJBgNVBAYTAlVTMQswCQYD
|
|
|
|
VQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEUMBIGA1UEAwwLZXhhbXBs
|
|
|
|
ZS5jb20xHTAbBgkqhkiG9w0BCQEWDm1lQGV4YW1wbGUuY29tMIIBIjANBgkqhkiG
|
|
|
|
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1cPTXpnOeUXU4tgblNLSS2rcA7eIqzc6gnMY
|
|
|
|
Sh76WxOaN8VncyJw89/28QYOSYeWRn4fYywbPhHpFmrY6+1gW/8y0+Yoj7TL2Mvs
|
|
|
|
5m1ZH9eOS6kcnnX/lr+HCfJpTHokKk/Vxr0/p6agkdZq0OYMPAmiuw1M4afd5abm
|
|
|
|
8s5R99b4DgQyNvRYJp+JMddz2cM8t2AKQH4rq2NEf/GBHqHpHKmaxTyX5Rh7zg/g
|
|
|
|
WJQ/DjxUVLpbRy+soiUJTZzamrO0iu9fcww+1Q4TZsMWizA4ChQFI7uegKkZ2Alv
|
|
|
|
SNItsv01FQH3IB7pNWuna3IXXY789R0Qp0Ha5ScryVc9syg4cQIDAQABMA0GCSqG
|
|
|
|
SIb3DQEBCwUAA4IBAQBtUcuwL0rS/uhk4v53ALF+ryRoLF93wT+O9KOvK15Pi1dX
|
|
|
|
oZ9yxu5GOGi59womsrDs1vNrBuIQNVQ69dbUYu1LkhgQGDUWQb8JpCp++WHWTIeP
|
|
|
|
YTJ5C/Q1B3rXeQrVWPvO0bMCig+/G5DGtzZmKWMQGHhfOvSwrkA58YAwjC+rqexl
|
|
|
|
skA+hQ2JiU4bzIxvlPLBOUA/p+TgUKtdzPY3lxyDO2p7+8ZD56B0PoW87zNJYRcu
|
|
|
|
VdSr7er8UkUr5nVjcw/6MJeptmx6QaiHgTUSFf2HjFfzsBa/IY1VGr/8bOII+IFN
|
|
|
|
iYQTLBNG0/q/PZGeMX/RHxmCzZz/7wE0CDPMLbyf
|
|
|
|
-----END CERTIFICATE-----
|
|
|
|
```
|
|
|
|
|
|
|
|
**NOTE:** If you don't have OpenSSL, simply copy the above certificate and
|
|
|
|
save it as `cert.pem`.
|
|
|
|
|
|
|
|
|
2018-01-09 23:06:00 +00:00
|
|
|
#### CLI command
|
|
|
|
|
2018-01-24 00:22:17 +00:00
|
|
|
The command is basically the same as the Google API key example. Now, the path
|
|
|
|
convention is **`secret/<ENVIRONMENT>/cert/<SYSTEM>`**. To store the root certificate
|
|
|
|
for production MySQL, the path becomes `secret/staging/cert/postgres`.
|
2018-01-09 23:06:00 +00:00
|
|
|
|
|
|
|
**Example:**
|
|
|
|
|
|
|
|
```shell
|
2018-01-24 00:22:17 +00:00
|
|
|
$ vault write secret/prod/cert/mysql cert=@cert.pem
|
2018-01-09 23:06:00 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
This example reads the root certificate from a PEM file from the disk, and store it under
|
|
|
|
`secret/prod/cert/mysql` path.
|
2018-01-24 00:22:17 +00:00
|
|
|
> **NOTE:** Any value begins with "@" is loaded from a file.
|
2018-01-09 23:06:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
#### API call using cURL
|
|
|
|
|
|
|
|
To perform the same task using the Vault API, pass the token in the request header.
|
|
|
|
|
|
|
|
**Example:**
|
|
|
|
|
|
|
|
```shell
|
2018-01-24 00:22:17 +00:00
|
|
|
$ curl --header "X-Vault-Token: ..." \
|
|
|
|
--request POST \
|
|
|
|
--data @cert.pem \
|
|
|
|
https://vault.rocks/v1/secret/prod/cert/mysql
|
2018-01-09 23:06:00 +00:00
|
|
|
```
|
2018-01-24 00:22:17 +00:00
|
|
|
> **NOTE:** Any value begins with "@" is loaded from a file.
|
2018-01-09 23:06:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
### <a name="step3"></a>Step 3: Retrieve the secrets
|
|
|
|
|
|
|
|
Retrieving the secret from Vault is simple.
|
|
|
|
|
|
|
|
#### CLI command
|
|
|
|
|
|
|
|
```shell
|
2018-01-24 00:22:17 +00:00
|
|
|
$ vault read secret/<PATH>
|
2018-01-09 23:06:00 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
**Example:**
|
|
|
|
|
|
|
|
```shell
|
2018-01-24 00:22:17 +00:00
|
|
|
$ vault read secret/eng/apikey/Google
|
2018-01-09 23:06:00 +00:00
|
|
|
Key Value
|
|
|
|
--- -----
|
|
|
|
refresh_interval 768h0m0s
|
|
|
|
key AAaaBBccDDeeOTXzSMT1234BB_Z8JzG7JkSVxI
|
|
|
|
```
|
|
|
|
|
|
|
|
To return the key value alone, pass `-field=key` as an argument.
|
|
|
|
|
|
|
|
```shell
|
2018-01-24 00:22:17 +00:00
|
|
|
$ vault read -field=key secret/eng/apikey/Google
|
2018-01-09 23:06:00 +00:00
|
|
|
AAaaBBccDDeeOTXzSMT1234BB_Z8JzG7JkSVxI
|
|
|
|
```
|
|
|
|
|
|
|
|
#### Root certificate example:
|
|
|
|
|
|
|
|
```shell
|
2018-01-24 00:22:17 +00:00
|
|
|
$ vault read -field=cert secret/prod/cert/mysql
|
2018-01-09 23:06:00 +00:00
|
|
|
-----BEGIN RSA PRIVATE KEY-----
|
|
|
|
MIIEowIBAAKCAQEA6E2Uq0XqreZISgVMUu9pnoMsq+OoK1PI54rsA9vtDE6wiRk0GWhf5vD4DGf1
|
|
|
|
...
|
|
|
|
```
|
|
|
|
|
|
|
|
#### API call using cURL
|
|
|
|
|
|
|
|
**Example:**
|
|
|
|
|
|
|
|
```shell
|
2018-01-24 00:22:17 +00:00
|
|
|
$ curl --header "X-Vault-Token: ..." --request GET \
|
|
|
|
https://vault.rocks/v1/secret/eng/apikey/Google | jq
|
2018-01-09 23:06:00 +00:00
|
|
|
{
|
|
|
|
"request_id": "5a2005ac-1149-2275-cab3-76cee71bf524",
|
|
|
|
"lease_id": "",
|
|
|
|
"renewable": false,
|
|
|
|
"lease_duration": 2764800,
|
|
|
|
"data": {
|
|
|
|
"key": "AAaaBBccDDeeOTXzSMT1234BB_Z8JzG7JkSVxI"
|
|
|
|
},
|
|
|
|
"wrap_info": null,
|
|
|
|
"warnings": null,
|
|
|
|
"auth": null
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
**NOTE:** This example uses `jq` to parse the JSON output.
|
|
|
|
|
|
|
|
Retrieve the key value with `jq`:
|
|
|
|
|
|
|
|
```shell
|
2018-01-24 00:22:17 +00:00
|
|
|
$ curl --header "X-Vault-Token: ..." --request GET \
|
|
|
|
https://vault.rocks/v1/secret/eng/apikey/Google | jq ".data.key"
|
2018-01-09 23:06:00 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
#### Root certificate example:
|
|
|
|
|
|
|
|
```shell
|
2018-01-24 00:22:17 +00:00
|
|
|
$ curl --header "X-Vault-Token: ..." --request GET \
|
|
|
|
https://vault.rocks/v1/secret/prod/cert/mysql | jq ".data.cert"
|
2018-01-09 23:06:00 +00:00
|
|
|
```
|
|
|
|
|
2018-01-18 01:39:21 +00:00
|
|
|
## Additional Discussion
|
2018-01-09 23:06:00 +00:00
|
|
|
|
|
|
|
### Q: How do I enter my secrets without appearing in history?
|
|
|
|
|
|
|
|
As a precaution, you may wish to avoid passing your secret as a part of the CLI
|
|
|
|
command so that the secret won't appear in the history file. Here are a few
|
|
|
|
techniques you can use.
|
|
|
|
|
|
|
|
#### Option 1: Use a dash "-"
|
|
|
|
|
|
|
|
An easy technique is to use a dash "-" and then press Enter. This allows you to
|
|
|
|
enter the secret in a new line. After entering the secret, press **`Ctrl+d`** to
|
|
|
|
end the pipe and write the secret to the Vault.
|
|
|
|
|
|
|
|
```shell
|
2018-01-24 00:22:17 +00:00
|
|
|
$ vault write secret/eng/apikey/Google key=-
|
2018-01-09 23:06:00 +00:00
|
|
|
|
|
|
|
AAaaBBccDDeeOTXzSMT1234BB_Z8JzG7JkSVxI
|
|
|
|
<Ctrl+d>
|
|
|
|
```
|
|
|
|
|
|
|
|
#### Option 2: Read the secret from a file
|
|
|
|
|
|
|
|
Using the Google API key example, you can create a file containing the key (apikey.txt):
|
|
|
|
|
|
|
|
```text
|
|
|
|
{
|
|
|
|
"key": "AAaaBBccDDeeOTXzSMT1234BB_Z8JzG7JkSVxI"
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
The CLI command would look like:
|
|
|
|
|
|
|
|
```shell
|
2018-01-24 00:22:17 +00:00
|
|
|
$ vault write secret/eng/apikey/Google @apikey.txt
|
2018-01-09 23:06:00 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
#### Option 3: Disable all vault command history
|
|
|
|
|
|
|
|
Sometimes, you may not even want the vault command itself to appear in history
|
|
|
|
at all. The Option 1 and Option 2 prevents the secret to appear in the history;
|
|
|
|
however, the vault command, `vault write secret/eng/apikey/Google` will appear
|
|
|
|
in history.
|
|
|
|
|
|
|
|
In bash:
|
|
|
|
|
|
|
|
```shell
|
2018-01-24 00:22:17 +00:00
|
|
|
$ export HISTIGNORE="&:vault"
|
2018-01-09 23:06:00 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
**NOTE:** This prevents the use of the Up arrow key for command history as well.
|
|
|
|
|
|
|
|
|
|
|
|
### Q: How do I save multiple values?
|
|
|
|
|
|
|
|
The two examples introduced in this guide only had a single key-value pair. You can pass multiple values in the command.
|
|
|
|
|
|
|
|
```shell
|
2018-01-24 00:22:17 +00:00
|
|
|
$ vault write secret/dev/config/mongodb url=foo.example.com:35533 db_name=users \
|
2018-01-09 23:06:00 +00:00
|
|
|
username=admin password=pa$$w0rd
|
|
|
|
```
|
|
|
|
|
|
|
|
Or, read the secret from a file:
|
|
|
|
|
|
|
|
```shell
|
|
|
|
$ vault write secret/dev/config/mongodb @mongodb.txt
|
|
|
|
|
|
|
|
$ cat mongodb.txt
|
|
|
|
{
|
|
|
|
"url": "foo.example.com:35533",
|
|
|
|
"db_name": "users",
|
|
|
|
"username": "admin",
|
|
|
|
"password": "pa$$w0rd"
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Next steps
|