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 manually-created 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 beginIn the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Note: If you don't plan to keep the resources that you create in this procedure, create a project instead of selecting an existing project. After you finish these steps, you can delete the project, removing all resources associated with the project.Make sure that billing is enabled for your Google Cloud project.
Install the gcloud CLI.
If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.
To initialize the gcloud CLI, run the following command:
gcloud init
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Note: If you don't plan to keep the resources that you create in this procedure, create a project instead of selecting an existing project. After you finish these steps, you can delete the project, removing all resources associated with the project.Make sure that billing is enabled for your Google Cloud project.
Install the gcloud CLI.
If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.
To initialize the gcloud CLI, run the following command:
gcloud init
Enable the Cloud Key Management Service API.
Enable the Cloud SQL Admin API.
Your Cloud SQL instance is now enabled with CMEK.
Create a service accountYou 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:
roles/iam.serviceAccountUser
): Includes permissions to list service accounts, get details about a service account, and impersonate a service account.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 CLI 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.
gcloudgcloud beta services identity create \ --service=sqladmin.googleapis.com \ --project=PROJECT_IDTerraform
To create a service account, use a Terraform resource.
Apply the changesTo apply your Terraform configuration in a Google Cloud project, complete the steps in the following sections.
Prepare Cloud ShellSet the default Google Cloud project where you want to apply your Terraform configurations.
You only need to run this command once per project, and you can run it in any directory.
export GOOGLE_CLOUD_PROJECT=PROJECT_ID
Environment variables are overridden if you set explicit values in the Terraform configuration file.
Each Terraform configuration file must have its own directory (also called a root module).
.tf
extension—for example main.tf
. In this tutorial, the file is referred to as main.tf
.
mkdir DIRECTORY && cd DIRECTORY && touch main.tf
If you are following a tutorial, you can copy the sample code in each section or step.
Copy the sample code into the newly created main.tf
.
Optionally, copy the code from GitHub. This is recommended when the Terraform snippet is part of an end-to-end solution.
terraform init
Optionally, to use the latest Google provider version, include the -upgrade
option:
terraform init -upgrade
terraform plan
Make corrections to the configuration as necessary.
yes
at the prompt:
terraform apply
Wait until Terraform displays the "Apply complete!" message.
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 Note: You can use an externally managed key with CMEK using the Cloud EKM service to make the key available through Cloud KMS.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.
Warning: Never delete the primary key version that you initially use when you create your instance. You can't restore the backup for the instance if the key version that was originally used when the instance was created is destroyed. Even when the key version is rotated, the original key version must be maintained. If it is destroyed, it can't be re-created. Note: Sometimes, a Cloud SQL instance enabled with CMEK has the Cloud KMS key hosted in a different cloud project. For this scenario, when you enable VPC-SC, you must add the KMS key hosting project to the security perimeter. Note: Cloud KMS usage is subject to a quota. GKE calls the Cloud KMS API every time it performs a cryptographic operation. Confirm that you have enough quota to enable application-layer secrets encryption for your application.To create a Cloud KMS key:
ConsoleIn the Google Cloud console, go to the Key management page.
gcloud kms keyrings create KMS_KEYRING_ID \ --location=GCP_REGIONWrite down this name because you need it when granting the key access to the service account.
gcloud kms keys create KMS_KEY_ID \ --location=GCP_REGION \ --keyring=KMS_KEYRING_ID \ --purpose=encryptionWrite down this name because you need it when granting the key access to the service account.
To create a keyring, use a Terraform resource.
To create a key, use a Terraform resource.
Apply the Terraform configuration:
terraform applyGrant the service account access to the key
When creating the Cloud SQL instance with CMEK, you only need to perform this procedure if you are using gcloud or the API. You can perform this procedure if you run into permission issues after the instance is created.
To grant the service account access:
ConsoleIn the Google Cloud console, go to the Key management page.
Alternatively, you can also grant it in the project IAM page.
gcloudgcloud 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.cryptoKeyEncrypterDecrypterTerraform
To grant access to the key, use a Terraform resource.
Apply the Terraform configuration:
terraform applyCreate a Cloud SQL instance with CMEK Note: You can't enable customer-managed encryption keys on existing instances.
To create an instance with customer-managed encryption keys:
ConsoleIn the Google Cloud console, go to the Cloud SQL Instances page.
'root'@'%'
user.roles/cloudkms.cryptoKeyEncrypterDecrypter>
IAM role on the selected KMS key.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-HERETerraform
To create an instance with CMEK, use a Terraform resource.
Delete the changesTo delete your changes, do the following:
deletion_protection
argument to false
.
deletion_protection = "false"
yes
at the prompt:
terraform apply
Remove resources previously applied with your Terraform configuration by running the following command and entering yes
at the prompt:
terraform destroy
diskEncryptionConfiguration
to the command.
Before using any of the request data, make the following replacements:
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:
curl (Linux, macOS, or Cloud Shell) Note: The following command assumes that you have logged in to thegcloud
CLI with your user account by running gcloud init
or gcloud auth login
, or by using Cloud Shell, which automatically logs you into the gcloud
CLI . You can check the currently active account by running gcloud auth list
.
Save the request body in a file named request.json
, and execute the following command:
curl -X POST \PowerShell (Windows) Note: The following command assumes that you have logged in to the
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json; charset=utf-8" \
-d @request.json \
"https://sqladmin.googleapis.com/v1/projects/project-id/instances"
gcloud
CLI with your user account by running gcloud init
or gcloud auth login
. You can check the currently active account by running gcloud auth list
.
Save the request body in a file named request.json
, and execute the following command:
$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }Invoke-WebRequest `
-Method POST `
-Headers $headers `
-ContentType: "application/json; charset=utf-8" `
-InFile request.json `
-Uri "https://sqladmin.googleapis.com/v1/projects/project-id/instances" | Select-Object -Expand Content
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:
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:
curl (Linux, macOS, or Cloud Shell) Note: The following command assumes that you have logged in to thegcloud
CLI with your user account by running gcloud init
or gcloud auth login
, or by using Cloud Shell, which automatically logs you into the gcloud
CLI . You can check the currently active account by running gcloud auth list
.
Save the request body in a file named request.json
, and execute the following command:
curl -X POST \PowerShell (Windows) Note: The following command assumes that you have logged in to the
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json; charset=utf-8" \
-d @request.json \
"https://sqladmin.googleapis.com/sql/v1beta4/projects/project-id/instances"
gcloud
CLI with your user account by running gcloud init
or gcloud auth login
. You can check the currently active account by running gcloud auth list
.
Save the request body in a file named request.json
, and execute the following command:
$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }Invoke-WebRequest `
-Method POST `
-Headers $headers `
-ContentType: "application/json; charset=utf-8" `
-InFile request.json `
-Uri "https://sqladmin.googleapis.com/sql/v1beta4/projects/project-id/instances" | Select-Object -Expand Content
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. If your instance uses a CMEK created by Cloud KMS Autokey, the backup still uses the same key as the primary instance; Autokey doesn't create keys for backups.
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 instanceWhen 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.
On the Create read replica page, you see the following information:
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 instanceWhen 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:
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.
In the Google Cloud console, go to the Cloud SQL Instances page.
You can re-encrypt your existing Cloud SQL instances and replicas with the latest primary key version. For more information about re-encrypting your existing CMEK-enabled instance or replica, see About keys.
Note: Until re-encryption is completed, don't disable or destroy the existing key versions. Obtain the new primary key versionTo re-encrypt your instance or replica with a new version, you'll need the new primary key version. If you need a new key version for your instances, you'll need to rotate your key using Cloud Key Management Service. To rotate your primary key, see Rotate a key.
After your key rotation is complete, wait for the primary key change to be propagated before you re-encrypt your instances. If your key version change isn't consistent, your instance will continue to use the old key version after re-encryption. For more information, see Consistency of key versions.
After key rotation is complete, re-encrypt your existing CMEK-enabled instance or replica.
Note: If your new key version isn't consistent across Cloud SQL, the instance continues using the old key version after re-encryption. ConsoleIn the Google Cloud console, go to the Cloud SQL Instances page.
To re-encrypt the instance or replica, run the following command:
gcloud sql instances reencrypt INSTANCE_NAMEReplace
INSTANCE_NAME
with name of the instance or replica you are re-encrypting. REST v1
To re-encrypt your instance or replica with your new key, run the following command:
POST https://sqladmin.googleapis.com/v1/projects/PROJECT_ID/instances/INSTANCE_ID/reencrypt
Before using any of the request data, make the following replacements:
HTTP method and URL:
POST https://sqladmin.googleapis.com/v1/projects/PROJECT_ID/instances/INSTANCE_ID/reencrypt
To send your request, expand one of these options:
curl (Linux, macOS, or Cloud Shell) Note: The following command assumes that you have logged in to thegcloud
CLI with your user account by running gcloud init
or gcloud auth login
, or by using Cloud Shell, which automatically logs you into the gcloud
CLI . You can check the currently active account by running gcloud auth list
.
Execute the following command:
curl -X POST \PowerShell (Windows) Note: The following command assumes that you have logged in to the
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json; charset=utf-8" \
-d "" \
"https://sqladmin.googleapis.com/v1/projects/PROJECT_ID/instances/INSTANCE_ID/reencrypt"
gcloud
CLI with your user account by running gcloud init
or gcloud auth login
. You can check the currently active account by running gcloud auth list
.
Execute the following command:
$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }Invoke-WebRequest `
-Method POST `
-Headers $headers `
-Uri "https://sqladmin.googleapis.com/v1/projects/PROJECT_ID/instances/INSTANCE_ID/reencrypt" | Select-Object -Expand Content
You should receive a JSON response similar to the following:
{ "kind": "sql#operation", "targetLink": "https://sqladmin.googleapis.com/v1/projects/REST v1beta4 To re-encrypt your instance or replica with your new key, run the following command:project-id
/instances/instance-id
", "status": "PENDING", "user": "user@example.com", "insertTime": "2023-06-28T21:19:09.503Z", "operationType": "REENCRYPT", "name": "operation-id
", "targetId": "instance-id
", "selfLink": "https://sqladmin.googleapis.com/v1/projects/project-id
/operations/operation-id
", "targetProject": "project-id
" }
POST https://sqladmin.googleapis.com/v1beta4/projects/PROJECT_ID/instances/INSTANCE_ID/reencrypt
Before using any of the request data, make the following replacements:
HTTP method and URL:
POST https://sqladmin.googleapis.com/sql/v1beta4/projects/PROJECT_ID/instances/INSTANCE_ID/reencrypt
To send your request, expand one of these options:
curl (Linux, macOS, or Cloud Shell) Note: The following command assumes that you have logged in to thegcloud
CLI with your user account by running gcloud init
or gcloud auth login
, or by using Cloud Shell, which automatically logs you into the gcloud
CLI . You can check the currently active account by running gcloud auth list
.
Execute the following command:
curl -X POST \PowerShell (Windows) Note: The following command assumes that you have logged in to the
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json; charset=utf-8" \
-d "" \
"https://sqladmin.googleapis.com/sql/v1beta4/projects/PROJECT_ID/instances/INSTANCE_ID/reencrypt"
gcloud
CLI with your user account by running gcloud init
or gcloud auth login
. You can check the currently active account by running gcloud auth list
.
Execute the following command:
$cred = gcloud auth print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }Invoke-WebRequest `
-Method POST `
-Headers $headers `
-Uri "https://sqladmin.googleapis.com/sql/v1beta4/projects/PROJECT_ID/instances/INSTANCE_ID/reencrypt" | Select-Object -Expand Content
You should receive a JSON response similar to the following:
{ "kind": "sql#operation", "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/Automatic re-encryption backupsproject-id
/instances/instance-id
", "status": "PENDING", "user": "user@example.com", "insertTime": "2023-06-28T21:22:13.663Z", "operationType": "REENCRYPT", "name": "operation-id
", "targetId": "instance-id
", "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/project-id
/operations/operation-id
", "targetProject": "project-id
" }
When you re-encrypt a primary instance with a new primary key version, Cloud SQL automatically creates an on-demand backup called the re-encryption backup.
In your list of backups for your Cloud SQL instance, the re-encryption backup is listed as type on-demand
and labeled with backup created automatically for data before CMEK re-encryption
.
As with other on-demand backups, re-encryption backups persist until you delete them or delete the instance.
Re-encryption limitationsWhen you re-encrypt an instance, keep note of the following limitations:
For troubleshooting, see the Re-encryption troubleshooting table.
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.
Warning: If an external key is deleted or cannot be recovered, any Cloud SQL instances encrypted with that key become permanently inaccessible. Disable and re-enable key versionsSee the following topics:
TroubleshootThis 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 to your user or service account. 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. Insufficient permission to use the Cloud KMS key Thecloudkms.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. In the Google Cloud project that hosts the key, add the cloudkms.cryptoKeyEncrypterDecrypter
role to your user or service account.
cloudkms.cryptoKeyEncrypterDecrypter
role to your user or service account in the Google Cloud project that hosts the key. Note: If the instance is in a failed state during the create
operation, you must delete it, add the role to the account you are using, and create a new instance with an active Cloud KMS key version. Re-encryption troubleshooting table For this error... The issue might be... Try this... CMEK resource re-encryption failed because the Cloud KMS key is inaccessible. Please ensure that the primary key version is enabled and the permission is granted properly. The key version is disabled or doesn't grant proper permissions.
Re-enable the Cloud KMS key version:
In the Google Cloud project that hosts the key, confirm the cloudkms.cryptoKeyEncrypterDecrypter
role is granted to your user or service account:
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4