Key Management Secrets Engine with GCP Cloud KMS
Note
Key Management Secrets Engine requires Vault Enterprise Advanced Data Protection (ADP) license.
Challenge
You need to use security features of cloud providers, which involve encryption keys issued and stored by the provider in its own key management system (KMS), but you must also maintain root of trust and control of the encryption key lifecycle outside of the cloud.
Solution
The Vault Key Management Secrets Engine provides distribution and lifecycle management features for cloud provider keys.
Currently, it manages keys for the following cloud providers.
Personas
The end-to-end scenario described in this tutorial involves one persona:
admin
a user with with privileged permissions to configure secrets engines.
Prerequisites
To perform the tasks described in this tutorial, you need to have:
A Google Cloud account with sufficient permissions to manage applications, service accounts, and Cloud Key Management Service (Cloud KMS).
Vault Enterprise with the Advanced Data Protection Module at version 1.9.0 or later.
jq is required to pretty print JSON output.
Policy requirements
Each persona requires a different set of capabilities. These are expressed in policies. If you are not familiar with policies, complete the policies tutorial.
The admin tasks require these capabilities.
# Mount secrets enginespath "sys/mounts/*" { capabilities = [ "create", "read", "update", "delete", "list" ]} # Configure the default Key Management Secrets Engine instancepath "keymgmt/*" { capabilities = [ "create", "read", "update", "delete", "list" ]}
Start Vault dev server
In a new terminal session, start a Vault dev server with the value of the initial root token set to root
.
$ vault server -dev -dev-root-token-id root
The Vault dev server defaults to listening at 127.0.0.1:8200
. The server is also automatically initialized and unsealed.
Insecure operation
Do not run a Vault dev server in production. This approach starts a Vault server with an in-memory database and runs in an insecure way.
In another new terminal session, export an environment variable for the vault
CLI to address the dev server.
$ export VAULT_ADDR=http://127.0.0.1:8200
Then export an environment variable for the vault
CLI to authenticate with the Vault server.
$ export VAULT_TOKEN=root
Note
For these tasks, you can use Vault's root token. However, it is recommended that root tokens are only used for enough initial setup or in emergencies. As a best practice, use an authentication method or token that meets the policy requirements.
Refer to Dev Options to learn more about Vault dev server options.
The Vault dev server is now ready for use.
Scenario introduction
You will configure a Cloud KMS instance, then use the Vault CLI or HTTP API to configure a Vault development mode server and enable management of the Cloud KMS key with the Key Management secrets engine.
After initial configuration, you will perform some lifecycle operations with the secrets engine, like writing, reading, updating, and rotating keys.
- Configure Cloud KMS
- Enable Key Management secrets engine
- Write keys
- Read keys
- Create KMS provider
- Distribute keys to Cloud KMS
- Rotate key
Configure Cloud KMS
To follow this tutorial, you must configure a Google Cloud project, enable billing for the project, and enable the required Cloud KMS API.
You must then create a KMS keyring and note its resource name. The example used in this tutorial is projects/learn-kmse/locations/global/keyRings/learn-keyring
.
You must also create a service account, and assign it the proper roles in the project to manage Cloud KMS keys. The minimum roles required are as follows:
- cloudkms.cryptoKeys.create
- cloudkms.cryptoKeys.update
- cloudkms.importJobs.create
- cloudkms.importJobs.get
- cloudkms.cryptoKeyVersions.list
- cloudkms.cryptoKeyVersions.destroy
- cloudkms.cryptoKeyVersions.update
- cloudkms.cryptoKeyVersions.create
You then need to generate a JSON based credential file for this service account that Vault will use to connect to and manage the Cloud KMS instance. You can also specify the credentials using the GOOGLE_CREDENTIALS
environment variable or application default credentials. Consult the Key Management Secrets Engine documentation for more details.
Note
In this tutorial, the Cloud KMS instance is named learn-kmse and the service account is named learn-vault-kmse. As you follow the step-by-step instruction, be sure to use the Cloud KMS instance name and service account name that matches what you created if different.
You can refer to the Cloud KMS Quickstart documentation for further details on these steps.
When complete, you should have a Cloud KMS and keyring available in the Google Cloud Console as shown in this screenshot.
Enable Key Management secrets engine
You must first enable an instance of the Key Management Secrets engine before you can use it. The default behavior without specifying a path to enable the secrets engine on is to enable it at the path keymgmt/
.
Enable the secrets engine.
$ vault secrets enable keymgmt
The secrets engine is now enabled and ready for use.
Write keys
The Key Management secrets engine currently supports generation of the key types specified in Key Types.
Write a aes256-gcm96 key to the secrets engine.
$ vault write keymgmt/key/aes256-gcm96 type="aes256-gcm96"
With this command line syntax, you are instructing Vault to write a new key of type aes256-gcm96 to the path keymgmt/key/aes256-gcm96
. The key that is written is for general purpose use, but you will set its specific use later.
You can do the same again to write the second key, but change the type to ecdsa-p256
, and the path to keymgmt/key/ecdsa-p256
.
$ vault write keymgmt/key/ecdsa-p256 type="ecdsa-p256"
Read keys
To learn about the content of a key, you can read it back. Let's read the aes256-gcm96 key, use JSON as the output, and pipe that into jq
.
$ vault read -format=json keymgmt/key/aes256-gcm96 | jq
Your output should resemble this example.
{ "request_id": "631f98de-b755-9863-40db-f789ff9ff10a", "lease_id": "", "lease_duration": 0, "renewable": false, "data": { "deletion_allowed": false, "latest_version": 1, "min_enabled_version": 1, "name": "aes256-gcm96", "type": "aes256-gcm96", "versions": { "1": { "creation_time": "2021-11-16T13:07:17.878864-05:00" } } }, "warnings": null}
Notice the value of versions
; it is 1 since this is the first version of the key that Vault knows about. This will figure into the example on key rotation later.
Read the second key.
$ vault read -format=json keymgmt/key/ecdsa-p256 | jq
Your output should resemble this example.
{ "request_id": "858f8b0d-043c-113f-6f53-e5043cfdaf6f", "lease_id": "", "lease_duration": 0, "renewable": false, "data": { "deletion_allowed": false, "latest_version": 1, "min_enabled_version": 1, "name": "ecdsa-p256", "type": "ecdsa-p256", "versions": { "1": { "creation_time": "2021-11-16T13:08:23.499803-05:00", "public_key": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAES7Zln/7LeCRHsNLXGQCgz23wwiZp\n97oiTsi9Jvpcsuf6pX2A2XipLWIhZfW2XvvUjAqS5oKnGw/XZc0jR+yF3g==\n-----END PUBLIC KEY-----\n" } } }, "warnings": null}
Create KMS provider
The next step is to create the KMS provider configuration in Vault; this corresponds to the Cloud KMS instance you previously created in Google Cloud.
Create the KMS provider at the path keymgmt/kms/gcpckms
.
$ vault write keymgmt/kms/gcpckms \ provider="gcpckms" \ key_collection="projects/learn-kmse/locations/global/keyRings/learn-keyring" \ credentials=service_account_file="/tmp/credentials.json"
Be sure to replace learn-kmse
and learn-keyring
with the appropriate project name and keyring name for your account if different.
In this command line example, you specified 4 pieces of information to successfully configure the Cloud KMS instance.
- The full path to this KMS provider instance in Vault (
keymgmt/kms/gcpckms
). - The KMS provider type is set to gcpckms.
- A key collection, which refers to the resource ID of an existing GCP Cloud KMS key ring; this value cannot be changed after creation.
- Credentials file to use for authentication with GCP Cloud KMS. Supplying values for this parameter is optional, as credentials may also be specified as the
GOOGLE_CREDENTIALS
environment variable or default application credentials.
Distribute keys to key vault
To use the keys you wrote in step 3, you must first distribute them to the Cloud KMS. Add the aes256-gcm96 key to the Cloud KMS at the path keymgmt/kms/gcpckms/key/aes256-gcm96
.
$ vault write keymgmt/kms/gcpckms/key/aes256-gcm96 \ purpose="encrypt,decrypt" \ protection="hsm"
Write the second key to the path keymgmt/kms/gcpckms/key/ecdsa-p256
next, but specify that its purpose is for signing.
$ vault write keymgmt/kms/gcpckms/key/ecdsa-p256 \ purpose="sign" \ protection="hsm"
Verify keys
You can use the vault
CLI to list the keys that have been distributed to the Cloud KMS instance.
$ vault list keymgmt/kms/gcpckms/key/Keys----aes256-gcm96ecdsa-p256
You can also visit the Cloud Console to confirm the key distribution.
Inspecting the key aes256-gcm96 shows its current version.
Inspecting the key ecdsa-p256 shows its permitted operations, which includes only Sign.
Rotate key
Key rotation is a fundamental part of the key management lifecycle. Let's use Vault to rotate the aes256-gcm96 key and then verify its version with the vault
CLI and Cloud Console.
Rotate the key.
$ vault write -f keymgmt/key/aes256-gcm96/rotate
Note
This command line uses the force flag (-f
) because there are no parameters passed as key/value pairs and in such cases, it is required to avoid an error.
Confirm key rotation
You can confirm successful key rotation by reading the key with the CLI, and getting the value of .data.latest_version
.
$ vault read -format=json keymgmt/key/aes256-gcm96 | jq '.data.latest_version'2
The key is now at version 2; in the Cloud Console, the key will be expected to have a different version string than the original value under Primary version as shown in the Cloud Console UI screenshot.
Cleanup
If you wish to clean up your environment after completing the tutorial, follow the steps in this section.
Unset the environment variables.
$ unset ROOT_TOKEN UNSEAL_KEY VAULT_ADDR LEARN_VAULT
Remove the credential file.
$ rm -f /tmp/credentials.json
Remove the JSON payload files.
$ rm -f \ /tmp/kmse-gcpckms.json \ /tmp/aes256-gcm96-key.json \ /tmp/ecdsa-p256-key.json
You can stop the Vault server by pressing Ctrl+C where the server is running. Or, execute the following command.
$ pgrep -f vault | xargs kill
Summary
You have learned the basics about the Key Management secrets engine, including configuring Cloud KMS, enabling the secrets engine, and performing basic key lifecycle management operations.
From here, you can learn can learn about other Vault secrets engines in the Secrets tutorial collection.