Customer-Managed Encryption Keys (CMEK) for CockroachDB Dedicated advanced allows the customer to delegate responsibility for the work of encrypting their cluster data to CockroachDB Cloud, while maintaining the ability to completely revoke CockroachDB Cloud's access.
This page shows how to enable Customer-Managed Encryption Keys (CMEK) for CockroachDB Advanced advanced.
Before you begin
To enable CMEK for a cluster, you need:
- An IAM role in your AWS account or a cross-tenant service account in your GCP project. CockroachDB Cloud will use this identity to encrypt and decrypt using the CMEK. This page shows how to provision a new identity, but you can use an existing identity instead. CMEK is not yet available for CockroachDB Advanced on Azure.
- A CMEK key for your cluster stored in AWS KMS or GCP KMS. CockroachDB Cloud never has access to the CMEK itself. This page shows how to provision a new CMEK directly in your KMS or using Hashicorp Vault, but you can use an existing key instead.
- A new CockroachDB Advanced private cluster with advanced security features enabled. A private cluster's nodes communicate only over private Cloud infrastructure, avoiding public networks.
Advanced security features can be enabled only during cluster creation. If necessary, create a new CockroachDB Advanced private cluster and enable advanced security features. Complete the steps in this page before inserting data into the cluster. - A CockroachDB Cloud service account and a CockroachDB Cloud API key for the service account. You will use the service account to authenticate to the CockroachDB Cloud API and configure CMEK on your cluster.
Enable CMEK
This section shows how to enable CMEK on a CockroachDB Advanced cluster.
Step 1. Provision the cross-account IAM role
Follow these steps to create a cross-account IAM role and give it permission to access the CMEK in AWS KMS. CockroachDB Cloud will assume this role to encrypt and decrypt using the CMEK.
In CockroachDB Cloud, visit the CockroachDB Cloud organization settings page. Copy your organization ID, which you will need to create the IAM role:
Visit the Clusters page. Click on the name of your cluster to open its cluster overview page. In the URL, copy the cluster ID:
https://cockroachlabs.cloud/cluster/{YOUR_CLUSTER_ID}/overview
.Use the CockroachDB Cloud API to find the ID of the AWS account managed by CockroachDB Cloud that is associated with your cluster (not your own AWS account):
curl --request GET \ --url https://cockroachlabs.cloud/api/v1/clusters/{YOUR_CLUSTER_ID} \ --header 'Authorization: Bearer {YOUR_API_KEY}'
In the response, the ID is stored in the
account_id
field.In the AWS console, visit the IAM page and select Roles and click Create role.
- For Trusted entity type, select AWS account.
- Select Another AWS account and set Account ID, provide the AWS account ID for your cluster.
- Select Require external ID and set External ID to your CockroachDB Cloud organization ID.
- Provide a name for the role. Do not enable any permissions.
Make a note of the Amazon Resource Name (ARN) for the new IAM role.
In CockroachDB Cloud, visit the CockroachDB Cloud organization settings page. Copy your organization ID, which you will need to create the cross-tenant service account.
Visit the Clusters page. Click on the name of your cluster to open its cluster overview page. In the URL, copy the cluster ID:
https://cockroachlabs.cloud/cluster/{YOUR_CLUSTER_ID}/overview
.Use the CockroachDB Cloud API to find the ID of the AWS account managed by CockroachDB Cloud that is associated with your cluster (not your own GCP project):
CLUSTER_ID= #{ your cluster ID } API_KEY= #{ your API key } curl --request GET \ --url https://cockroachlabs.cloud/api/v1/clusters/${CLUSTER_ID} \ --header "Authorization: Bearer ${API_KEY}"
In the response, the ID is stored in the
account_id
field.In the GCP Console, visit the IAM service accounts page for your project and click + Create service account. Select Cross-tenant.
Click the new service account to open its details.
In PERMISSIONS, click GRANT ACCESS.
- For New principals, enter the service account ID for your cluster, which you found earlier.
- For Role, enter Service Account Token Creator.
Click SAVE. 1. Make a note of the email address for the new service account.
Step 2. Create the CMEK key
If you intend to use an existing key as the CMEK, skip this step.
Configure Vault's authentication details:
export VAULT_ADDR={YOUR_VAULT_TARGET} export VAULT_TOKEN={YOUR_VAULT_TOKEN} export VAULT_NAMESPACE="admin"
Enable Vault KMS Secrets Engine:
vault secrets enable keymgmt
Connect Vault to your AWS account by creating a KMS provider entry:
vault write keymgmt/kms/awskms \ provider="awskms" \ key_collection="us-east-1" \ credentials=access_key="{your access key}" \ credentials=secret_key="{your secret key}"
Create an encryption key in Vault. The key has not yet been imported into AWS KMS.
vault write keymgmt/key/crdb-cmek-vault type="aes256-gcm96"
Import the key into AWS KMS:
vault write keymgmt/kms/awskms/key/crdb-cmek-vault \ purpose="encrypt,decrypt" \ protection="hsm"
In the AWS console, visit the KMS page.
Choose Customer managed keys.
Select the key you just created in Vault, which will be prefixed with
crdb-cmek-vault
.Set the permissions policy for your key with the
crdb-cmek-kms
IAM policy provided in the Appendix.Save to finish creating the key.
In the GCP Console, visit the KMS page and click + CREATE KEY RING to create a key ring for your encryption key. Make a note of the name of the key ring, which you will provide to Vault to create your encryption key.
Visit the GCP IAM roles page and create a new role called
cmek-vault-role
. Add the required permissions specified in the Vault GCP-KMS documentation. Also add the permissioncloudkms.importJobs.useToImport
, which allows the role to import keys into GCP.Visit the GCP IAM service accounts page and create a service account, called
cmek-vault-agent
. Vault will use this service account to create your CMEK key.From the service account's details page, select the PERMISSIONS tab, and attach the
cmek-vault-role
.To generate credentials for the service account, select the keys tab, and click ADD KEY. Choose Create new key, then select JSON to generate a credential file in JSON format and download it. You will need the credential JSON file generated by GCP for the service account. Store it in a secure location such as a password manager.
Configure Vault's authentication details:
export VAULT_ADDR={YOUR_VAULT_TARGET} export VAULT_TOKEN={YOUR_VAULT_TOKEN} export VAULT_NAMESPACE="admin"
Enable Vault KMS Secrets Engine:
vault secrets enable keymgmt
Connect Vault to your GCP project by creating a KMS provider entry. Replace
{SERVICE_ACCOUNT_FILE}
with the path to the JSON file you downloaded earlier and replace{YOUR_PROJECT_NAME}
with your GCP project ID.vault write keymgmt/kms/gcpckms \ provider="gcpckms" \ key_collection="projects/{YOUR_PROJECT_NAME}/locations/global/keyRings/{YOUR_KEY_RING_NAME}" \ credentials=service_account_file="{SERVICE_ACCOUNT_FILE}"
Create the encryption key in Vault:
vault write keymgmt/key/crdb-cmek-vault type="aes256-gcm96"
Import the key into GCP KMS:
vault write keymgmt/kms/gcpkms/key/crdb-cmek-vault \ purpose="encrypt,decrypt" \ protection="hsm"
To authorize the service account to use the CMEK key, visit the GCP console KMS page and select your KMS key, which will be prefixed with
crdb-cmek-vault
. From the the PERMISSIONS tab, click ADD.- For New principals, enter the email address for your cross-tenant service account.
- Click Select a role and enter Cloud KMS CryptoKey Encrypter/Decrypter.
Click SAVE. Make a note of the key ring name.
- For New principals, enter the email address for your cross-tenant service account.
Step 3. Build your CMEK configuration manifest
Compile the information about the service account and key we've just created into a manifest, which you will use to activate CMEK on your cluster with the CockroachDB Cloud API.
Create a new file named
cmek_config.json
with the following contents. This file will contain a JSON array ofregion_spec
objects, each of which includes the name of a CockroachDB Cloud region and akey_spec
that specifies the URI of the CMEK key and the principal that is authorized to encrypt and decrypt using the key.Replace the placeholder values, being careful to include one
region_spec
object per cluster region. When enabling CMEK, you must include aregion_spec
for each region in the cluster.{ "region_specs": [ { "region": "{COCKROACHDB_CLOUD_REGION}", "key_spec": { "type": "AWS_KMS", "uri": "{YOUR_AWS_KMS_KEY_ARN}", "auth_principal": "{YOUR_AWS_IAM_ROLE_ARN}" } }, { "region": "{COCKROACHDB_CLOUD_REGION}", "key_spec": { "type": "AWS_KMS", "uri": "{YOUR_AWS_KMS_KEY_ARN}", "auth_principal": "{YOUR_AWS_IAM_ROLE_ARN}" } } ] }
Set the required information as environment variables:
export CLUSTER_REGION= # the region of the Dedicated-controlled GCP project where your cluster is located export GCP_PROJECT_ID= # your GCP project ID export KEY_LOCATION= # location of your KMS key (region or 'global') export KEY_RING= # your KMS key ring name export KEY_NAME= # your CMEK key name, i.e., crdb-cmek-vault-{RANDOM_SUFFIX} export SERVICE_ACCOUNT_EMAIL= # email for your cross-tenant service account
Then copy paste the following heredoc command to generate the YAML file, populating the values from your shell environment. (Alternatively, you can manually create the YAML file).
<<YML > cmek_config.yml --- region_specs: - region: "${CLUSTER_REGION}" key_spec: type: GCP_CLOUD_KMS uri: "projects/${GCP_PROJECT_ID}/locations/${KEY_LOCATION}/keyRings/${KEY_RING}/cryptoKeys/${KEY_NAME}" auth_principal: "${SERVICE_ACCOUNT_EMAIL}" YML
Use Ruby or another tool to compile human-editable YAML into API-parsable JSON:
ruby -ryaml -rjson -e 'puts(YAML.load(ARGF.read).to_json)' < cmek_config.yml > cmek_config.json
Use the shell utility JQ to inspect JSON payload:
Note:On a Mac, install JQ with
brew install jq
cat cmek_config.json | jq
After you have built your CMEK configuration manifest with the details of your cluster and provisioned the service account and KMS key in GCP, return to Enabling CMEK for a CockroachDB Dedicated cluster.
Step 4. Activate CMEK
Using the CockroachDB Cloud API, send a POST
request with the contents of cmek_config.json
to the cluster's cmek
endpoint.
CLUSTER_ID= #{ your cluster ID }
API_KEY= #{ your API key }
curl --request POST \
--url https://cockroachlabs.cloud/api/v1/clusters/${CLUSTER_ID}/cmek \
--header "Authorization: Bearer ${API_KEY}" \
--header 'content-type: application/json' \
--data "@cmek_config.json"
Check CMEK status
To view your cluster's CMEK status, send a GET
request:
curl --request GET \
--url https://cockroachlabs.cloud/api/v1/clusters/{cluster_id}/cmek \
--header "Authorization: Bearer ${API_KEY}"
Rotate a CMEK key
You can rotate a CMEK key for a CockroachDB Advanced cluster either by creating a new version of the existing CMEK key or by creating a new CMEK key. At a high level:
To begin using a new version of an existing CMEK key:
- In your KMS platform, you can either configure automatic rotation for the CMEK key, or you can perform a manual rotation.
- CockroachDB Cloud does not automatically re-encrypt the store key using the new CMEK key version. For each region you want to update, you must also perform a rotation using the CockroachDB Cloud API without modifying the CMEK key URI. CockroachDB Cloud re-encrypts the store key using the new CMEK key version.
To begin using an entirely new CMEK key:
- Within your KMS platform, you create a new CMEK key.
- Next, you perform a rotation using the CockroachDB Cloud API and provide the new CMEK key URI.
Within your KMS, do not revoke access to, disable, schedule for destruction, or destroy a CMEK after it is rotated. It is still required to access data that was written using it. that is in use by one or more clusters. The CMEK is an external resource and is never stored in CockroachDB Cloud. If the CMEK for a cluster or region is not available in your KMS, nodes that are configured to use it cannot rejoin the cluster if they are restarted, and the cluster's managed CockroachDB Cloud backups will fail. Even if access to the CMEK is restored, affected nodes cannot automatically recover. For assistance in that situation, contact your Cockroach Labs account team.
To rotate a CMEK key:
Edit or recreate the cluster's
cmek_config.json
to update theregion_spec
objects, each of which includes the name of a CockroachDB Cloud region and akey_spec
that specifies the URI of the CMEK key and the principal that is authorized to encrypt and decrypt using the key.Using the CockroachDB Cloud API, send a
PUT
request with the contents ofcmek_config.json
to the cluster'scmek
endpoint:CLUSTER_ID= #{ your cluster ID } API_KEY= #{ your API key } curl --request PUT \ --url https://cockroachlabs.cloud/api/v1/clusters/${CLUSTER_ID}/cmek \ --header "Authorization: Bearer ${API_KEY}" \ --header 'content-type: application/json' \ --data "@cmek_config.json"
Add a region to a CMEK-enabled cluster
To add a region to a cluster that already has CMEK enabled:
Edit or recreate the cluster's
cmek_config.json
to update theregion_spec
objects, each of which includes the name of a CockroachDB Cloud region and akey_spec
that specifies the URI of the CMEK key and the principal that is authorized to encrypt and decrypt using the key.Send the payload as a
PATCH
request to the cluster endpoint:CLUSTER_ID= #{ your cluster ID } API_KEY= #{ your API key } curl --request PATCH \ --url "https://cockroachlabs.cloud/api/v1/clusters/${CLUSTER_ID}" \ --header "Authorization: Bearer ${API_KEY}" \ --header 'content-type: application/json' \ --data "@cmek_config.json"
Revoke CMEK for a cluster
When you revoke access to the CMEK in your KMS, CockroachDB Cloud can no longer encrypt or decrypt your cluster's data. All access to the cluster's data will be prevented until you you restore access. In general, revoke access to the CMEK only when you are permanently decommissioning the cluster or to mitigate a critical security breach or at the request of Cockroach Labs support.
Within your KMS platform, you can revoke access to the CMEK temporarily or permanently.
Within your KMS, do not revoke access to a CMEK that is in use by one or more clusters. The CMEK is an external resource and is never stored in CockroachDB Cloud.
- In your cloud provider's KMS platform, revoke CockroachDB Cloud's access to your CMEK key at the IAM level, either by removing the authorization the cross-account IAM role or by removing the cross-account IAM role's permission to access the key.
This will not immediately stop your cluster from encrypting and decrypting data, which does not take effect until you update your cluster in the next step. That is because CockroachDB does not use your CMEK key to encrypt/decrypt your cluster data itself. CockroachDB Dedicated accesses your CMEK key to encrypt/decrypt a key encryption key (KEK). This KEK is used to encrypt a data encryption key (DEK), which is used to encrypt/decrypt your application data. Your cluster will continue to use the already-provisioned DEK until you make the Cloud API call to revoke CMEK.
Your cluster will continue to operate with the CMEK until you update it to revoke CMEK. To revoke access:
curl --request PATCH \ --url https://cockroachlabs.cloud/api/v1/clusters/{cluster_id}/cmek \ --header "Authorization: Bearer ${API_KEY}" \ --header 'content-type: application/json' \ --data '{"action":"REVOKE"}'
Check your CMEK status to confirm the revocation has taken effect.
Once you have resolved the security incident, re-authorize CMEK for your cluster to return to normal operations. Contact your account team, or create a support ticket.
Appendix: IAM policy for the CMEK key
This IAM policy is to be attached to the CMEK key. It grants the required KMS permissions to the cross-account IAM role to be used by CockroachDB Dedicated.
Note that this IAM policy refers to the ARN for the cross-account IAM role you created at the end of Step 1. Provision the cross-account IAM role.
{
"Version": "2012-10-17",
"Id": "crdb-cmek-kms",
"Statement": [
{
"Sid": "Allow use of the key for CMEK",
"Effect": "Allow",
"Principal": {
"AWS": "{ARN_OF_CROSS_ACCOUNT_IAM_ROLE}"
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:GenerateDataKey*",
"kms:DescribeKey",
"kms:ReEncrypt*"
],
"Resource": "*"
},
{
{OTHER_POLICY_STATEMENT_FOR_ADMINISTRATING_KEY}
}
]
}