»Google Cloud KMS Secrets Engine

The Google Cloud KMS Vault secrets engine provides encryption and key management via Google Cloud 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:

    $ vault secrets enable gcpkms
    Success! Enabled the gcpkms secrets engine at: gcpkms/
    
    $ vault secrets enable gcpkmsSuccess! 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.

  2. Configure the secrets engine with account credentials and/or scopes:

    $ vault write gcpkms/config \
        credentials=@my-credentials.json
    Success! Data written to: gcpkms/config
    
    $ vault write gcpkms/config \    credentials=@my-credentials.jsonSuccess! Data written to: gcpkms/config

    If you are running Vault from inside Google Compute Engine or Google Kubernetes Engine, 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 below.

  3. Create a Google Cloud KMS key:

    $ vault write gcpkms/keys/my-key \
      key_ring=projects/my-project/locations/my-location/keyRings/my-keyring \
      rotation_period=72h
    
    $ 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:

    projects/<project>/locations/<location>/keyRings/<keyring>
    
    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.

PurposeSupported Algorithms
encrypt_decryptsymmetric_encryption
  1. Create or use an existing key eligible for symmetric encryption/decryption:

    $ vault write gcpkms/keys/my-key \
        key_ring=projects/.../my-keyring \
        purpose=encrypt_decrypt \
        algorithm=symmetric_encryption
    
    $ vault write gcpkms/keys/my-key \    key_ring=projects/.../my-keyring \    purpose=encrypt_decrypt \    algorithm=symmetric_encryption
  2. Encrypt plaintext data using the /encrypt endpoint with a named key:

    $ vault write gcpkms/encrypt/my-key plaintext="hello world"
    Key            Value
    ---            -----
    ciphertext     CiQAuMv0lTiKjrF43Lgr4...
    key_version    1
    
    $ 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.

  3. Decrypt ciphertext using the /decrypt endpoint with a named key:

    $ vault write gcpkms/decrypt/my-key ciphertext=CiQAuMv0lTiKjrF43Lgr4...
    Key          Value
    ---          -----
    plaintext    hello world
    
    $ 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:

    $ vault write -field=plaintext gcpkms/decrypt/my-key ciphertext=CiQAuMv0lTiKjrF43Lgr4...
    hello world
    
    $ vault write -field=plaintext gcpkms/decrypt/my-key ciphertext=CiQAuMv0lTiKjrF43Lgr4...hello world
  4. 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.

    $ 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
    
    $ vault write -f gcpkms/keys/rotate/my-keyWARNING! 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.

  5. 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.

    $ vault write gcpkms/reencrypt/my-key ciphertext=CiQAuMv0lTiKjrF43Lgr4...
    Key            Value
    ---            -----
    ciphertext     CiQAuMv0lZTTozQA/ElqM...
    key_version    2
    
    $ 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.

  6. Trim old key versions by deleting Cloud KMS crypto key versions that are older than the min_version allowed on the key.

    $ vault write gcpkms/keys/config/my-key min_version=10
    
    $ 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.

    $ vault write -f gcpkms/keys/trim/my-key
    
    $ vault write -f gcpkms/keys/trim/my-key
  7. Delete the key to delete all key versions and Vault's record of the key.

    $ vault delete gcpkms/keys/my-key
    
    $ 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.

PurposeSupported Algorithms
asymmetric_decryptrsa_decrypt_oaep_2048_sha256
rsa_decrypt_oaep_3072_sha256
rsa_decrypt_oaep_4096_sha256
  1. Create or use an existing key eligible for symmetric encryption/decryption:

    $ vault write gcpkms/keys/my-key \
        key_ring=projects/.../my-keyring \
        purpose=asymmetric_decrypt \
        algorithm=rsa_decrypt_oaep_4096_sha256
    
    $ vault write gcpkms/keys/my-key \    key_ring=projects/.../my-keyring \    purpose=asymmetric_decrypt \    algorithm=rsa_decrypt_oaep_4096_sha256
  2. Retrieve the public key from Cloud KMS:

    $ gcloud kms keys versions get-public-key <crypto-key-version> \
        --location <location> \
        --keyring <key-ring> \
        --key <key> \
        --output-file ~/mykey.pub
    
    $ gcloud kms keys versions get-public-key <crypto-key-version> \    --location <location> \    --keyring <key-ring> \    --key <key> \    --output-file ~/mykey.pub
  3. 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.

    $ 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
    
    $ 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.

  4. Decrypt ciphertext using the /decrypt endpoint with a named key:

    $ vault write gcpkms/decrypt/my-key key_version=1 ciphertext=CiQAuMv0lTiKjrF43Lgr4...
    Key          Value
    ---          -----
    plaintext    hello world
    
    $ 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.

PurposeSupported Algorithms
asymmetric_signrsa_sign_pss_2048_sha256
rsa_sign_pss_3072_sha256
rsa_sign_pss_4096_sha256
rsa_sign_pkcs1_2048_sha256
rsa_sign_pkcs1_3072_sha256
rsa_sign_pkcs1_4096_sha256
ec_sign_p256_sha256
ec_sign_p384_sha384
  1. Create or use an existing key eligible for symmetric encryption/decryption:

    $ vault write gcpkms/keys/my-key \
        key_ring=projects/.../my-keyring \
        purpose=asymmetric_sign \
        algorithm=ec_sign_p384_sha384
    
    $ vault write gcpkms/keys/my-key \    key_ring=projects/.../my-keyring \    purpose=asymmetric_sign \    algorithm=ec_sign_p384_sha384
  2. Calculate the base64-encoded binary digest. Use the hashing algorithm that corresponds to they key type:

    $ export DIGEST=$(openssl dgst -sha384 -binary /my/file | base64)
    
    $ export DIGEST=$(openssl dgst -sha384 -binary /my/file | base64)

    Ask Cloud KMS to sign the digest:

    $ vault write gcpkms/sign/my-key key_version=1 digest=$DIGEST
    Key          Value
    ---          -----
    signature    MGYCMQDbOS2462SKMsGdh2GQ...
    
    $ vault write gcpkms/sign/my-key key_version=1 digest=$DIGESTKey          Value---          -----signature    MGYCMQDbOS2462SKMsGdh2GQ...
  3. Verify the signature of the digest:

    $ vault write gcpkms/verify/my-key key_version=1 digest=$DIGEST signature=$SIGNATURE
    Key      Value
    ---      -----
    valid    true
    
    $ vault write gcpkms/verify/my-key key_version=1 digest=$DIGEST signature=$SIGNATUREKey      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. 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.

  2. 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 or Google Kubernetes Engine

For more information on service accounts, please see the Google Cloud Service Accounts documentation.

To use this secrets engine, the service account must have the following minimum scope(s):

https://www.googleapis.com/auth/kms
https://www.googleapis.com/auth/kms

»Required Permissions

The credentials given to Vault must have the following role:

roles/cloudkms.admin
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:

roles/cloudkms.cryptoKeyEncrypterDecrypter
roles/cloudkms.cryptoKeyEncrypterDecrypter

To sign and verify, you only need the following permissions:

roles/cloudkms.signerVerifier
roles/cloudkms.signerVerifier

For more information, please see the Google Cloud KMS IAM documentation.

»FAQ

How is this different than Vault's transit secrets engine?
Vault's 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 secrets engine to get those benefits while leveraging Vault's policy and identity system.

Can Vault use an existing KMS key?
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 for more information.

Can this be used with a hardware key like an HSM?
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?
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 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.

»API

The Google Cloud KMS secrets engine has a full HTTP API. Please see the Google Cloud KMS secrets engine API docs for more details.