open-vault/website/source/guides/static-secrets.html.md

362 lines
10 KiB
Markdown
Raw Normal View History

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