| --- |
| layout: docs |
| page_title: Google Cloud KMS - Secrets Engines |
| description: |- |
| The Google Cloud KMS secrets engine for Vault interfaces with Google Cloud |
| KMS for encryption/decryption of data and KMS key management through Vault. |
| --- |
| |
| # Google Cloud KMS secrets engine |
| |
| The Google Cloud KMS Vault secrets engine provides encryption and key management |
| via [Google Cloud KMS][kms]. It supports management of keys, including creation, |
| rotation, and revocation, as well as encrypting and decrypting data with managed |
| keys. This enables management of KMS keys through Vault's policies and IAM |
| system. |
| |
| ## Setup |
| |
| Most secrets engines must be configured in advance before they can perform their |
| functions. These steps are usually completed by an operator or configuration |
| management tool. |
| |
| 1. Enable the Google Cloud KMS secrets engine: |
| |
| ```text |
| $ vault secrets enable gcpkms |
| Success! Enabled the gcpkms secrets engine at: gcpkms/ |
| ``` |
| |
| By default, the secrets engine will mount at the name of the engine. To |
| enable the secrets engine at a different path, use the `-path` argument. |
| |
| 1. Configure the secrets engine with account credentials and/or scopes: |
| |
| ```text |
| $ vault write gcpkms/config \ |
| credentials=@my-credentials.json |
| Success! Data written to: gcpkms/config |
| ``` |
| |
| If you are running Vault from inside [Google Compute Engine][gce] or [Google |
| Kubernetes Engine][gke], the instance or pod service account can be used in |
| place of specifying the credentials JSON file. For more information on |
| authentication, see the [authentication section](#authentication) below. |
| |
| 1. Create a Google Cloud KMS key: |
| |
| ```text |
| $ vault write gcpkms/keys/my-key \ |
| key_ring=projects/my-project/locations/my-location/keyRings/my-keyring \ |
| rotation_period=72h |
| ``` |
| |
| The `key_ring` parameter is specified in the following format: |
| |
| ```text |
| projects/<project>/locations/<location>/keyRings/<keyring> |
| ``` |
| |
| where: |
| |
| - `<project>` - the name of the GCP project (e.g. "my-project") |
| - `<location>` - the location of the KMS key ring (e.g. "us-east1", "global") |
| - `<keyring>` - the name of the KMS key ring (e.g. "my-keyring") |
| |
| ## Usage |
| |
| After the secrets engine is configured and a user/machine has a Vault token with |
| the proper permission, it can be used to encrypt, decrypt, and manage keys. The |
| following sections describe the different ways in which keys can be managed. |
| |
| ### Symmetric Encryption/Decryption |
| |
| This section describes using a Cloud KMS key for symmetric |
| encryption/decryption. This is one of the most common types of encryption. |
| Google Cloud manages the key ring which is used to encrypt and decrypt data. |
| |
| <table> |
| <thead> |
| <tr> |
| <th>Purpose</th> |
| <th>Supported Algorithms</th> |
| </tr> |
| <tr> |
| <td valign="top"> |
| <code>encrypt_decrypt</code> |
| </td> |
| <td valign="top"> |
| <code>symmetric_encryption</code> |
| </td> |
| </tr> |
| </thead> |
| </table> |
| |
| 1. Create or use an existing key eligible for symmetric encryption/decryption: |
| |
| ```text |
| $ vault write gcpkms/keys/my-key \ |
| key_ring=projects/.../my-keyring \ |
| purpose=encrypt_decrypt \ |
| algorithm=symmetric_encryption |
| ``` |
| |
| 1. Encrypt plaintext data using the `/encrypt` endpoint with a named key: |
| |
| ```text |
| $ vault write gcpkms/encrypt/my-key plaintext="hello world" |
| Key Value |
| --- ----- |
| ciphertext CiQAuMv0lTiKjrF43Lgr4... |
| key_version 1 |
| ``` |
| |
| Unlike Vault's transit backend, plaintext data does not need to be base64 |
| encoded. The endpoint will automatically convert data. |
| |
| Note that Vault is not _storing_ this data. The caller is responsible for |
| storing the resulting ciphertext. |
| |
| 1. Decrypt ciphertext using the `/decrypt` endpoint with a named key: |
| |
| ```text |
| $ vault write gcpkms/decrypt/my-key ciphertext=CiQAuMv0lTiKjrF43Lgr4... |
| Key Value |
| --- ----- |
| plaintext hello world |
| ``` |
| |
| For easier scripting, it is also possible to extract the plaintext directly: |
| |
| ```text |
| $ vault write -field=plaintext gcpkms/decrypt/my-key ciphertext=CiQAuMv0lTiKjrF43Lgr4... |
| hello world |
| ``` |
| |
| 1. Rotate the underlying encryption key. This will generate a new crypto key |
| version on Google Cloud KMS and set that version as the active key. |
| |
| ```text |
| $ vault write -f gcpkms/keys/rotate/my-key |
| WARNING! The following warnings were returned from Vault: |
| |
| * The crypto key version was rotated successfully, but it can take up to 2 |
| hours for the new crypto key version to become the primary. In practice, it |
| is usually much shorter. Be sure to issue a read operation and verify the |
| key version if you require new data to be encrypted with this key. |
| |
| Key Value |
| --- ----- |
| key_version 2 |
| ``` |
| |
| As the message says, rotation is not immediate. Depending on a number of |
| factors, the propagation of the new key can take quite some time. If you |
| have a need to immediately encrypt data with this new key, query the API to |
| wait for the key to become the primary. Alternatively, you can specify the |
| `key_version` parameter to lock to the exact key for use with encryption. |
| |
| 1. Re-encrypt already-encrypted ciphertext to be encrypted with a new version of |
| the crypto key. Vault will decrypt the value using the appropriate key in the |
| keyring and then encrypt the resulting plaintext with the newest key in the |
| keyring. |
| |
| ```text |
| $ vault write gcpkms/reencrypt/my-key ciphertext=CiQAuMv0lTiKjrF43Lgr4... |
| Key Value |
| --- ----- |
| ciphertext CiQAuMv0lZTTozQA/ElqM... |
| key_version 2 |
| ``` |
| |
| This process **does not** reveal the plaintext data. As such, a Vault policy |
| could grant an untrusted process the ability to re-encrypt ciphertext data, |
| since the process would not be able to get access to the plaintext data. |
| |
| 1. Trim old key versions by deleting Cloud KMS crypto key versions that are |
| older than the `min_version` allowed on the key. |
| |
| ```text |
| $ vault write gcpkms/keys/config/my-key min_version=10 |
| ``` |
| |
| Then delete all keys older than version 10. This will make it impossible to |
| encrypt, decrypt, or sign values with the older key by conventional means. |
| |
| ```text |
| $ vault write -f gcpkms/keys/trim/my-key |
| ``` |
| |
| 1. Delete the key to delete all key versions and Vault's record of the key. |
| |
| ```text |
| $ vault delete gcpkms/keys/my-key |
| ``` |
| |
| This will make it impossible to encrypt, decrypt, or sign values by |
| conventional means. |
| |
| ### Asymmetric decryption |
| |
| This section describes using a Cloud KMS key for asymmetric decryption. In this |
| model Google Cloud manages the key ring and exposes the public key via an API |
| endpoint. The public key is used to encrypt data offline and produce ciphertext. |
| When the plaintext is desired, the user submits the ciphertext to Cloud KMS |
| which decrypts the value using the corresponding private key. |
| |
| <table> |
| <thead> |
| <tr> |
| <th>Purpose</th> |
| <th>Supported Algorithms</th> |
| </tr> |
| <tr> |
| <td valign="top"> |
| <code>asymmetric_decrypt</code> |
| </td> |
| <td valign="top"> |
| <code>rsa_decrypt_oaep_2048_sha256</code> |
| <br /> |
| <code>rsa_decrypt_oaep_3072_sha256</code> |
| <br /> |
| <code>rsa_decrypt_oaep_4096_sha256</code> |
| </td> |
| </tr> |
| </thead> |
| </table> |
| |
| 1. Create or use an existing key eligible for symmetric encryption/decryption: |
| |
| ```text |
| $ vault write gcpkms/keys/my-key \ |
| key_ring=projects/.../my-keyring \ |
| purpose=asymmetric_decrypt \ |
| algorithm=rsa_decrypt_oaep_4096_sha256 |
| ``` |
| |
| 1. Retrieve the public key from Cloud KMS: |
| |
| ```text |
| $ gcloud kms keys versions get-public-key <crypto-key-version> \ |
| --location <location> \ |
| --keyring <key-ring> \ |
| --key <key> \ |
| --output-file ~/mykey.pub |
| ``` |
| |
| 1. Encrypt plaintext data with the public key. Note this varies widely between |
| programming languages. The following example uses OpenSSL, but you can use your |
| language's built-ins as well. |
| |
| ```text |
| $ openssl pkeyutl -in ~/my-secret-file \ |
| -encrypt -pubin \ |
| -inkey ~/mykey.pub \ |
| -pkeyopt rsa_padding_mode:oaep \ |
| -pkeyopt rsa_oaep_md:sha256 \ |
| -pkeyopt rsa_mgf1_md:sha256 |
| ``` |
| |
| Note that this encryption happens offline (meaning outside of Vault), and |
| the encryption is happening with a _public_ key. Only Cloud KMS has the |
| corresponding _private_ key. |
| |
| 1. Decrypt ciphertext using the `/decrypt` endpoint with a named key: |
| |
| ```text |
| $ vault write gcpkms/decrypt/my-key key_version=1 ciphertext=CiQAuMv0lTiKjrF43Lgr4... |
| Key Value |
| --- ----- |
| plaintext hello world |
| ``` |
| |
| ### Asymmetric signing |
| |
| This section describes using a Cloud KMS key for asymmetric signing. In this |
| model Google Cloud manages the key ring and exposes the public key via an API |
| endpoint. A message or digest is signed with the corresponding private key, and |
| can be verified by anyone with the corresponding public key. |
| |
| <table> |
| <thead> |
| <tr> |
| <th>Purpose</th> |
| <th>Supported Algorithms</th> |
| </tr> |
| <tr> |
| <td valign="top"> |
| <code>asymmetric_sign</code> |
| </td> |
| <td valign="top"> |
| <code>rsa_sign_pss_2048_sha256</code> |
| <br /> |
| <code>rsa_sign_pss_3072_sha256</code> |
| <br /> |
| <code>rsa_sign_pss_4096_sha256</code> |
| <br /> |
| <code>rsa_sign_pkcs1_2048_sha256</code> |
| <br /> |
| <code>rsa_sign_pkcs1_3072_sha256</code> |
| <br /> |
| <code>rsa_sign_pkcs1_4096_sha256</code> |
| <br /> |
| <code>ec_sign_p256_sha256</code> |
| <br /> |
| <code>ec_sign_p384_sha384</code> |
| </td> |
| </tr> |
| </thead> |
| </table> |
| |
| 1. Create or use an existing key eligible for symmetric encryption/decryption: |
| |
| ```text |
| $ vault write gcpkms/keys/my-key \ |
| key_ring=projects/.../my-keyring \ |
| purpose=asymmetric_sign \ |
| algorithm=ec_sign_p384_sha384 |
| ``` |
| |
| 1. Calculate the base64-encoded binary digest. Use the hashing algorithm that |
| corresponds to they key type: |
| |
| ```text |
| $ export DIGEST=$(openssl dgst -sha384 -binary /my/file | base64) |
| ``` |
| |
| Ask Cloud KMS to sign the digest: |
| |
| ```text |
| $ vault write gcpkms/sign/my-key key_version=1 digest=$DIGEST |
| Key Value |
| --- ----- |
| signature MGYCMQDbOS2462SKMsGdh2GQ... |
| ``` |
| |
| 1. Verify the signature of the digest: |
| |
| ```text |
| $ vault write gcpkms/verify/my-key key_version=1 digest=$DIGEST signature=$SIGNATURE |
| Key Value |
| --- ----- |
| valid true |
| ``` |
| |
| Note: it is also possible to verify this signature without Vault. Download |
| the public key from Cloud KMS, and use a tool like OpenSSL or your |
| programming language primitives to verify the signature. |
| |
| ## Authentication |
| |
| The Google Cloud KMS Vault secrets backend uses the official Google Cloud Golang |
| SDK. This means it supports the common ways of [providing credentials to Google |
| Cloud][cloud-creds]. In addition to specifying `credentials` directly via Vault |
| configuration, you can also get configuration from the following values **on the |
| Vault server**: |
| |
| 1. The environment variables `GOOGLE_APPLICATION_CREDENTIALS`. This is specified |
| as the **path** to a Google Cloud credentials file, typically for a service |
| account. If this environment variable is present, the resulting credentials are |
| used. If the credentials are invalid, an error is returned. |
| |
| 1. Default instance credentials. When no environment variable is present, the |
| default service account credentials are used. This is useful when running Vault |
| on [Google Compute Engine][gce] or [Google Kubernetes Engine][gke] |
| |
| For more information on service accounts, please see the [Google Cloud Service |
| Accounts documentation][service-accounts]. |
| |
| To use this secrets engine, the service account must have the following |
| minimum scope(s): |
| |
| ```text |
| https://www.googleapis.com/auth/kms |
| ``` |
| |
| ### Required permissions |
| |
| The credentials given to Vault must have the following role: |
| |
| ```text |
| roles/cloudkms.admin |
| ``` |
| |
| If Vault will not be creating keys, you can reduce the permissions. For example, |
| to create keys out of band and have Vault manage the encryption/decryption, you |
| only need the following permissions: |
| |
| ```text |
| roles/cloudkms.cryptoKeyEncrypterDecrypter |
| ``` |
| |
| To sign and verify, you only need the following permissions: |
| |
| ```text |
| roles/cloudkms.signerVerifier |
| ``` |
| |
| For more information, please see the [Google Cloud KMS IAM documentation][kms-iam]. |
| |
| ## FAQ |
| |
| **How is this different than Vault's transit secrets engine?**<br /> |
| Vault's [transit][vault-transit] secrets engine uses in-memory keys to |
| encrypt/decrypt keys. In general it will be faster and more performant. However, |
| users who need physical, off-site, or out-of-band key management can use the |
| [Google Cloud KMS][kms] secrets engine to get those benefits while leveraging |
| Vault's policy and identity system. |
| |
| **Can Vault use an existing KMS key?**<br /> |
| You can use the `/register` endpoint to configure Vault to talk to an existing |
| Google Cloud KMS key. As long as the IAM permissions are correct, Vault will be |
| able to encrypt/decrypt data and rotate the key. See the [api][api] for more |
| information. |
| |
| **Can this be used with a hardware key like an HSM?**<br /> |
| Yes! You can set `protection_level` to "hsm" when creating a key, or use an |
| existing Cloud KMS key that is backed by an HSM. |
| |
| **How much does this cost?**<br /> |
| The plugin is free and open source. KMS costs vary by key type and the number of |
| operations. Please see the [Cloud KMS pricing page][kms-pricing] for more |
| details. |
| |
| ## Help & support |
| |
| The Google Cloud KMS Vault secrets engine is written as an external Vault |
| plugin. The code lives outside the main Vault repository. It is automatically |
| bundled with Vault releases, but the code is managed separately. |
| |
| Please report issues, add feature requests, and submit contributions to the |
| [vault-plugin-secrets-gcpkms repo on GitHub][repo]. |
| |
| ## API |
| |
| The Google Cloud KMS secrets engine has a full HTTP API. Please see the |
| [Google Cloud KMS secrets engine API docs][api] for more details. |
| |
| [api]: /vault/api-docs/secret/gcpkms |
| [cloud-creds]: https://cloud.google.com/docs/authentication/production#providing_credentials_to_your_application |
| [gce]: https://cloud.google.com/compute/ |
| [gke]: https://cloud.google.com/kubernetes-engine/ |
| [kms]: https://cloud.google.com/kms |
| [kms-iam]: https://cloud.google.com/kms/docs/reference/permissions-and-roles |
| [kms-pricing]: https://cloud.google.com/kms/pricing |
| [repo]: https://github.com/hashicorp/vault-plugin-secrets-gcpkms |
| [service-accounts]: https://cloud.google.com/compute/docs/access/service-accounts |
| [vault-transit]: /vault/docs/secrets/transit |