使用自行管理的 SSL 证书

自行管理的 SSL 证书是您自行获取、预配和续订的证书。您可以使用此资源来确保客户端与负载均衡器之间的通信安全。

自行管理的证书可以是以下证书类型的任意组合:

  • 网域验证 (DV)
  • 组织验证 (OV)
  • 扩展验证 (EV)

以下负载均衡器支持自行管理的证书:

  • 全球证书
    • 全球外部应用负载均衡器
    • 传统应用负载均衡器
    • 外部代理网络负载均衡器(使用目标 SSL 代理)
  • 区域证书
    • 区域外部应用负载均衡器
    • 内部应用负载均衡器

本页介绍获取有效 Compute Engine 证书,然后上传证书以创建 Google Cloud SSL 证书资源的过程。

如需使用 Certificate Manager 创建 Google 管理的证书,请参阅部署概览

须知事项

权限

如需执行本指南中的任务,您必须能够在项目中创建和修改 SSL 证书。如果存在以下任一情况,您可以执行此操作:

第 1 步:创建私钥和证书

如果您已具有证书授权机构 (CA) 颁发的私钥和证书,请跳过此部分并转到创建 SSL 证书资源

选择或创建私钥

Google Cloud SSL 证书同时包含私钥和证书本身,两者均采用 PEM 格式。您的私钥必须符合以下条件:

  • 必须采用 PEM 格式
  • 无法通过密码进行保护。Google Cloud 以专属加密格式存储您的私钥。
  • 其加密算法必须是 RSA-2048 或 ECDSA P-256。

如需创建新的私钥,请使用以下 OpenSSL 命令之一。

  • 创建 RSA-2048 私钥:

    openssl genrsa -out PRIVATE_KEY_FILE 2048
    
  • 创建 ECDSA P-256 私钥:

    openssl ecparam -name prime256v1 -genkey -noout -out PRIVATE_KEY_FILE
    

PRIVATE_KEY_FILE 替换为新私钥文件的路径和文件名。

创建证书签名请求 (CSR)

拥有私钥后,您便可以使用 OpenSSL 生成 PEM 格式的证书签名请求 (CSR)。您的 CSR 必须符合以下条件:

  • 必须采用 PEM 格式。
  • 必须具有公用名 (CN) 或主题备用名称 (SAN) 特性。实际上,您的证书应该同时包含 CNSAN 特性(即使是用于单个网域),这是因为,现代的客户端(例如 macOS 和 iOS 的当前版本)不仅仅依赖于 CN 特性。

如需创建 CSR,请按照以下步骤操作:

  1. 创建一个 OpenSSL 配置文件。 在以下示例中,主题备用名称是在 [sans_list] 中定义的。

    cat <<'EOF' >CONFIG_FILE
    [req]
    default_bits              = 2048
    req_extensions            = extension_requirements
    distinguished_name        = dn_requirements
    prompt                    = no
    
    [extension_requirements]
    basicConstraints          = CA:FALSE
    keyUsage                  = nonRepudiation, digitalSignature, keyEncipherment
    subjectAltName            = @sans_list
    
    [dn_requirements]
    countryName               = Country Name (2 letter code)
    stateOrProvinceName       = State or Province Name (full name)
    localityName              = Locality Name (eg, city)
    0.organizationName        = Organization Name (eg, company)
    organizationalUnitName    = Organizational Unit Name (eg, section)
    commonName                = Common Name (e.g. server FQDN or YOUR name)
    emailAddress              = Email Address
    
    [sans_list]
    DNS.1                     = SUBJECT_ALTERNATIVE_NAME_1
    DNS.2                     = SUBJECT_ALTERNATIVE_NAME_2
    
    EOF
    
  2. 运行以下 OpenSSL 命令以创建证书签名请求 (CSR) 文件。该命令是交互式的;系统会提示您输入特性(主题备用名称除外,您已在上一步中在 CONFIG_FILE[sans_list] 中定义了)。

    openssl req -new -key PRIVATE_KEY_FILE \
        -out CSR_FILE \
        -config CONFIG_FILE
    

对于这两个步骤,请替换以下内容:

  • CONFIG_FILE:OpenSSL 配置文件的路径,包括文件名(您可以在完成此过程后删除该文件)
  • SUBJECT_ALTERNATIVE_NAME_1SUBJECT_ALTERNATIVE_NAME_2:证书的主题备用名称

    如果您的证书仅用于一个主机名,则仅应定义一个与公用名匹配的主题备用名称。如果您需要的主题备用名称超过两个,请将其添加到配置文件中,注意递增 DNS 后面的数字(DNS.3DNS.4 等等)。

  • PRIVATE_KEY_FILE:私钥文件的路径

  • CSR_FILE:CSR 的路径,包括文件名

为 CSR 签名

当证书授权机构 (CA) 为您的 CSR 签名时,会使用其专属私钥来创建证书。使用以下任一方法为 CSR 签名:

使用受大众信任的 CA

如果您请求由受大众信任的 CA 为您的 CSR 签名,则所有信任该公共 CA 的客户端都会信任生成的证书。公共 CA 只需要您的 CSR 即可生成签名证书。

使用您自己的内部 CA

如果您管理着自己的 CA,则可以使用它来为 CSR 签名。如果您的客户端也已配置为信任您自己的 CA,则使用 CA 为 CSR 签名以创建内部信任的证书。

使用自签名证书

如果您使用用于创建 CSR 的同一私钥为 CSR 签名,则表示您已经创建了自签名证书。自签名证书只能用于测试用途。

Google Cloud 不支持自签名服务器证书的客户端验证。因此,您必须将客户端配置为跳过证书验证。例如,您可以创建一个网络浏览器客户端,该客户端显示一条消息,询问您是否要信任自签名证书。

如果您管理着自己的 CA,或者想要创建用于测试的自签名证书,则可以使用以下 OpenSSL 命令:

openssl x509 -req \
    -signkey PRIVATE_KEY_FILE \
    -in CSR_FILE \
    -out CERTIFICATE_FILE \
    -extfile CONFIG_FILE \
    -extensions extension_requirements \
    -days TERM

替换以下内容:

  • PRIVATE_KEY_FILE:您的 CA 的私钥路径;如果创建用于测试的自签名证书,则此私钥与用于创建 CSR 的私钥为同一个。
  • CSR_FILE:CSR 的路径
  • CERTIFICATE_FILE:要创建的证书文件的路径
  • TERM:对证书进行验证的客户端认定该证书有效的天数(从现在起算)

公用名中的通配符

自行管理的 SSL 证书可在公用名中使用通配符。例如,公用名为 *.example.com. 的证书与主机名 www.example.comfoo.example.com 匹配,但与 a.b.example.comexample.com 不匹配。当负载均衡器选择证书时,它始终会先将主机名与不带通配符的证书进行匹配,然后再与带通配符的证书进行匹配。

带通配符片段(例如 f*.example.com)的证书不受支持。

第 2 步:创建自行管理的 SSL 证书资源

您必须拥有私钥和证书,然后才能创建 Google Cloud SSL 证书资源。如果您尚未创建或获得私钥和证书,请参阅创建私钥和证书

控制台

您可以在 Google Cloud 控制台中的经典证书标签页上使用全球 SSL 证书。无法在 Google Cloud 控制台中创建区域级 SSL 证书。使用 gcloud 或 REST API。

  1. 转到 Google Cloud 控制台中的经典证书标签页。
    转到“经典证书”标签页
  2. 点击创建 SSL 证书
  3. 为证书输入名称和可选说明。
  4. 选择上传我的证书
  5. 粘贴您的证书,或点击上传以导航到您的证书文件。
    您可以选择将 CA 证书链包含到证书所在的文件中。Google Cloud 不会为您验证证书链,您必须自行负责验证。
  6. 粘贴您的私钥,或点击上传以导航到您的私钥文件。
  7. 点击创建

gcloud

如需创建全球 SSL 证书,请使用带有 --global 标志的 gcloud compute ssl-certificates create 命令:

gcloud compute ssl-certificates create CERTIFICATE_NAME \
    --certificate=CERTIFICATE_FILE \
    --private-key=PRIVATE_KEY_FILE \
    --global

如需创建区域级 SSL 证书,请使用带有 --region 标志的 gcloud compute ssl-certificates create 命令:

gcloud compute ssl-certificates create CERTIFICATE_NAME \
    --certificate=CERTIFICATE_FILE \
    --private-key=PRIVATE_KEY_FILE \
    --region=REGION

请替换以下内容:

  • CERTIFICATE_NAME:要创建的全球性证书资源的名称
  • CERTIFICATE_FILE:PEM 格式的证书文件的路径

    您可以选择将 CA 证书链包含到证书所在的文件中。Google Cloud 不会为您验证证书链 - 您需要自行负责验证。

  • PRIVATE_KEY_FILE:PEM 格式的私钥的路径;私钥无法通过密码进行保护

  • REGION:区域性 SSL 证书的区域(如果适用)。

    如果此证书资源用于内部应用负载均衡器或区域外部应用负载均衡器,则该区域必须与负载均衡器所在的区域相同。

API

如需使用 API 方法,您必须先读取证书和私钥文件,因为 API 请求必须发送这些文件的内容。

读取证书和私钥文件,然后创建 SSL 证书。以下示例显示了如何使用 Python 执行此操作。

对于全球 SSL 证书,请使用 sslCertificates.insert API 方法:

from pathlib import Path
from pprint import pprint
from typing import Union

from googleapiclient import discovery


def create_certificate(
    project_id: str,
    certificate_file: Union[str, Path],
    private_key_file: Union[str, Path],
    certificate_name: str,
    description: str = "Certificate created from a code sample.",
) -> dict:
    """
    Create a global SSL self-signed certificate within your Google Cloud project.

    Args:
        project_id: project ID or project number of the Cloud project you want to use.
        certificate_file: path to the file with the certificate you want to create in your project.
        private_key_file: path to the private key you used to sign the certificate with.
        certificate_name: name for the certificate once it's created in your project.
        description: description of the certificate.

    Returns:
        Dictionary with information about the new global SSL self-signed certificate.
    """
    service = discovery.build("compute", "v1")

    # Read the cert into memory
    with open(certificate_file) as f:
        _temp_cert = f.read()

    # Read the private_key into memory
    with open(private_key_file) as f:
        _temp_key = f.read()

    # Now that the certificate and private key are in memory, you can create the
    # certificate resource
    ssl_certificate_body = {
        "name": certificate_name,
        "description": description,
        "certificate": _temp_cert,
        "privateKey": _temp_key,
    }
    request = service.sslCertificates().insert(
        project=project_id, body=ssl_certificate_body
    )
    response = request.execute()
    pprint(response)
    return response

对于区域级 SSL 证书,请使用 regionSslCertificates.insert API 方法:

from pathlib import Path
from pprint import pprint
from typing import Union

from googleapiclient import discovery


def create_regional_certificate(
    project_id: str,
    region: str,
    certificate_file: Union[str, Path],
    private_key_file: Union[str, Path],
    certificate_name: str,
    description: str = "Certificate created from a code sample.",
) -> dict:
    """
    Create a regional SSL self-signed certificate within your Google Cloud project.

    Args:
        project_id: project ID or project number of the Cloud project you want to use.
        region: name of the region you want to use.
        certificate_file: path to the file with the certificate you want to create in your project.
        private_key_file: path to the private key you used to sign the certificate with.
        certificate_name: name for the certificate once it's created in your project.
        description: description of the certificate.

        Returns:
        Dictionary with information about the new regional SSL self-signed certificate.
    """
    service = discovery.build("compute", "v1")

    # Read the cert into memory
    with open(certificate_file) as f:
        _temp_cert = f.read()

    # Read the private_key into memory
    with open(private_key_file) as f:
        _temp_key = f.read()

    # Now that the certificate and private key are in memory, you can create the
    # certificate resource
    ssl_certificate_body = {
        "name": certificate_name,
        "description": description,
        "certificate": _temp_cert,
        "privateKey": _temp_key,
    }
    request = service.regionSslCertificates().insert(
        project=project_id, region=region, body=ssl_certificate_body
    )
    response = request.execute()
    pprint(response)

    return response

如需查看其他代码示例,请参阅 API 参考页面

第 3 步:将 SSL 证书与目标代理相关联

您必须将至少一个 SSL 证书与每个目标 HTTPS 或 SSL 代理相关联。您可以为目标代理配置多个 SSL 证书,但总数量不能超过每个目标 HTTPS 或目标 SSL 代理的 SSL 证书数量上限。您可以在同一个目标代理上引用多个自行管理的证书。

控制台

使用 Google Cloud 控制台修改现有负载均衡器时,SSL 证书会自动与相应的目标代理相关联。

gcloud

如需将全球 SSL 证书与目标 HTTPS 代理相关联,请使用带 --global--global-ssl-certificates 标志的 gcloud compute target-https-proxies update 命令:

gcloud compute target-https-proxies update TARGET_PROXY_NAME \
    --global \
    --ssl-certificates=SSL_CERTIFICATE_LIST \
    --global-ssl-certificates

如需将全球 SSL 证书与目标 SSL 代理相关联,请使用 gcloud compute target-ssl-proxies update 命令:

gcloud compute target-ssl-proxies update TARGET_PROXY_NAME \
    --ssl-certificates=SSL_CERTIFICATE_LIST

如需将区域级 SSL 证书与目标 HTTPS 代理相关联,请使用带有 --region--ssl-certificates-region 标志的 gcloud compute target-https-proxies update 命令:

gcloud compute target-https-proxies update TARGET_PROXY_NAME \
    --region=REGION \
    --ssl-certificates=SSL_CERTIFICATE_LIST \
    --ssl-certificates-region=REGION

请替换以下内容:

  • TARGET_PROXY_NAME:负载均衡器的目标代理名称
  • REGION(如果适用):区域性目标代理和区域性 SSL 证书的区域;区域必须匹配
  • SSL_CERTIFICATE_LIST:以英文逗号分隔的 Google Cloud SSL 证书名称列表

    确保引用的证书列表包含所有旧的有效 SSL 证书,以及新的 SSL 证书。gcloud compute target-ssl-proxies update 命令会使用新值替换 --ssl-certificates 的原始值。

API

如需将全球 SSL 证书与目标 HTTPS 代理相关联,请向 targetHttpsProxies.insert 方法发出 POST 请求,并将 PROJECT_ID 替换为您的项目 ID。

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/targetHttpsProxy

{
"name": "l7-xlb-proxy",
"urlMap": "projects/PROJECT_ID/global/urlMaps/l7-xlb-map",
"sslCertificates": /projectsPROJECT_IDglobal/sslCertificates/SSL_CERT_NAME
}

如需将全球 SSL 证书与目标 HTTPS 代理相关联,请向 targetSslProxies.insert 方法发出 POST 请求,并将 PROJECT_ID 替换为您的项目 ID。

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/targetSslProxy

{
"name": "l7-ssl-proxy",
"sslCertificates": /projectsPROJECT_IDglobal/sslCertificates/SSL_CERT_NAME
}

如需将区域 SSL 证书与目标 HTTPS 代理相关联,请向 targetHttpsProxies.insert 方法发出 POST 请求,并将 PROJECT_ID 替换为您的项目 ID。

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/targetHttpsProxy

{
"name": "l7-xlb-proxy",
"urlMap": "projects/PROJECT_ID/global/urlMaps/l7-ilb-map",
"region": "us-west1"
"sslCertificates": /projectsPROJECT_IDregions/us-west1/sslCertificates/SSL_CERT_NAME
}

第 4 步:更新 DNS A 和 AAAA 记录以指向负载均衡器的 IP 地址

在您的注册商网站、DNS 主机或 ISP(管理 DNS 记录的任何位置)上,为您的网域和任何子网域添加或更新 DNS A 记录(对于 IPv4)和 DNS AAAA 记录(对于 IPv6),使其指向与负载均衡器的一条或多条转发规则关联的 IP 地址。

如果您使用的是 Cloud DNSCloud Domains,请设置您的域名更新您的域名服务器

如果您对单个证书使用多个网域,则必须为所有网域和任何子网域添加或更新 DNS 记录,以使其全部指向负载均衡器的 IP 地址。

等待 DNS 传播完成后,您可以通过运行 dig 命令来验证设置。例如,假设您的网域是 www.example.com。运行以下 dig 命令:

dig www.example.com
; <<>> DiG 9.10.6 <<>> www.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31748
;; flags: qr rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;www.example.com.           IN  A

;; ANSWER SECTION:
www.example.com.        1742    IN  CNAME   www.example.com.edgekey.net.
www.example.com.edgekey.net. 21330 IN   CNAME   www.example.com.edgekey.net.globalredir.akadns.net.
www.example.com.edgekey.net.globalredir.akadns.net. 3356 IN CNAME   e6858.dsce9.akamaiedge.net.
e6858.dsce9.akamaiedge.net. 19  IN  A   203.0.113.5

;; Query time: 43 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Wed Jun 03 16:54:44 PDT 2020
;; MSG SIZE  rcvd: 193

在此示例中,203.0.113.5 是您的负载均衡器的 IP 地址。

第 5 步:使用 OpenSSL 进行测试

负载均衡器最多可能需要 30 分钟才会开始使用自行管理的 SSL 证书。

如需进行测试,请运行以下 OpenSSL 命令,注意将 DOMAIN 替换为您的 DNS 名称,并将 IP_ADDRESS 替换为您的负载均衡器的 IP 地址。

echo | openssl s_client -showcerts -servername DOMAIN -connect IP_ADDRESS:443 -verify 99 -verify_return_error

此命令会输出负载均衡器提供给客户端的证书。输出应包含证书链和 Verify return code: 0 (ok) 以及其他详细信息。

使用自行管理的 SSL 证书

以下部分介绍了如何列出、查看、删除和替换 SSL 证书资源。

列出 SSL 证书

控制台

您可以在证书管理器页面的经典证书标签页上查看全局 SSL 证书的状态。 无法在 Google Cloud 控制台中维护区域级 SSL 证书。使用 gcloud 或 REST API。

  1. 转到 Google Cloud 控制台中的“经典证书”标签页。
    转到“经典证书”标签页
  2. (可选)过滤 SSL 证书列表。

gcloud

如需列出全球 SSL 证书,请使用带 --global 标志的 gcloud compute ssl-certificates list 命令:

gcloud compute ssl-certificates list \
   --global

如需列出区域级 SSL 证书,请使用带 region 过滤条件的 gcloud compute ssl-certificates list 命令:

gcloud compute ssl-certificates list \
   --filter="region:(REGION ...)"

请替换以下内容:

  • REGION:Google Cloud 区域;以空格分隔列表形式添加多个区域

描述 SSL 证书

控制台

您可以在证书管理器页面的经典证书标签页上查看有关全局 SSL 证书的更多详细信息。

  1. 转到 Google Cloud 控制台中的“经典证书”页面。
    转到“经典证书”标签页
  2. (可选)过滤 SSL 证书列表。
  3. 如需查看更多详细信息,请点击证书名称。

gcloud

如需描述全球 SSL 证书,请使用带 --global 标志的 gcloud compute ssl-certificates describe 命令:

gcloud  compute ssl-certificates describe CERTIFICATE_NAME \
   --global

如需描述区域级 SSL 证书,请使用带 --region 标志的 gcloud compute ssl-certificates describe 命令:

gcloud compute ssl-certificates describe CERTIFICATE_NAME \
   --region=REGION

请替换以下内容:

  • CERTIFICATE_NAME:SSL 证书的名称
  • REGION:Google Cloud 区域

删除多个 SSL 证书

如需删除 SSL 证书,您必须先更新引用该证书的各个目标代理。对于每个目标代理,运行相应的 gcloud update 命令来更新目标代理的 SSL_CERTIFICATE_LIST,以使其不再包含需要删除的 SSL 证书。每个目标 SSL 代理或目标 HTTPS 代理必须至少引用一个 SSL 证书。

更新目标代理后,您便可删除 SSL 证书了。

控制台

您可以在证书管理器页面的经典证书标签页上删除全局 SSL 证书。

  1. 转到 Google Cloud 控制台中的“经典证书”标签页。
    转到“经典证书”标签页
  2. 选择要删除的 SSL 证书。
  3. 点击删除
  4. 再次点击删除进行确认。

gcloud

如需删除全球 SSL 证书,请使用带 --global 标志的 gcloud compute ssl-certificates delete 命令:

gcloud compute ssl-certificates delete CERTIFICATE_NAME \
    --global

如需删除区域级 SSL 证书,请使用带 --region 标志的 gcloud compute ssl-certificates delete 命令:

gcloud compute ssl-certificates delete CERTIFICATE_NAME \
    --region=REGION

请替换以下内容:

  • CERTIFICATE_NAME:SSL 证书的名称
  • REGION:Google Cloud 区域

在 SSL 证书到期之前替换或续订证书

如果您需要替换、续订或轮替 SSL 证书,请按以下步骤操作:

  1. 运行当前证书的 gcloud compute ssl-certificates describe 命令,检查证书是否即将过期。

  2. 创建新的 SSL 证书资源。新 SSL 证书在项目中必须具有唯一的名称。

  3. 更新目标代理以分离旧的 SSL 证书并添加新证书。请务必包含要保留的任何其他现有 SSL 证书。

    为避免停机,请运行带有 --ssl-certificates 标志的单个 gcloud 命令。例如:

    对于全球外部应用负载均衡器

    使用带有 --global 标志的 gcloud compute target-https-proxies update 命令。

    gcloud compute target-https-proxies update TARGET_PROXY_NAME \
       --global \
       --ssl-certificates=new-ssl-cert,other-certificates \
       --global-ssl-certificates
    

    对于区域外部应用负载均衡器和内部应用负载均衡器

    使用带有 --region 标志的 gcloud compute target-https-proxies update 命令。

    gcloud compute target-https-proxies update TARGET_PROXY_NAME \
       --region REGION \
       --ssl-certificates=new-ssl-cert,other-certificates \
       --global-ssl-certificates
    

    对于外部代理网络负载均衡器

    使用带有 --backend-service 标志的 gcloud compute target-ssl-proxies update 命令。

    gcloud compute target-ssl-proxies update TARGET_PROXY_NAME \
       --ssl-certificates=new-ssl-cert,other-certificates
    
  4. 通过运行以下 OpenSSL 命令来验证负载均衡器是否正在提供替换证书:

    echo | openssl s_client -showcerts -connect IP_ADDRESS:443 -verify 99 -verify_return_error
    
  5. 等待 15 分钟,以确保替换操作已传播到所有 Google Front End (GFE)。

  6. (可选)删除旧的 SSL 证书

定期轮替 SSL 证书

示例解决方案会定期检查用于 Google Cloud 负载均衡器的证书状态,并在证书达到其生命周期的指定百分比时轮替证书。该工具使用通过 Certificate Authority Service 配置的 CA。

此解决方案适用于以下负载均衡器:

  • 全球外部应用负载均衡器
  • 传统应用负载均衡器
  • 区域级外部应用负载均衡器
  • 内部应用负载均衡器
  • 使用 SSL 代理的外部代理网络负载均衡器

后续步骤