配置 SSL/TLS 证书

本页面介绍如何对实例强制使用 SSL/TLS 加密以确保所有连接均已加密。您还可以详细了解 Cloud SQL 如何使用自行管理的 SSL/TLS 证书安全地连接到 Cloud SQL 实例。

概览

当您创建实例时,Cloud SQL 会自动创建一份服务器证书 (server-ca.pem)。 我们建议您强制所有连接使用 SSL/TLS

如需使用 SSL/TLS 证书验证客户端/服务器身份,您需要创建客户端证书并将证书下载到 MySQL 客户端宿主机。

如果您对实例强制执行 SSL,则该实例需要重启。更改 SSL/TLS 证书后,可能也需要重启。如果需要重启,则 Cloud SQL 会自动为您重启实例。重启实例可能会导致停机。

强制执行 SSL/TLS 加密

您可以使用 SSL 模式设置,通过以下方式强制执行 SSL 加密:

  • 允许非 SSL/非 TLS 和 SSL/TLS 连接。 对于 SSL/TLS 连接,不验证客户端证书。这是默认设置。

  • 仅允许使用 SSL/TLS 加密的连接。 对于 SSL 连接,不验证客户端证书。

  • 仅允许使用 SSL/TLS 加密并具有有效客户端证书的连接。

如果您为 Cloud SQL 实例选择允许非 SSL/非 TLS 和 SSL/TLS 连接,则将接受 SSL/TLS 连接以及未加密的不安全连接。如果您不要求所有连接使用 SSL/TLS,则系统仍会允许未加密的连接。因此,如果您使用公共 IP 地址访问实例,我们强烈建议您对所有连接强制执行 SSL。

您可以使用 SSL/TLS 证书直接连接到实例,也可以使用 Cloud SQL Auth 代理Cloud SQL 连接器进行连接。如果您使用 Cloud SQL Auth 代理或 Cloud SQL 连接器进行连接,则连接会使用 SSL/TLS 自动加密。无论 SSL 模式设置如何,使用 Cloud SQL Auth 代理和 Cloud SQL 连接器还会自动验证客户端和服务器身份。

如需启用“要求使用 SSL/TLS”,请执行以下操作:

控制台

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

    转到“Cloud SQL 实例”

  2. 如需打开实例的概览页面,请点击实例名称。
  3. 点击 SQL 导航菜单中的连接
  4. 选择安全标签页。
  5. 从下列选项中选择一项:
    • 允许未加密的网络流量(不推荐)
    • 只允许 SSL 连接。此选项仅允许使用 SSL/TLS 加密的连接。不验证证书。
    • 需要受信任的客户端证书。此选项仅允许来自使用有效客户端证书的客户端且经过 SSL 加密的连接。

gcloud

   gcloud sql instances patch INSTANCE_NAME \
   --ssl-mode=SSL_ENFORCEMENT_MODE
  

SSL_ENFORCEMENT_MODE 替换为以下某个选项:

  • ALLOW_UNENCRYPTED_AND_ENCRYPTED 允许非 SSL/非 TLS 和 SSL/TLS 连接。对于 SSL 连接,不验证客户端证书。此设置为默认值。
  • ENCRYPTED_ONLY 仅允许使用 SSL/TLS 加密的连接。对于 SSL 连接,不验证客户端证书。
  • TRUSTED_CLIENT_CERTIFICATE_REQUIRED 仅允许使用 SSL/TLS 加密并具有有效客户端证书的连接。
  • 如需了解详情,请参阅 Cloud SQL for MySQL 的设置

Terraform

如需强制执行 SSL/TLS 加密,请使用 Terraform 资源

resource "google_sql_database_instance" "mysql_instance" {
  name             = "mysql-instance"
  region           = "asia-northeast1"
  database_version = "MYSQL_8_0"
  settings {
    tier = "db-f1-micro"
    ip_configuration {
      # The following SSL enforcement options only allow connections encrypted with SSL/TLS and with
      # valid client certificates. Please check the API reference for other SSL enforcement options:
      # https://cloud.google.com/sql/docs/postgres/admin-api/rest/v1beta4/instances#ipconfiguration
      ssl_mode = "TRUSTED_CLIENT_CERTIFICATE_REQUIRED"
    }
  }
  # 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
}

应用更改

如需在 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 已创建或更新它们。

删除更改

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

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

    terraform destroy

REST v1

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

    • PROJECT_ID:项目 ID
    • SSL_ENFORCEMENT_MODE:使用以下任一选项:
      • ALLOW_UNENCRYPTED_AND_ENCRYPTED:允许非 SSL/非 TLS 和 SSL/TLS 连接。 对于 SSL 连接,不验证客户端证书。此设置为默认值。
      • ENCRYPTED_ONLY:仅允许使用 SSL/TLS 加密的连接。
      • TRUSTED_CLIENT_CERTIFICATE_REQUIRED:仅允许使用 SSL/TLS 加密并具有有效客户端证书的连接。
    • INSTANCE_ID:实例 ID

    HTTP 方法和网址:

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

    请求 JSON 正文:

    
    {
      "settings": {
        "ipConfiguration": {"sslMode": "SSL_ENFORCEMENT_MODE"}
      }
    }
    

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

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

REST v1beta4

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

    • PROJECT_ID:项目 ID
    • SSL_ENFORCEMENT_MODE:使用以下任一选项:
      • ALLOW_UNENCRYPTED_AND_ENCRYPTED:允许非 SSL/非 TLS 和 SSL/TLS 连接。 对于 SSL 连接,不验证客户端证书。此设置为默认值。
      • ENCRYPTED_ONLY:仅允许使用 SSL/TLS 加密的连接。
      • TRUSTED_CLIENT_CERTIFICATE_REQUIRED:仅允许使用 SSL/TLS 加密并具有有效客户端证书的连接。
    • INSTANCE_ID:实例 ID

    HTTP 方法和网址:

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

    请求 JSON 正文:

    {
      "settings": {
        "ipConfiguration": {"sslMode": "SSL_ENFORCEMENT_MODE"}
      }
    }
    

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

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

服务器证书

当您创建实例时,Cloud SQL 会自动创建一个服务器证书。只要此服务器证书有效,您就无需主动管理服务器证书。但是,服务器证书是有失效日期的(即 10 年);此日期过后,该证书就不再有效,客户端也无法再使用该证书与您的实例之间建立安全连接。 系统会定期通知您服务器证书即将到期。通知在失效日期前的以下天数发送:90、30、10、2 和 1。

您可以获取服务器证书的相关信息,例如该证书的创建时间和到期时间。您也可以手动创建一个新证书。

控制台

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

    转到“Cloud SQL 实例”

  2. 如需打开实例的概览页面,请点击实例名称。
  3. 点击 SQL 导航菜单中的连接
  4. 选择安全标签页。
  5. 前往管理服务器证书部分。

    您可以在表中查看服务器证书的失效日期。

gcloud

  1. 获取有关服务证书的信息:
    gcloud beta sql ssl server-ca-certs list \
    --instance=INSTANCE_NAME
  2. 创建服务器证书:
    gcloud beta sql ssl server-ca-certs create \
    --instance=INSTANCE_NAME
  3. 将证书信息下载到本地 PEM 文件中:
    gcloud beta sql ssl server-ca-certs list \
    --format="value(cert)" \
    --instance=INSTANCE_NAME > \
    FILE_PATH/FILE_NAME.pem
  4. 通过将下载的文件复制到客户端宿主机上并替换现有的 server-ca.pem 文件,将所有客户端更新为使用新信息。

Terraform

如需提供服务器证书信息作为输出,请使用 Terraform 数据源

  1. 将以下内容添加到 Terraform 配置文件中:
       data "google_sql_ca_certs" "ca_certs" {
         instance = google_sql_database_instance.default.name
       }
    
       locals {
         furthest_expiration_time = reverse(sort([for k, v in data.google_sql_ca_certs.ca_certs.certs : v.expiration_time]))[0]
         latest_ca_cert           = [for v in data.google_sql_ca_certs.ca_certs.certs : v.cert if v.expiration_time == local.furthest_expiration_time]
       }
    
       output "db_latest_ca_cert" {
         description = "Latest CA certificate used by the primary database server"
         value       = local.latest_ca_cert
         sensitive   = true
       }
       
  2. 如要创建 server-ca.pem 文件,请运行以下命令:
       terraform output db_latest_ca_cert > server-ca.pem
       

客户端证书

新建客户端证书

您最多可为每个实例创建 10 个客户端证书。如需创建客户端证书,您必须具有 Cloud SQL Admin IAM 角色

以下是您需要了解的关于客户端证书的重要注意事项:

  • 如果您丢失了证书的私钥,则必须新建一个新密钥,私钥无法恢复。
  • 默认情况下,客户端证书的有效期为 10 年。
  • 当客户端证书即将到期时,您不会收到通知。
  • 您的 Cloud SQL 实例必须处于运行状态才能创建 SSL 证书。

控制台

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

    转到“Cloud SQL 实例”

  2. 如需打开实例的概览页面,请点击实例名称。
  3. 点击 SQL 导航菜单中的连接
  4. 选择安全标签页。
  5. 点击创建客户端证书
  6. 创建客户端证书对话框中,添加一个唯一名称。
  7. 点击创建
  8. 已创建新的 SSL 证书对话框的第一部分,点击下载 client-key.pem,将私钥下载到名为 client-key.pem 的文件中。
  9. 在第二部分,点击下载 client-cert.pem,将客户端证书下载到名为 client-cert.pem 的文件中。
  10. 在第三部分,点击下载 server-ca.pem,将服务器证书下载到名为 server-ca.pem 的文件中。
  11. 点击关闭

gcloud

  1. 使用 ssl client-certs create 命令创建客户端证书:

    gcloud sql ssl client-certs create CERT_NAME client-key.pem \
    --instance=INSTANCE_NAME
  2. 使用 ssl client-certs describe 命令检索您刚刚创建的证书的公钥,并将其复制到 client-cert.pem 文件中:

    gcloud sql ssl client-certs describe CERT_NAME \
    --instance=INSTANCE_NAME \
    --format="value(cert)" > client-cert.pem
  3. 使用 instances describe 命令将服务器证书复制到 server-ca.pem 文件:

    gcloud sql instances describe INSTANCE_NAME \
    --format="value(serverCaCert.cert)" > server-ca.pem

Terraform

如需创建客户端证书,请使用 Terraform 资源

resource "google_sql_ssl_cert" "mysql_client_cert" {
  common_name = "mysql_common_name"
  instance    = google_sql_database_instance.mysql_instance.name
}

REST v1

  1. 创建一个 SSL/TLS 证书,为其指定对于此实例唯一的名称:

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

    • project-id:项目 ID
    • instance-id:实例 ID
    • client-cert-name:客户端证书名称

    HTTP 方法和网址:

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

    请求 JSON 正文:

    {
      "commonName" : "client-cert-name"
    }
    

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

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

  2. 将响应中英文引号内的所有证书内容(不包括英文引号本身)复制到本地文件中,如下所示:
    1. serverCaCert.cert 复制到 server-ca.pem
    2. clientCert.cert 复制到 client-cert.pem
    3. certPrivateKey 复制到 client-key.pem
  3. 在使用任何请求数据之前,请先进行以下替换:

    • project-id:项目 ID
    • instance-id:实例 ID
    • activation-policy:激活政策为 ALWAYSNEVER

    HTTP 方法和网址:

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

    请求 JSON 正文:

    {
      "settings": {
        "activationPolicy": "activation-policy"
      }
    }
    

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

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

    {
      "kind": "sql#operation",
      "targetLink": "https://sqladmin.googleapis.com/v1/projects/project-id/instances/instance-id",
      "status": "PENDING",
      "user": "user@example.com",
      "insertTime": "2020-01-20T21:30:35.667Z",
      "operationType": "RESTART",
      "name": "operation-id",
      "targetId": "instance-id",
      "selfLink": "https://sqladmin.googleapis.com/v1/projects/project-id/operations/operation-id",
      "targetProject": "project-id"
    }
    

REST v1beta4

  1. 创建一个 SSL/TLS 证书,为其指定对于此实例唯一的名称:

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

    • project-id:项目 ID
    • instance-id:实例 ID
    • client-cert-name:客户端证书名称

    HTTP 方法和网址:

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

    请求 JSON 正文:

    {
      "commonName" : "client-cert-name"
    }
    

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

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

  2. 将响应中英文引号内的所有证书内容(不包括英文引号本身)复制到本地文件中,如下所示:
    1. serverCaCert.cert 复制到 server-ca.pem
    2. clientCert.cert 复制到 client-cert.pem
    3. certPrivateKey 复制到 client-key.pem
  3. 在使用任何请求数据之前,请先进行以下替换:

    • project-id:项目 ID
    • instance-id:实例 ID
    • activation-policy:激活政策为 ALWAYSNEVER

    HTTP 方法和网址:

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

    请求 JSON 正文:

    {
      "settings": {
        "activationPolicy": "activation-policy"
      }
    }
    

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

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

    {
      "kind": "sql#operation",
      "targetLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/project-id/instances/instance-id",
      "status": "PENDING",
      "user": "user@example.com",
      "insertTime": "2020-01-20T21:30:35.667Z",
      "operationType": "RESTART",
      "name": "operation-id",
      "targetId": "instance-id",
      "selfLink": "https://sqladmin.googleapis.com/sql/v1beta4/projects/project-id/operations/operation-id",
      "targetProject": "project-id"
    }
    

此时,您会获得如下结果:

  • 另存为 server-ca.pem 的服务器证书。
  • 另存为 client-cert.pem 的客户端公钥证书。
  • 另存为 client-key.pem 的客户端私钥。

根据您在建立连接时所使用工具的不同,这三个项目的指定方式也会有所不同。例如,使用 MySQL 客户端建立连接时,这三个文件分别是 --ssl-ca--ssl-cert--ssl-key 命令选项的值。有关使用 MySQL 客户端和 SSL/TLS 的示例连接,请参阅使用 MySQL 客户端连接

后续步骤