Store versioned key/value secrets
This tutorial demonstrates the K/V Secrets Engine version 2 with secret versioning.
The KV secrets engine v1 does not provide a way to version or roll back secrets. This made it difficult to recover from unintentional data loss or overwrite when more than one user is writing at the same path.
Run the version 2 of KV secrets engine which can retain a configurable number of secret versions. This enables older versions' data to be retrievable in case of unwanted deletion or updates of the data. In addition, its Check-and-Set operations can be used to protect the data from being overwritten unintentionally.
What this tutorial covers
This tutorial will walk you through the basic features of the KV v2 secrets engine:
- Check the KV secrets engine version
- Write secrets
- Retrieve a specific version of secret
- Specify the number of versions to keep
- Delete versions of secret
- Permanently delete data
- Configure automatic data deletion
- Check-and-Set operations
Prerequisites
To perform the tasks described in this tutorial, you need to have a Vault environment. Refer to the Getting Started tutorial to install Vault.
Launch Terminal
This tutorial includes a free interactive command-line lab that lets you follow along on actual cloud infrastructure.
Policy requirements
Note
For the purpose of this tutorial, you can use root
token to work
with Vault. However, it is recommended that root tokens are only used for
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 tutorial, your policy must include the following permissions:
Vault version
The -output-policy
flag requires Vault 1.11.0 or later.
To perform all tasks demonstrated in this tutorial, you are going to need to run
a number of vault
CLI commands. Adding the -output-policy
flag does not
execute the command, but instead prints the ACL policy needed to successfully
execute the command.
Check the policy needed for kv put
:
Output:
Now, check the ACL policy needed for kv get
:
If you are not familiar with policies, complete the policies tutorial.
Lab setup
Note
If you do not have access to an HCP Vault Dedicated cluster, visit the Create a Vault Cluster on HCP tutorial.
Launch the HCP Portal and login.
Click Vault in the left navigation pane.
In the Vault clusters pane, click vault-cluster.
Under Cluster URLs, click Public Cluster URL.
In a terminal, set the
VAULT_ADDR
environment variable to the copied address.Return to the Overview page and click Generate token.
Within a few moments, a new token will be generated.
Copy the Admin Token.
Return to the terminal and set the
VAULT_TOKEN
environment variable.Set the
VAULT_NAMESPACE
environment variable toadmin
.The
admin
namespace is the top-level namespace automatically created by HCP Vault. All CLI operations default to use the namespace defined in this environment variable.Type
vault status
to verify your connectivity to the Vault cluster.
The Vault Dedicated server is ready.
Check the KV secrets engine version
(Persona: admin)
The Vault server started in dev
mode, automatically enables v2
of the KV secrets engine at the secret/
path. Verify that KV secrets engine
is enabled and its version is 2.
Display all the enabled secrets engine.
The results display a table of all enabled secrets engines. One entry in the
table has the Path of secret/
with the Type of kv
. The Options
column displays the version number.
Display the details of kv
secrets engine enabled at sys/mounts/<name>
.
Example output:
Enable KV v2 at secret/
.
If the KV version is version:1
, upgrade it to version:2
.
Write secrets
To understand how the versioning works, let's write some test data.
Create a secret at the path secret/customer/acme
with a customer_name
and
contact_email
.
New in Vault 1.11.0: The following command is equivalent to the above command.
Example output:
The secret stores metadata along with the secret data. The version
is an auto-incrementing number that starts at 1
.
Create secret at the same path secret/customer/acme
but with different
secret data.
Example output:
The secret is fully replaced and the version is incremented to 2
.
Get the secret defined at the path secret/customer/acme
.
New in Vault 1.11.0: The following command is equivalent to the above command.
Example output:
The output displays version 2 of the secret. Creating a secret at the same path replaces the existing data; fields are not merged together. The secret data stored in earlier versions is still accessible but it is no longer returned by default.
Use JSON file
You can define the secret's key-value pairs in a JSON file, and pass the file to the command. Refer to the Option 2: Read the secret from a file section for the example.
Patch the existing data
While vault kv put
fully replaces the current version of the secret;
therefore, you need to send the entire set of data including the values that
remain the same. To partially update the current version of the secret, you can
use vault kv patch
command instead.
Use case: Think of an application that does not have read permission, but
captures partial data updates. The vault kv patch
command allows the
application to send only the changing values to Vault.
ACL Policy
KV v2 secrets engine honors the distinction between the create
and update
capabilities inside ACL policies. The patch
capability is also supported which
can perform partial updates whereas the update
capability represents full
overwrites. To permit partial updates, be sure to add patch
capability in the
ACL policy.
Update the contact_email
value to admin@acme.com
(current value is
john.smith@acme.com
).
Example output:
The patch command creates a new version of the secret which merges the fields within the secret data.
Read the secret at secret/customer/acme
to verify the change.
The contact_email
value is now admin@acme.com
, and the version
is
now 3.
Add custom metadata
You saw that the secret's key (in this example, secret/customer/acme
) has
metadata associated with it. An organization may want to add custom metadata
describing further details (technical contact, mission criticality, etc.) about
the secret.
When you are running Vault 1.9.0 or later, you can add custom metadata using
custom_metadata
parameter. This feature stores a map of arbitrary
string-to-string valued user-provided metadata meant to describe the secret.
The -custom-metadata
flag can be repeated to add multiple key-value pairs.
Output:
Now, when you read the secret, the returned secret metadata displays the custom metadata.
Example output:
Retrieve a specific version of secret
You may run into a situation where you need to view the secret before an update.
Get version 1 of the secret defined at the path secret/customer/acme
.
Get the metadata
of the secret defined at the path secret/customer/acme
.
Specify the number of versions to keep
By default, the kv-v2
secrets engine keeps up to 10 versions. Let's limit the
maximum number of versions to keep to be 4.
Configure the secrets engine at path secret/
to limit all secrets to a
maximum of 4
versions.
Every secret stored for this engine can retain up to 4
versions.
Display the secrets engine configuration settings.
Configure the secret at path secret/customer/acme
to limit secrets to
a maximum of 4
versions.
The secret can also define the maximum number of versions.
Create four more secrets at the path secret/customer/acme
.
Get the metadata
of the secret defined at the path secret/customer/acme
.
Example output:
The metadata displays the current_version
and the history of versions stored.
Secrets stored at this path are limited to 4 versions. Version 1 and 2 are
deleted.
Verify that version 1 of the secret defined at the path secret/customer/acme
are deleted.
Delete versions of secret
Delete version 4 and 5 of the secrets at path secret/customer/acme
.
Get the metadata of the secret defined at the path secret/customer/acme
.
The metadata on versions 4 and 5 reports its deletion timestamp
(deletion_time
); however, the destroyed
parameter is set to false
.
Undelete version 5 of the secrets at path secret/customer/acme
.
Permanently delete data
Destroy version 4 of the secrets at path secret/customer/acme
.
Get the metadata of the secret defined at the path secret/customer/acme
.
The metadata displays that Version 4 is destroyed.
Delete all versions of the secret at the path secret/customer/acme
.
Configure automatic data deletion
As of Vault 1.2, you can configure the length of time before a version gets
deleted. For example, if your organization requires data to be deleted after 10
days from its creation, you can configure the K/V v2 secrets engine to do so by
setting the delete_version_after
parameter.
For demonstration, configure the secrets at path secret/test
to delete
versions after 40
seconds.
Create a secret at the path secret/test
.
Again, create a secret at the path secret/test
.
Again, create a secret at the path secret/test
.
Note
You can use upper-arrow key to recover the previously executed command.
Get the metadata of the secret defined at the path secret/test
.
Example output:
The metadata displays a deletion_time
set on each version. After 40 seconds,
the data gets deleted automatically. The data has not been destroyed.
Get version 1 of the secret defined at the path secret/test
.
Check-and-Set operations
The v2 of KV secrets engine supports a Check-And-Set operation to prevent
unintentional secret overwrite. When you pass the cas
flag to Vault, it first
checks if the key already exists.
Display the secrets engine configuration settings.
The cas_required
setting is false
. The KV secrets engine defaults to disable
the Check-And-Set operation.
Configure the secrets engine at path secret/
to enable Check-And-Set.
Configure the secret at path secret/partner
to enable Check-And-Set.
Once check-and-set is enabled, every write operation requires the cas
parameter with the current version of the secret. Set cas
to 0
when a secret
at that path does not already exist.
Create a new secret at the path secret/partner
.
Overwrite the secret at the path secret/partner
.
Example output:
Additional discussion
Q: How do I enter my secrets without exposing the secret in my shell's 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 on a new line. After entering the secret, press Ctrl+d
to
end the pipe which will write the secret to the Vault.
Option 2: Read the secret from a file
You can use a file to pass the key-value pairs. Create a file named
apikey.json
that defines the key
field.
Create a secret at path kv-v1/eng/apikey/Google
with keys and values defined
in apikey.json
.
Option 3: Disable all vault command history
The first two options ensure that the contents of the secret do not appear in the shell history. The secret path would still be accessible through the shell history.
You can configure your shell to avoid logging any vault
commands to your
history.
In bash
, set the history to ignore all commands that start with vault
.
Note
This prevents vault
commands from appearing when using the Up
arrow or when searching command history with <Ctrl-r>
.
Q: How do I save multiple values at once?
The tutorial examples demonstrating a secret with a single key-value pair. Multiple key-value pairs may be provided in a single command.
Create a secret at path kv-v1/dev/config/mongodb
that sets the url
,
db_name
, username
, and password
.
You can pass a file containing multiple key-value pairs to the command.
Create a file named mongodb.json
that defines the url
, db_name
, username
,
and password
fields.
Create a secret at path kv-v1/dev/config/mongodb
with keys and values defined
in mongodb.json
.
Q: How do I store secrets generated by Vault in KV secrets engine?
Assuming that you have AppRole auth method enabled (refer to the AppRole Pull Authentication tutorial).
The following command retrieves the Secret ID of the jenkins
role, encode it
with base64, and stores the value in the kv-v1/secret-id
path.
Output:
Next steps
This tutorial demonstrated the versioned KV secrets engine (kv-v2
) feature. To
integrate the KV secrets engine into your existing application, you must
implement the Vault API to accomplish that. Alternatively, you can leverage
Vault Agent which significantly reduces the amount of code change introduced to
your application.
The Vault Agent Templates tutorial provides an end-to-end example.