使用客户管理的加密密钥 (CMEK)

本页面介绍如何为 CMEK 设置服务账号和密钥,以及如何创建使用 CMEK 的实例。如需详细了解如何在 Cloud SQL 中使用 CMEK,请参阅 CMEK 概览

准备工作

  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 Google Cloud project.

  4. Install the Google Cloud CLI.
  5. To initialize the gcloud CLI, run the following command:

    gcloud init
  6. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  7. Make sure that billing is enabled for your Google Cloud project.

  8. Install the Google Cloud CLI.
  9. To initialize the gcloud CLI, run the following command:

    gcloud init
  10. 确保您的用户账号具有 Cloud SQL Admin 角色。

    转到 IAM 页面

  11. Enable the Cloud Key Management Service API.

    Enable the API

  12. Enable the Cloud SQL Admin API.

    Enable the API

创建具有 CMEK 的 Cloud SQL 实例的工作流

  1. 仅限 gcloud 和 API 用户:为每个需要 CMEK 的项目创建服务账号
  2. 创建密钥环和密钥并为每个密钥设置位置。该位置指的是 Google Cloud 区域。
  3. 仅限 gcloud 和 API 用户向服务账号授予对密钥的访问权限
  4. 记下密钥 ID (KMS_KEY_ID)、密钥位置 (GCP_REGION) 和密钥环 ID (KMS_KEYRING_ID)。
  5. 转到项目并使用以下选项创建 Cloud SQL 实例
    1. CMEK 所在的位置
    2. 客户管理的密钥配置
    3. CMEK ID

您的 Cloud SQL 实例现已启用 CMEK。

创建服务账号

您需要为每个需要 CMEK 的项目创建一个服务账号。

要允许用户管理服务账号,请授予以下角色之一:

  • Service Account User (roles/iam.serviceAccountUser):包括列出服务账号、获取服务账号的详细信息以及模拟服务账号的权限。
  • Service Account Admin (roles/iam.serviceAccountAdmin):包括列出服务账号和获取服务账号的详细信息的权限。此外,还包括创建、更新和删除服务账号的权限,以及查看或更改服务账号的 Cloud SQL for SQL Server 政策的权限。

目前,您只能使用 gcloud CLI 命令创建 CMEK 所需的服务账号类型。如果您使用的是控制台,则 Cloud SQL 会自动为您创建此服务账号。

gcloud

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

Terraform

如需创建服务账号,请使用 Terraform 资源

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

应用更改

如需在 Google Cloud 项目中应用 Terraform 配置,请完成以下部分中的步骤。

准备 Cloud Shell

  1. 启动 Cloud Shell
  2. 设置要在其中应用 Terraform 配置的默认 Google Cloud 项目。

    您只需为每个项目运行一次以下命令,即可在任何目录中运行它。

    export GOOGLE_CLOUD_PROJECT=PROJECT_ID

    如果您在 Terraform 配置文件中设置显式值,则环境变量会被替换。

准备目录

每个 Terraform 配置文件都必须有自己的目录(也称为“根模块”)。

  1. Cloud Shell 中,创建一个目录,并在该目录中创建一个新文件。文件名必须具有 .tf 扩展名,例如 main.tf。在本教程中,该文件称为 main.tf
    mkdir DIRECTORY && cd DIRECTORY && touch main.tf
  2. 如果您按照教程进行操作,可以在每个部分或步骤中复制示例代码。

    将示例代码复制到新创建的 main.tf 中。

    (可选)从 GitHub 中复制代码。如果端到端解决方案包含 Terraform 代码段,则建议这样做。

  3. 查看和修改要应用到您的环境的示例参数。
  4. 保存更改。
  5. 初始化 Terraform。您只需为每个目录执行一次此操作。
    terraform init

    (可选)如需使用最新的 Google 提供程序版本,请添加 -upgrade 选项:

    terraform init -upgrade

应用更改

  1. 查看配置并验证 Terraform 将创建或更新的资源是否符合您的预期:
    terraform plan

    根据需要更正配置。

  2. 通过运行以下命令并在提示符处输入 yes 来应用 Terraform 配置:
    terraform apply

    等待 Terraform 显示“应用完成!”消息。

  3. 打开您的 Google Cloud 项目以查看结果。在 Google Cloud 控制台的界面中找到资源,以确保 Terraform 已创建或更新它们。

上述命令会返回服务账号名称。在向服务账号授予对密钥的访问权限的过程中,您将使用此服务账号名称。

创建密钥

您可以在 Cloud SQL 实例所属的 Google Cloud 项目中创建密钥,也可以在单独的用户项目中创建密钥。Cloud KMS 密钥环的位置必须与您要在其中创建 Cloud SQL 实例的区域相匹配。多区域密钥或全球区域密钥将不会起作用。如果区域不匹配,Cloud SQL 实例创建请求会失败。

如需创建 Cloud KMS 密钥,请执行以下操作:

控制台

  1. 在 Google Cloud 控制台中,进入密钥管理页面。

    前往密钥管理

  2. 点击创建密钥环
  3. 添加密钥环名称。请记下此名称,因为您在向服务账号授予对密钥的访问权限时需要用到此名称。
  4. 添加密钥环位置
  5. 点击创建。此时会打开创建密钥页面。
  6. 添加密钥名称
  7. 选择用途(对称或非对称)。
  8. 选择轮替周期开始日期
  9. 点击创建
  10. 密钥表上,点击最后一列中的三个点,然后选择复制资源 ID 或将其记录下来。这就是 KMS_KEY_ID。在向服务账号授予密钥访问权限时,您需要 KMS_KEY_ID。

gcloud

  1. 创建新的密钥环。
    gcloud kms keyrings create KMS_KEYRING_ID \
    --location=GCP_REGION
      
    记录此名称,因为您在向服务账号授予密钥访问权限时需要用到此名称。
  2. 针对该密钥环创建密钥。
    gcloud kms keys create KMS_KEY_ID \
    --location=GCP_REGION \
    --keyring=KMS_KEYRING_ID \
    --purpose=encryption
      
    记录此名称,因为您在向服务账号授予密钥访问权限时需要用到此名称。

Terraform

如需创建密钥环,请使用 Terraform 资源

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

如需创建密钥,请使用 Terraform 资源

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

应用 Terraform 配置:

terraform apply

向服务账号授予密钥的访问权限

创建具有 CMEK 的 Cloud SQL 实例时,您只需在使用 gcloud 或 API 时执行此过程。如果您在创建实例后遇到权限问题,可以执行此过程。

如需向服务账号授予访问权限,请执行以下操作:

控制台

  1. 在 Google Cloud 控制台中,进入密钥管理页面。

    前往密钥管理

  2. 如需选择托管密钥的项目,请使用项目选择器。
  3. 点击密钥环的名称。
  4. 点击密钥的名称。
  5. 点击权限标签页。
  6. 如需打开面板,请点击授予访问权限
  7. 输入服务账号作为主账号,并选择“Cloud KMS CryptoKey Encrypter/Decrypter”作为角色。
  8. 点击保存

或者,您也可以在项目 IAM 页面中授予访问权限。

进入项目 IAM 页面

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

如需授予对密钥的访问权限,请使用 Terraform 资源

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}",
  ]
}

应用 Terraform 配置:

terraform apply

创建具有 CMEK 的 Cloud SQL 实例

如需创建具有 CMEK 的实例,请按如下所述操作:

控制台

  1. 在 Google Cloud 控制台中,转到 Cloud SQL 实例页面。

    转到“Cloud SQL 实例”

  2. 点击创建实例
  3. 选择数据库引擎。
  4. 输入实例的名称。请勿在实例名称中包含敏感信息或个人身份信息,因为此名称对外可见。无需在实例名称中包含项目 ID。此 ID 将在适当的位置(例如在日志文件中)自动创建。
  5. 'root'@'%' 用户输入密码。
  6. 为您的实例设置区域。 将实例与访问实例的资源置于相同区域内。大多数情况下,您不需要指定地区。
  7. 配置选项部分,选择所有配置选项,一直到机器类型和存储
  8. 展开机器类型和存储
  9. 加密部分中,选择客户管理的密钥
  10. 从下拉菜单中选择 KMS 密钥或手动输入 KMS_KEY_ID。系统仅显示与该实例位于同一项目和区域的 KMS 密钥。如需选择属于其他项目但位于同一区域的 KMS 密钥,请选择“没有看到您的密钥?输入密钥资源 ID,然后输入之前捕获的 KMS_KEY_ID。
  11. 如果该服务账号无权使用所选密钥进行加密/解密,则会显示一条消息。如果发生这种情况,请点击授权,向服务账号授予所选 KMS 密钥的 roles/cloudkms.cryptoKeyEncrypterDecrypter> IAM 角色。
  12. 选择配置选项后,点击创建
  13. 您将看到一条消息,说明使用 CMEK 的影响。阅读并确认该消息,以便进一步创建实例。

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

如需创建使用 CMEK 的实例,请使用 Terraform 资源

resource "google_sql_database_instance" "default" {
  name                = "sqlserver-instance-cmek"
  provider            = google-beta
  region              = "us-central1"
  database_version    = "SQLSERVER_2019_STANDARD"
  root_password       = "INSERT-PASSWORD-HERE "
  encryption_key_name = google_kms_crypto_key.key.id
  settings {
    tier = "db-custom-2-7680"
  }
  # set `deletion_protection` to true, will ensure that one cannot accidentally delete this instance by
  # use of Terraform whereas `deletion_protection_enabled` flag protects this instance at the GCP level.
  deletion_protection = false
}

删除更改

如需删除更改,请执行以下操作:

  1. 如需停用删除防护,请在 Terraform 配置文件中将 deletion_protection 参数设置为 false
    deletion_protection =  "false"
  2. 运行以下命令并在提示符处输入 yes,以应用更新后的 Terraform 配置:
    terraform apply
  1. 通过运行以下命令并在提示符处输入 yes,移除之前使用 Terraform 配置应用的资源:

    terraform destroy

REST v1

如需创建具有 CMEK 的实例,请向命令传递 diskEncryptionConfiguration

在使用任何请求数据之前,请先进行以下替换:

  • project-id:项目 ID
  • instance-id:实例 ID
  • region:区域
  • database-version:Emum 版本字符串(例如 SQLSERVER_2017_STANDARD)
  • kms-resource-id:您通过创建密钥收到的 ID。

HTTP 方法和网址:

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

请求 JSON 正文:

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

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

{
  "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"
}
此示例使用 instances:insert

REST v1beta4

如需创建具有 CMEK 的实例,请向命令传递 diskEncryptionConfiguration

在使用任何请求数据之前,请先进行以下替换:

  • project-id:项目 ID
  • instance-id:实例 ID
  • region:区域
  • database-version:Emum 版本字符串(例如 SQLSERVER_2017_STANDARD)
  • kms-resource-id:您通过创建密钥收到的 ID。

HTTP 方法和网址:

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

请求 JSON 正文:

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

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

{
  "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"
}
此示例使用 instances:insert

为启用了 CMEK 的实例创建备份

创建 Cloud SQL 实例的备份时,请使用与主实例的客户管理的密钥相同的主密钥版本来加密备份。

请参阅创建和管理按需备份与自动备份

您会在创建备份表单中看到一条消息:“您的备份将使用此实例的 CMEK 的主要版本进行加密。如果任何人销毁或停用此密钥版本,则使用此密钥版本加密的所有备份数据都将永久丢失。您可以在 Cloud KMS 中检查密钥的主要版本。”

在备份页面上,使用 CMEK 启用的备份列表有两个额外的列。一列显示备份用于启用 CMEK 的实例,一列显示用于加密备份的密钥版本。

查看启用了 CMEK 的实例的密钥信息

成功创建 Cloud SQL 实例后,您可以查看实例列表或实例概览页面,了解该实例是使用 CMEK 创建的。详细信息还显示用于创建实例的密钥。

  1. 在 Google Cloud 控制台中,转到 Cloud SQL 实例页面。

    转到“Cloud SQL 实例”

  2. 在实例列表中,滚动到右侧,直到看到加密列。在此列中,您会看到由 Google 管理由客户管理
  3. 点击一个实例名称,打开其概览页面。配置窗格中会列出 CMEK。

重新加密现有的启用了 CMEK 的实例或副本

您可以使用最新的主密钥版本重新加密现有的 Cloud SQL 实例和副本。如需详细了解如何重新加密现有的启用了 CMEK 的实例或副本,请参阅密钥简介

获取新的主密钥版本

  • 如需使用新版本重新加密实例或副本,您将需要新的主密钥版本。如果您的实例需要新的密钥版本,您将需要使用 Cloud Key Management Service 轮替密钥。如需轮替主密钥,请参阅轮替密钥

  • 密钥轮替完成后,请等待主密钥更改传播,然后再重新加密实例。如果密钥版本更改不一致,实例将在重新加密后继续使用旧密钥版本。如需了解详情,请参阅密钥版本的一致性

重新加密启用了 CMEK 的实例

密钥轮替完成后,重新加密现有的启用了 CMEK 的实例或副本。

控制台

  1. 在 Google Cloud 控制台中,转到 Cloud SQL 实例页面。

    转到“Cloud SQL 实例”

  2. 如需打开实例的概览页面,请点击实例名称。
  3. 配置部分中,点击重新加密实例
  4. 在出现的对话框中,点击重新加密以确认您的选择。

gcloud

如需重新加密实例或副本,请运行以下命令:

gcloud sql instances reencrypt INSTANCE_NAME
INSTANCE_NAME 替换为您要重新加密的实例或副本的名称。

REST v1

如需使用新密钥重新加密实例或副本,请运行以下命令:

    POST https://sqladmin.googleapis.com/v1/projects/PROJECT_ID/instances/INSTANCE_ID/reencrypt

在使用任何请求数据之前,请先进行以下替换:

  • PROJECT_ID:项目 ID
  • INSTANCE_ID:实例 ID

HTTP 方法和网址:

POST https://sqladmin.googleapis.com/v1/projects/PROJECT_ID/instances/INSTANCE_ID/reencrypt

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

{
  "kind": "sql#operation",
  "targetLink": "https://sqladmin.googleapis.com/v1/projects/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"
}

REST v1beta4

如需使用新密钥重新加密实例或副本,请运行以下命令:
    POST https://sqladmin.googleapis.com/v1beta4/projects/PROJECT_ID/instances/INSTANCE_ID/reencrypt

在使用任何请求数据之前,请先进行以下替换:

  • PROJECT_ID:项目 ID
  • INSTANCE_ID:实例 ID

HTTP 方法和网址:

POST https://sqladmin.googleapis.com/sql/v1beta4/projects/PROJECT_ID/instances/INSTANCE_ID/reencrypt

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

{
  "kind": "sql#operation",
  "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/project-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"
}

自动重新加密备份

当您使用新的主密钥版本重新加密主实例时,Cloud SQL 会自动创建称为“重新加密备份”的按需备份。

在 Cloud SQL 实例的备份列表中,重新加密备份会列为 on-demand 类型,并带有 backup created automatically for data before CMEK re-encryption 标签。

与其他按需备份一样,重新加密备份会一直保留,直到您删除它们或删除实例。

重新加密限制

重新加密实例时,请注意以下限制:

  • 重新加密操作期间,您无法对实例执行任何其他管理操作。
  • 重新加密操作会触发停机,具体停机时间取决于实例或副本大小。
  • 实例重新加密时,实例的副本不会重新加密。您需要单独重新加密每个副本。
  • 重新加密实例时,备份不会自动使用新密钥版本重新加密。如需将备份或时间点恢复恢复到进行备份后的时间,您需要保留加密备份所用的 Cloud KMS 密钥版本。

如需进行问题排查,请参阅重新加密问题排查表

使用 Cloud External Key Manager (Cloud EKM)

为了保护 Cloud SQL 实例中的数据,您可以使用在受支持的外部密钥管理合作伙伴内管理的密钥。如需了解详情,请参阅 Cloud External Key Manager,包括注意事项部分。

当您准备好创建 Cloud EKM 密钥时,请参阅管理 Cloud EKM 密钥。创建密钥后,请在创建 Cloud SQL 实例时提供该密钥的名称。

您可以在 Cloud EKM 中使用 Key Access Justifications (KAJ)。KAJ 可让您查看每个 Cloud EKM 请求的原因。此外,根据提供的理由,您可以自动批准或拒绝请求。如需了解详情,请参阅概览

因此,KAJ 通过为每次解密数据的尝试提供理由来提供对数据的额外控制。

Google 无法控制外部密钥管理合作伙伴系统中密钥的可用性。

停用和重新启用密钥版本

请参阅以下主题:

问题排查

本部分介绍在设置或使用启用了 CMEK 的实例时针对收到的错误消息要尝试的操作。

由于 Cloud KMS 错误以及缺少角色或权限,Cloud SQL 管理员操作(例如创建、克隆或更新)可能会失败。常见的失败原因如下:缺少 Cloud KMS 密钥版本;Cloud KMS 密钥版本已被停用或被销毁;IAM 权限不足,无法访问 Cloud KMS 密钥版本;或者 Cloud KMS 密钥版本与 Cloud SQL 实例位于不同的区域。请使用以下问题排查表来诊断和解决常见问题。

CMEK 问题排查表

错误… 可能的问题… 请尝试以下操作…
找不到各项产品和项目的服务账号 服务账号名称不正确。 确保您已为正确的用户项目创建了服务账号。

转到“服务账号”页面

无法向服务账号授予访问权限 用户账号无权授予对此密钥版本的访问权限。 为您的用户或服务账号添加 Organization Administrator 角色。

转至 IAM 账号页面

Cloud KMS 密钥版本已被销毁 密钥版本已被销毁。 如果密钥版本遭到销毁,您就无法使用该版本来加密或解密数据。
Cloud KMS 密钥版本已停用 密钥版本已停用。 重新启用 Cloud KMS 密钥版本。

转到“加密密钥”页面

权限不足,无法使用 Cloud KMS 密钥 您用于对 Cloud SQL 实例运行操作的用户或服务账号缺少 cloudkms.cryptoKeyEncrypterDecrypter 角色,或 Cloud KMS 密钥版本不存在。 在托管密钥的 Google Cloud 项目中,为您的用户或服务账号添加 cloudkms.cryptoKeyEncrypterDecrypter 角色。

转至 IAM 账号页面


如果您已向您的账号授予此角色,请参阅创建密钥以了解如何创建新的密钥版本。请参阅备注。
找不到 Cloud KMS 密钥 密钥版本不存在。 创建新的密钥版本。请参阅创建密钥。 请参阅备注。
Cloud SQL 实例和 Cloud KMS 密钥版本位于不同区域 Cloud KMS 密钥版本和 Cloud SQL 实例必须位于同一区域。如果 Cloud KMS 密钥版本位于全球区域或多区域中,则密钥不起作用。 在要创建实例的同一区域中创建密钥版本。请参阅创建密钥。请参阅备注。
Cloud KMS 密钥版本已恢复,但实例仍处于暂停状态。 密钥版本已停用或未授予适当的权限。 重新启用密钥版本,并在托管密钥的 Google Cloud 项目中向您的用户或服务账号授予 cloudkms.cryptoKeyEncrypterDecrypter 角色。

重新加密问题排查表

错误… 可能的问题… 请尝试以下操作…
CMEK 资源重新加密失败,因为 Cloud KMS 密钥无法访问。请确保已启用主密钥版本,且已正确授予权限。 密钥版本已停用或未授予适当的权限。

重新启用 Cloud KMS 密钥版本:

进入“加密密钥”页面

在托管密钥的 Google Cloud 项目中,确认已向您的用户或服务账号授予 cloudkms.cryptoKeyEncrypterDecrypter 角色:

转至 IAM 账号页面

由于服务器内部错误,CMEK 资源重新加密失败。请稍后重试 服务器内部错误。 重试重新加密。如需了解详情,请参阅重新加密现有的启用了 CMEK 的实例或副本

后续步骤