Use customer-managed encryption keys (CMEK)

Stay organized with collections Save and categorize content based on your preferences.

This page describes how to set up a service account and keys for customer-managed encryption keys, and how to create an instance that uses a customer-managed encryption key. To learn more about using customer-managed encryption keys with Cloud SQL, see Overview of customer-managed encryption keys.

Before you begin

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Cloud project. Learn how to check if billing is enabled on a project.

  4. Install and initialize the Google Cloud CLI.
  5. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  6. Make sure that billing is enabled for your Cloud project. Learn how to check if billing is enabled on a project.

  7. Install and initialize the Google Cloud CLI.
  8. Make sure you have the Cloud SQL Admin role on your user account.

    Go to the IAM page

  9. Enable the Cloud Key Management Service API.

    Enable the API

  10. Enable the Cloud SQL Admin API.

    Enable the API

Workflow for creating a Cloud SQL instance with CMEK

  1. gcloud and API users only: Create a service account for each project that requires customer-managed encryption keys.
  2. Create a keyring and key, and set the location for each key. The location is the Google Cloud region.
  3. gcloud and API users only: Grant the service account access to the key.
  4. Copy or write down the key ID (KMS_KEY_ID) and location for the key, and the ID (KMS_KEYRING_ID) for the keyring. You need this information when granting the service account access to the key.
  5. Go to a project and create a Cloud SQL instance with the following options:
    1. The same location as the customer-managed encryption key
    2. The customer-managed key configuration
    3. The customer-managed encryption key ID

Your Cloud SQL instance is now enabled with CMEK.

Create a service account

You need to create a service account for each project that requires customer-managed encryption keys.

To allow a user to manage service accounts, grant one of the following roles:

  • Service Account User (roles/iam.serviceAccountUser): Includes permissions to list service accounts, get details about a service account, and impersonate a service account.
  • Service Account Admin (roles/iam.serviceAccountAdmin): Includes permissions to list service accounts and get details about a service account. Also includes permissions to create, update, and delete service accounts, and to view or change the Cloud SQL for PostgreSQL policy on a service account.

Currently, you can only use gcloud commands to create the type of service account you need for customer-managed encryption keys. If you are using the Console, Cloud SQL automatically creates this service account for you.

gcloud

gcloud beta services identity create \
--service=sqladmin.googleapis.com \
--project=PROJECT_ID

Terraform

To create a service account, use a Terraform resource.

resource "google_project_service_identity" "gcp_sa_cloud_sql" {
  provider = google-beta
  service  = "sqladmin.googleapis.com"
}

Apply the changes

To apply your Terraform configuration in a Google Cloud project, complete the following steps:

  1. Launch Cloud Shell.
  2. Set the Google Cloud project where you want to apply the Terraform configuration:
    export GOOGLE_CLOUD_PROJECT=PROJECT_ID
    
  3. Create a directory and open a new file in that directory. The filename must have the .tf extension, for example main.tf:
    mkdir DIRECTORY && cd DIRECTORY && nano main.tf
    
  4. Copy the sample into main.tf.
  5. Review and modify the sample parameters to apply to your environment.
  6. Save your changes by pressing Ctrl-x and then y.
  7. Initialize Terraform:
    terraform init
  8. Review the configuration and verify that the resources that Terraform is going to create or update match your expectations:
    terraform plan

    Make corrections to the configuration as necessary.

  9. Apply the Terraform configuration by running the following command and entering yes at the prompt:
    terraform apply

    Wait until Terraform displays the "Apply complete!" message.

  10. Open your Google Cloud project to view the results. In the Google Cloud console, navigate to your resources in the UI to make sure that Terraform has created or updated them.

The previous command returns a service account name. You use this service account name during the procedure in Granting the service account access to the key.

Create a key

You can create the key in the same Google Cloud project as the Cloud SQL instance or in a separate user project. The Cloud KMS key ring location must match the region where you want to create Cloud SQL instance. A multi-region or global region key will not work. The Cloud SQL instance create request fails if the regions don't match.

To create a Cloud KMS key:

Console

  1. In the Google Cloud console, go to the Cryptopraphic keys page.

    Go to Cryptopraphic keys

  2. Click Create key ring.
  3. Add a Key ring name. Note this name because you need it when granting the service account access to the key.
  4. Add a Key ring location.
  5. Click Create. The Create key page opens.
  6. Add a Key name.
  7. Select a Purpose (symmetric or asymmetric).
  8. Select a Rotation period and Starting on date.
  9. Click Create.
  10. On the Keys table, click the three dots in the last column, and select Copy Resource ID or write it down. This is the KMS_KEY_ID. You need the KMS_KEY_ID when granting the key access to the service account.

gcloud

  1. Create a new key ring.
    gcloud kms keyrings create KMS_KEYRING_ID \
    --location=GCP_REGION
      
    Write down this name because you need it when granting the key access to the service account.
  2. Create a key on the key ring.
    gcloud kms keys create KMS_KEY_ID \
    --location=GCP_REGION \
    --keyring=KMS_KEYRING_ID \
    --purpose=encryption
      
    Write down this name because you need it when granting the key access to the service account.

Terraform

To create a keyring, use a Terraform resource.

resource "google_kms_key_ring" "keyring" {
  provider = google-beta
  name     = "keyring-name"
  location = "us-central1"
}

To create a key, use a Terraform resource.

resource "google_kms_crypto_key" "key" {
  provider = google-beta
  name     = "crypto-key-name"
  key_ring = google_kms_key_ring.keyring.id
  purpose  = "ENCRYPT_DECRYPT"
}

Apply the Terraform configuration:

terraform apply

Grant the service account access to the key

You only need to perform this procedure if you are using gcloud or the API.

To grant the service account access:

gcloud

gcloud kms keys add-iam-policy-binding KMS_KEY_ID \
--location=GCP_REGION \
--keyring=KMS_KEYRING_ID \
--member=serviceAccount:service-PROJECT_NUMBER@gcp-sa-cloud-sql.iam.gserviceaccount.com \
--role=roles/cloudkms.cryptoKeyEncrypterDecrypter

Terraform

To grant access to the key, use a Terraform resource.

resource "google_kms_crypto_key_iam_binding" "crypto_key" {
  provider      = google-beta
  crypto_key_id = google_kms_crypto_key.key.id
  role          = "roles/cloudkms.cryptoKeyEncrypterDecrypter"

  members = [
    "serviceAccount:${google_project_service_identity.gcp_sa_cloud_sql.email}",
  ]
}

Apply the Terraform configuration:

terraform apply

Create a Cloud SQL instance with CMEK

To create an instance with customer-managed encryption keys:

Console

  1. In the Google Cloud console, go to the Cloud SQL Instances page.

    Go to Cloud SQL Instances

  2. Click Create instance.
  3. Choose the database engine.
  4. Enter a name for the instance. Do not include sensitive or personally identifiable information in your instance name; it is externally visible. You do not need to include the project ID in the instance name. This is created automatically where appropriate (for example, in the log files).
  5. Enter the password for the 'root'@'%' user.
  6. Set the region for your instance. Place your instance in the same region as the resources that access it. In most cases, you don't need to specify a zone.
  7. In the Configuration options section, select all your configurations options until you reach Machine type and storage.
  8. Expand Machine type and storage.
  9. In the Encryption section, select Customer-managed key.
  10. Select the KMS key from the dropdown menu or manually enter the KMS_KEY_ID. Only KMS keys in the same project and region as the instance are displayed. To choose a KMS key belonging to a different project but in the same region, select Don't see your key? Enter key resource ID and enter the KMS_KEY_ID captured earlier.
  11. If the service account does not have permission to encrypt/decrypt with the selected key, a message displays. If this happens, click Grant to grant the service account the roles/cloudkms.cryptoKeyEncrypterDecrypter> IAM role on the selected KMS key.
  12. Once the configuration options are selected, click Create.
  13. You see a message explaining the implications of using customer-managed encryption key. Read and acknowledge it to proceed further with instance creation.

gcloud

gcloud sql instances create INSTANCE_NAME \
--project=PROJECT_ID \
--disk-encryption-key=KMS_KEY_ID \
--database-version=VERSION \
--cpu=NUMBER_CPUS \
--memory=MEMORY_SIZE \
--region=REGION \
--root-password=INSERT-PASSWORD-HERE

Terraform

To create an instance with CMEK, use a Terraform resource.

resource "google_sql_database_instance" "postgres_instance_with_cmek" {
  name                = "postgres-instance-cmek"
  provider            = google-beta
  region              = "us-central1"
  database_version    = "POSTGRES_14"
  encryption_key_name = google_kms_crypto_key.key.id
  settings {
    tier = "db-custom-2-7680"
  }
  deletion_protection = false # set to true to prevent destruction of the resource
}

Delete the changes

To delete your changes, do the following:

  1. To disable deletion protection, in your Terraform configuration file set the deletion_protection argument to false.
    deletion_protection =  "false"
  2. Apply the updated Terraform configuration by running the following command and entering yes at the prompt:
    terraform apply
  1. Remove resources previously applied with your Terraform configuration by running the following command and entering yes at the prompt:

    terraform destroy

REST v1

To create an instance with customer-managed encryption keys, pass diskEncryptionConfiguration to the command.

Before using any of the request data, make the following replacements:

  • project-id: The project ID
  • instance-id: The instance ID
  • region: The region
  • database-version: Emum version string (for example, POSTGRES_12)
  • kms-resource-id: The ID you received from creating a key.

HTTP method and URL:

POST https://sqladmin.googleapis.com/v1/projects/project-id/instances

Request JSON body:

{
  "name":"instance-id",
  "region":"region",
  "databaseVersion": "database-version",
  "diskEncryptionConfiguration" :
  {
      "kmsKeyName" : "kms-resource-id"
  },
  "settings":
  {
     "backupConfiguration":
      {
         "pointInTimeRecoveryEnabled": true,
         "enabled":true
      }
   }
}

To send your request, expand one of these options:

You should receive a JSON response similar to the following:

{
  "kind": "sql#operation",
  "targetLink": "https://sqladmin.googleapis.com/v1/projects/project-id/instances",
  "status": "PENDING",
  "user": "user@example.com",
  "insertTime": "2020-01-16T02:32:12.281Z",
  "operationType": "UPDATE",
  "name": "operation-id",
  "targetId": "instance-id",
  "selfLink": "https://sqladmin.googleapis.com/v1/projects/project-id/operations/operation-id",
  "targetProject": "project-id"
}
This example uses instances:insert.

REST v1beta4

To create an instance with customer-managed encryption keys, pass diskEncryptionConfiguration to the command.

Before using any of the request data, make the following replacements:

  • project-id: The project ID
  • instance-id: The instance ID
  • region: The region
  • database-version: Emum version string (for example, POSTGRES_12)
  • kms-resource-id: The ID you received from creating a key.

HTTP method and URL:

POST https://sqladmin.googleapis.com/sql/v1beta4/projects/project-id/instances

Request JSON body:

{
  "name":"instance-id",
  "region":"region",
  "databaseVersion": "database-version",
  "diskEncryptionConfiguration" :
  {
      "kmsKeyName" : "kms-resource-id"
  },
  "settings":
  {
     "backupConfiguration":
      {
         "pointInTimeRecoveryEnabled": true,
         "enabled":true
      }
   }
}

To send your request, expand one of these options:

You should receive a JSON response similar to the following:

{
  "kind": "sql#operation",
  "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/project-id/instances",
  "status": "PENDING",
  "user": "user@example.com",
  "insertTime": "2020-01-16T02:32:12.281Z",
  "operationType": "UPDATE",
  "name": "operation-id",
  "targetId": "instance-id",
  "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/project-id/operations/operation-id",
  "targetProject": "project-id"
}
This example uses instances:insert.

Create a backup for a CMEK-enabled instance

When you create a backup of a Cloud SQL instance, the backup is encrypted with the same primary key version as the primary instance's customer-managed key.

See Creating and managing on-demand and automatic backups.

You will see a message on the Create a backup form that says: "Your backup will be encrypted with the primary version of this instance's customer-managed encryption key. If anyone destroys or disables this key version, all backup data encrypted using that key version will be permanently lost. You can check the primary version for the key in Cloud KMS."

On the backups page, the list of backups enabled with customer-managed encryption keys have two extra columns. One column that shows that the backup is for a CMEK-enabled instance, and a column that displays the key version used to encrypt the backup.

Create a replica for a CMEK-enabled instance

When you create a read replica of a Cloud SQL instance in the same region, it inherits the same customer-managed encryption key as the parent instance. If you create a read replica in a different region, you are given a new list of customer-managed encryption keys to select from. Each region uses its own set of keys.

See Creating read replicas.

On the Create read replica page, you see the following information:

  1. The Encryption shows customer-managed.
  2. The Encryption key for the replica is displayed.
  3. There is a message saying "Your replica will be encrypted with the primary instance's customer-managed key. If anyone destroys this key, all data encrypted with it will be permanently lost."

For a cross-region replica, you see the following message:

"Your cross-region replica will be encrypted with the selected customer-managed key. If anyone destroys this key, all data encrypted with it will be permanently lost."

Create a clone of a CMEK-enabled instance

When you create a clone of Cloud SQL instance, it inherits the same customer-managed encryption key as the one used to encrypt the source instance.

See Cloning instances.

On the Create clone page, you see the following information:

  1. The Encryption shows customer-managed.
  2. The Encryption key for the clone is displayed.
  3. There is a message saying "Your clone will be encrypted with the source instance's customer-managed key. If anyone destroys this key, all data encrypted with it will be permanently lost."

View key information for a CMEK-enabled instance

Once you successfully create a Cloud SQL instance, you can look at the instance list or the instance overview page to see that it was created using a customer-managed encryption key. The details also show the key that was used to create the instance.

  1. In the Google Cloud console, go to the Cloud SQL Instances page.

    Go to Cloud SQL Instances

  2. In the Instances list, scroll to the right until you see the Encryption column. In this column, you see Google-managed and Customer-managed.
  3. Click an instance name to open its Overview page. The customer-managed encryption key is listed in the Configuration pane.

Use Cloud External Key Manager (Cloud EKM)

To protect data in Cloud SQL instances, you can use keys that you manage within a supported external key management partner. For more information, see Cloud External Key Manager, including the Considerations section.

When you are ready to create a Cloud EKM key, see Managing Cloud EKM keys. After a key is created, provide the key name when you create a Cloud SQL instance.

You can use Key Access Justifications (KAJ) as part of Cloud EKM. KAJ enables you to view the reason for each Cloud EKM request. Additionally, based on the justification provided, you can automatically approve or deny a request. To learn more, see the Overview.

Thus, KAJ provides extra control over your data by providing a justification for each attempt to decrypt the data.

Google lacks control over the availability of keys in an external key management partner system.

Disable and re-enable key versions

See the following topics:

Troubleshoot

This section describes things to try when you get an error message while setting up or using CMEK-enabled instances.

Cloud SQL administrator operations, such as create, clone, or update, might fail due to Cloud KMS errors, and missing roles or permissions. Common reasons for failure include a missing Cloud KMS key version, a disabled or destroyed Cloud KMS key version, insufficient IAM permissions to access the Cloud KMS key version, or the Cloud KMS key version is in a different region than the Cloud SQL instance. Use the following troubleshooting table to diagnose and resolve common problems.

Customer-managed encryption keys troubleshooting table

For this error... The issue might be... Try this...
Per-product, per-project service account not found The service account name is incorrect. Make sure you created a service account for the correct user project.

GO TO THE SERVICE ACCOUNTS PAGE.

Cannot grant access to the service account The user account does not have permission to grant access to this key version. Add the Organization Administrator role on your user or service account.

GO TO THE IAM ACCOUNTS PAGE

Cloud KMS key version is destroyed The key version is destroyed. If the key version is destroyed, you cannot use it to encrypt or decrypt data.
Cloud KMS key version is disabled The key version is disabled. Re-enable the Cloud KMS key version.

GO TO THE CRYPTO KEYS PAGE

Insufficient permission to use the Cloud KMS key The cloudkms.cryptoKeyEncrypterDecrypter role is missing on the user or service account you are using to run operations on Cloud SQL instances, or the Cloud KMS key version doesn't exist. Add the cloudkms.cryptoKeyEncrypterDecrypter role on your user or service account.

GO TO THE IAM ACCOUNTS PAGE


If the role is already on your account, see Creating a key to learn how to create a new key version. See note.
Cloud KMS key is not found The key version does not exist. Create a new key version. See Creating a key. See note.
Cloud SQL instance and Cloud KMS key version are in different regions The Cloud KMS key version and Cloud SQL instance must be in the same region. It does not work if the Cloud KMS key version is in a global region or multi-region. Create a key version in the same region where you want to create instances. See Creating a key. See note.

What's next