Customer-Managed Encryption Keys (CMEK) for CockroachDB Cloud 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.
Before you begin
- Make a note of your Cloud organization ID in the Organization settings page.
- Find your Advanced cluster's ID. From the CockroachDB Cloud console Clusters list, click the name of a cluster to open its Cluster Overview page. From the page's URL make a note of the last 12 digits of the portion of the URL before
/overview/
. This is the cluster ID. Use the cluster ID to find the cluster's associated cross-account IAM role, which is managed by CockroachDB Cloud.
curl --request GET \ --url https://cockroachlabs.cloud/api/v1/clusters/{YOUR_CLUSTER_ID} \ --header 'Authorization: Bearer {YOUR_API_KEY}' | jq .account_id
In the response, verify that the
id
field matches the cluster ID you specified, then make a note of theaccount_id
, which is the ID for the cross-account IAM role.
- Make a note of your Cloud organization ID in the Organization settings page.
- Find your Advanced cluster's ID. From the CockroachDB Cloud console Clusters list, click the name of a cluster to open its Cluster Overview page. From the page's URL make a note of the last 12 digits of the portion of the URL before
/overview/
. This is the cluster ID. Use the cluster ID to find the cluster's associated GCP Project ID, which is managed by CockroachDB Cloud. Query the
clusters/
endpoint of the CockroachDB Cloud API: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, verify that the
id
field matches the cluster ID you specified, then make a note of the following:account_id
: the GCP project ID.regions
/name
: one entry for each of the cluster's regions. CMEK must be configured in each of a cluster's regions.
{ "id": "blahblahblah-9ebd-43d9-8f42-589c9e6fc081", "name": "crl-prod-xyz", "cockroach_version": "v22.1.1", "plan": "DEDICATED", "cloud_provider": "GCP", "account_id": "crl-prod-xyz", "state": "CREATED", "creator_id": "blahblahblah-3457-471c-b0cb-c2ab15834329", "operation_status": "CLUSTER_STATUS_UNSPECIFIED", "config": { "dedicated": { "machine_type": "n1-standard-2", "num_virtual_cpus": 2, "storage_gib": 15, "memory_gib": 7.5, "disk_iops": 450 } }, "regions": [ { "name": "us-east4", "sql_dns": "crl-prod-xyz.gcp-us-east4.cockroachlabs.cloud", "ui_dns": "crl-prod-xyz.gcp-us-east4.cockroachlabs.cloud", "node_count": 1 } ], "created_at": "2022-06-16T17:24:06.262259Z", "updated_at": "2022-06-16T17:43:59.189571Z", "deleted_at": null }
Formulate the service account's email address, which is in the following format. Replace
{cluster_id}
with the cluster ID, and replace{account_id}
with the GCP project ID.crl-kms-user-{cluster_id}@{account_id}.iam.gserviceaccount.com
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.
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 that you found in Before you begin.
- Select Require external ID and set External ID to your CockroachDB Cloud organization ID, which you found in Before you begin.
- 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.
Step 1. Provision the cross-tenant service account
- 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 in Before you begin
- 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.
- In the AWS console, visit AWS KMS.
- To create the key, select Customer managed keys and click Create Key.
- Set Key type to Symmetric Key.
- Set Key usage to Encrypt and decrypt.
- Under Advanced options, set Key material to KMS, then choose whether to create a single-region or multi-region key. For optimal performance, we recommend serving the key in each of your cluster's regions.
- Set Alias to a name for the key.
Configure the permissions for your key using the following IAM policy:
{ "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} } ] }
Finish creating the key.
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.
- Click + CREATE KEY RING and fill in the details to complete the key ring.
In the next screen, configure your encryption key as desired. Set the following:
- Type: Generated key.
- Protection level: Software
- Purpose: Symmetric encrypt/decrypt
Click Create.
Make a note of the key ring name.
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 Advanced-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 Advanced 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 Advanced 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 Advanced.
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}
}
]
}