使用私有证书授权机构设置双向 TLS

本页面介绍了如何使用 Certificate Authority Service 创建私有证书授权机构 (CA) 并将证书上传到 Certificate Manager TrustConfig 资源。

您还将创建为应用负载均衡器配置双向 TLS 所需的网络安全资源。

准备工作

  • 查看双向 TLS 概览
  • 安装 Google Cloud CLI。如需全面了解此工具,请参阅 gcloud CLI 概览。您可以在 API 和 gcloud CLI 参考文档中找到与负载均衡相关的命令。

    如果您之前未运行过 gcloud CLI,请先运行 gcloud init 进行身份验证。

  • 确保您知道如何创建 CA 池

  • 如果您使用的是全球外部应用负载均衡器或传统版应用负载均衡器,请确保您已使用以下任一受支持的后端设置负载均衡器:

    • 虚拟机实例组后端
    • Cloud Storage 存储桶(只有在以下情况下才受支持:除后端存储桶外,至少还有一个后端服务也连接到负载均衡器)
    • Cloud Run、App Engine 或 Cloud Run functions
    • 混合连接
  • 如果您使用的是区域级外部应用负载均衡器、跨区域内部应用负载均衡器或区域级内部应用负载均衡器,请确保您已设置负载均衡器,并使用以下任一受支持的后端:

    • 虚拟机实例组后端
    • Cloud Run
    • 混合连接

权限

如需获得完成本指南所需的权限,请让您的管理员为您授予项目的以下 IAM 角色:

  • Compute Load Balancer Admin (roles/compute.loadBalancerAdmin)(如需创建负载均衡器资源,例如 TargetHTTPProxy
  • Certificate Manager Owner (roles/certificatemanager.owner)(如需使用 Certificate Manager 资源)
  • Compute Network Admin (roles/compute.networkAdmin) 和 Compute Security Admin (roles/compute.securityAdmin)(如需创建安全和网络组件)
  • Project Creator (roles/resourcemanager.projectCreator)(如需创建项目 [可选])

如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限

您也可以通过自定义角色或其他预定义角色来获取所需的权限。

创建私有 CA

使用 CA Service 创建私有 CA,然后创建根证书:

  1. 如需创建 CA 池,请使用 gcloud privateca pools create 命令

    gcloud privateca pools create CA_POOL \
       --location=us-central1
    

    CA_POOL 替换为父级 CA 池的 ID 或名称。

  2. 如需在 CA 池中创建私有 CA,请使用 gcloud privateca roots create 命令

    gcloud privateca roots create CA_ROOT \
       --pool=CA_POOL \
       --subject="CN=my-ca, O=Test LLC" \
       --location=us-central1
    

    请替换以下内容:

    • CA_ROOT:私有 CA 的 ID 或名称
    • CA_POOL:父级 CA 池的 ID 或名称
  3. 如需描述新 CA 并创建 root.cert 文件,请使用 gcloud privateca roots describe 命令

    gcloud privateca roots describe CA_ROOT \
       --pool=CA_POOL \
       --location=us-central1 \
       --format='value(pemCaCertificates)' > root.cert
    
    export ROOT=$(cat root.cert | sed 's/^[ ]*//g' | tr '\n' $ | sed 's/\$/\\n/g')

    请替换以下内容:

    • CA_ROOT:私有 CA 的 ID 或名称
    • CA_POOL:父级 CA 池的 ID 或名称

    详情请参阅以下内容:

使用私有 CA 创建 TrustConfig

使用通过私有 CA 生成的根证书创建代表 PKI 的 Certificate Manager TrustConfig 资源。我们假设 TrustConfig 资源是一个简单的受信任证书存储区,它具有一个表示根证书的信任锚。

在以下步骤中,将 TRUST_CONFIG_NAME 替换为 TrustConfig 资源的名称。

  • 要创建 trust_config.yaml 文件,请使用以下命令:

    cat << EOF > trust_config.yaml
    name: TRUST_CONFIG_NAME
    trustStores:
    - trustAnchors:
       - pemCertificate: "${ROOT?}"
    EOF
    
  • 如需创建 Certificate Manager TrustConfig 资源,请使用 gcloud certificate-manager trust-configs import 命令

    gcloud certificate-manager trust-configs import TRUST_CONFIG_NAME  \
       --source=trust_config.yaml \
       --location=REGION
    

    替换以下内容:

    REGION:将 global 用于跨区域内部应用负载均衡器、全球外部应用负载均衡器或传统应用负载均衡器。对于区域级外部应用负载均衡器或区域级内部应用负载均衡器,请使用您在其中配置了负载均衡器的区域。

创建客户端身份验证资源

借助客户端身份验证(也称为 ServerTLSPolicy)资源,您可以指定在验证客户端证书时使用的服务器端 TLS 模式和 TrustConfig 资源。当客户端向负载均衡器提供无效证书或没有证书时,clientValidationMode 指定客户端连接的处理方式。 如需了解详情,请参阅 MTLS 客户端验证模式

  • clientValidationMode 设置为 ALLOW_INVALID_OR_MISSING_CLIENT_CERT 时,即使验证失败或缺少客户端证书,所有请求都会传递给后端。
  • clientValidationMode 设置为 REJECT_INVALID 时,只有提供能够针对 TrustConfig 资源进行验证的客户端证书的请求才会传递给后端。

如需创建 ServerTLSPolicy 资源,请完成以下步骤:

  1. 根据您希望处理连接的方式,选择以下选项之一。

    在以下步骤中,将 SERVER_TLS_POLICY_NAME 替换为服务器 TLS 政策的名称,并将 PROJECT_ID 替换为您的 Google Cloud 项目的 ID。

    • 方法 1clientValidationMode 设置为 ALLOW_INVALID_OR_MISSING_CLIENT_CERT

      要创建 server_tls_policy.yaml 文件,请使用以下命令:

      全局

      对于外部应用负载均衡器和跨区域内部应用负载均衡器,请使用以下命令:

      cat << EOF > server_tls_policy.yaml
      name: SERVER_TLS_POLICY_NAME
      mtlsPolicy:
        clientValidationMode: ALLOW_INVALID_OR_MISSING_CLIENT_CERT
        clientValidationTrustConfig: projects/PROJECT_ID/locations/global/trustConfigs/TRUST_CONFIG_NAME
      EOF
      

      区域级

      对于区域级外部应用负载均衡器和区域级内部应用负载均衡器,请使用以下命令:

      cat << EOF > server_tls_policy.yaml
      name: SERVER_TLS_POLICY_NAME
      mtlsPolicy:
        clientValidationMode: ALLOW_INVALID_OR_MISSING_CLIENT_CERT
        clientValidationTrustConfig: projects/PROJECT_ID/locations/REGION/trustConfigs/TRUST_CONFIG_NAME
      EOF
      
    • 方法 2:将 clientValidationMode 设置为 REJECT_INVALID

      要创建 server_tls_policy.yaml 文件,请使用以下命令:

      全局

      对于外部应用负载均衡器和跨区域内部应用负载均衡器,请使用以下命令:

      cat << EOF > server_tls_policy.yaml
      name: SERVER_TLS_POLICY_NAME
      mtlsPolicy:
        clientValidationMode: REJECT_INVALID
        clientValidationTrustConfig: projects/PROJECT_ID/locations/global/trustConfigs/TRUST_CONFIG_NAME
      EOF
      

      区域级

      对于区域级外部应用负载均衡器和区域级内部应用负载均衡器,请使用以下命令:

      cat << EOF > server_tls_policy.yaml
      name: SERVER_TLS_POLICY_NAME
      mtlsPolicy:
        clientValidationMode: REJECT_INVALID
        clientValidationTrustConfig: projects/PROJECT_ID/locations/REGION/trustConfigs/TRUST_CONFIG_NAME
      EOF
      
  2. 如需创建 ServerTlsPolicy 资源,请使用 gcloud network-security server-tls-policies import 命令

    全局

    对于外部应用负载均衡器和跨区域内部应用负载均衡器,请使用以下命令:

    gcloud network-security server-tls-policies import SERVER_TLS_POLICY_NAME \
      --source=server_tls_policy.yaml \
      --location=global
    

    区域级

    对于区域级外部应用负载均衡器和区域级内部应用负载均衡器,请使用以下命令:

    gcloud network-security server-tls-policies import SERVER_TLS_POLICY_NAME \
      --source=server_tls_policy.yaml \
      --location=REGION
    
  3. 可选:列出当前项目指定位置中的所有客户端身份验证 (ServerTlsPolicies) 资源。

    控制台

    1. 在 Google Cloud 控制台中,进入客户端身份验证页面。

      前往客户端身份验证

    2. 系统会显示所有 ServerTlsPolicies 资源。

    gcloud

    如需列出所有客户端身份验证 (ServerTlsPolicies) 资源,请使用 gcloud network-security server-tls-policies list 命令

    gcloud network-security server-tls-policies list \
      --location=REGION
    

    替换以下内容:

    REGION:将 global 用于跨区域内部应用负载均衡器、全球外部应用负载均衡器或传统应用负载均衡器。对于区域级外部应用负载均衡器或区域级内部应用负载均衡器,请使用您在其中配置了负载均衡器的区域。

为负载均衡器设置 mTLS

要使双向 TLS 身份验证正常运行,在设置负载均衡器后,您需要使用 ServerTLSPolicy 资源更新目标 HTTPS 代理。

  1. 确保您已创建客户端身份验证 (ServerTLSPolicy) 资源。如需了解相关说明,请参阅创建客户端身份验证资源

  2. 如需列出项目中的所有目标 HTTPS 代理,请使用 gcloud compute target-https-proxies list 命令

    gcloud compute target-https-proxies list
    

    记下目标 HTTPS 代理的名称,用于附加 ServerTLSPolicy 资源。此名称在后面的步骤中称为 TARGET_HTTPS_PROXY_NAME

  3. 如需将目标 HTTPS 代理的配置导出到文件,请使用 gcloud compute target-https-proxies export 命令

    全局

      gcloud compute target-https-proxies export TARGET_HTTPS_PROXY_NAME \
          --destination=TARGET_PROXY_FILENAME \
          --global
      

    替换以下内容:

    • TARGET_HTTPS_PROXY_NAME:目标代理的名称。
    • TARGET_PROXY_FILENAME:YAML 文件的名称。例如 mtls_target_proxy.yaml

    区域级

     gcloud compute target-https-proxies export TARGET_HTTPS_PROXY_NAME \
         --destination=TARGET_PROXY_FILENAME \
         --region=REGION
     

    替换以下内容:

    • TARGET_HTTPS_PROXY_NAME:目标代理的名称。
    • TARGET_PROXY_FILENAME:YAML 文件的名称。例如 mtls_target_proxy.yaml
    • REGION:您在其中配置了负载均衡器的区域。
  4. 列出当前项目指定位置中的所有 ServerTlsPolicies 资源。

    控制台

    1. 在 Google Cloud 控制台中,进入客户端身份验证页面。

      前往客户端身份验证

    2. 系统会显示所有 ServerTlsPolicies 资源。

    gcloud

    如需列出所有客户端身份验证 (ServerTlsPolicies) 资源,请使用 gcloud network-security server-tls-policies list 命令

    gcloud network-security server-tls-policies list \
      --location=REGION
    

    替换以下内容:

    REGION:将 global 用于跨区域内部应用负载均衡器、全球外部应用负载均衡器或传统应用负载均衡器。对于区域级外部应用负载均衡器或区域级内部应用负载均衡器,请使用您在其中配置了负载均衡器的区域。

    记下 ServerTlsPolicies 资源的名称,用于配置 mTLS。此名称在下一步中称为 SERVER_TLS_POLICY_NAME

  5. 如需附加 ServerTlsPolicy 资源文件 TARGET_PROXY_FILENAME,请使用以下命令。将 PROJECT_ID 替换为您的 Google Cloud 项目的 ID。

    echo "serverTlsPolicy: //networksecurity.googleapis.com/projects/PROJECT_ID/locations/REGION/serverTlsPolicies/SERVER_TLS_POLICY_NAME" >> TARGET_PROXY_FILENAME
  6. 如需从文件导入目标 HTTPS 代理的配置,请使用 gcloud compute target-https-proxies import 命令

    全局

       gcloud compute target-https-proxies import TARGET_HTTPS_PROXY_NAME \
           --source=TARGET_PROXY_FILENAME \
           --global
       

    替换以下内容:

    • TARGET_HTTPS_PROXY_NAME:目标代理的名称。
    • TARGET_PROXY_FILENAME:YAML 文件的名称。例如 mtls_target_proxy.yaml

    区域级

       gcloud compute target-https-proxies import TARGET_HTTPS_PROXY_NAME \
           --source=TARGET_PROXY_FILENAME \
           --region=REGION
       

    替换以下内容:

    • TARGET_HTTPS_PROXY_NAME:目标代理的名称。
    • TARGET_PROXY_FILENAME:YAML 文件的名称。例如 mtls_target_proxy.yaml
    • REGION:您在其中配置了负载均衡器的区域。

添加 mTLS 自定义标头

启用 mTLS 后,您可以使用自定义标头传递 mTLS 连接相关的信息。您还可以启用日志记录,以便在日志中捕获 mTLS 连接失败

向后端服务添加 mTLS 自定义标头

对于全球外部应用负载均衡器或传统版应用负载均衡器,您可以使用 自定义标头将 mTLS 连接的相关信息传递给后端服务

  1. 如需列出项目中的所有后端服务,请使用 gcloud compute backend-services list 命令

    gcloud compute backend-services list
    

    记下后端服务的名称,用于启用自定义标头和日志记录。此名称在后面的步骤中称为 BACKEND_SERVICE

  2. 如需更新后端服务,请使用 gcloud compute backend-services update 命令

    gcloud compute backend-services update BACKEND_SERVICE \
      --global \
      --enable-logging \
      --logging-sample-rate=1 \
      --custom-request-header='X-Client-Cert-Present:{client_cert_present}' \
      --custom-request-header='X-Client-Cert-Chain-Verified:{client_cert_chain_verified}' \
      --custom-request-header='X-Client-Cert-Error:{client_cert_error}' \
      --custom-request-header='X-Client-Cert-Hash:{client_cert_sha256_fingerprint}' \
      --custom-request-header='X-Client-Cert-Serial-Number:{client_cert_serial_number}' \
      --custom-request-header='X-Client-Cert-SPIFFE:{client_cert_spiffe_id}' \
      --custom-request-header='X-Client-Cert-URI-SANs:{client_cert_uri_sans}' \
      --custom-request-header='X-Client-Cert-DNSName-SANs:{client_cert_dnsname_sans}' \
      --custom-request-header='X-Client-Cert-Valid-Not-Before:{client_cert_valid_not_before}' \
      --custom-request-header='X-Client-Cert-Valid-Not-After:{client_cert_valid_not_after}'
    

将 mTLS 自定义标头添加到网址映射

对于跨区域内部应用负载均衡器、区域级外部应用负载均衡器或区域级内部应用负载均衡器,您可以使用 自定义标头将有关 mTLS 连接的信息传递给网址映射

如需列出项目中的所有网址映射,请使用 gcloud compute url-maps list 命令

   gcloud compute url-maps list
   

记下网址映射的名称,以便启用自定义标头和日志记录。此名称在后面的步骤中称为 URL_MAP_NAME

全局

如需修改跨区域内部应用负载均衡器的网址映射,请使用 gcloud compute url-maps edit 命令:

   gcloud compute url-maps edit URL_MAP_NAME --global
   

以下示例 YAML 文件展示了如何在自定义请求标头 (requestHeadersToAdd) 中使用变量。您可以使用相同的变量发送自定义响应标头 (responseHeadersToAdd)。

   headerAction:
      requestHeadersToAdd:
      - headerName: "X-Client-Cert-Present"
        headerValue: "{client_cert_present}"
      - headerName: "X-Client-Cert-Chain-Verified"
        headerValue: "{client_cert_chain_verified}"
      - headerName: "X-Client-Cert-Error"
        headerValue: "{client_cert_error}"
      - headerName: "X-Client-Cert-Hash"
        headerValue: "{client_cert_sha256_fingerprint}"
      - headerName: "X-Client-Cert-Serial-Number"
        headerValue: "{client_cert_serial_number}"
      - headerName: "X-Client-Cert-SPIFFE"
        headerValue: "{client_cert_spiffe_id}"
      - headerName: "X-Client-Cert-URI-SANs"
        headerValue: "{client_cert_uri_sans}"
      - headerName: "X-Client-Cert-DNSName-SANs"
        headerValue: "{client_cert_dnsname_sans}"
      - headerName: "X-Client-Cert-Valid-Not-Before"
        headerValue: "{client_cert_valid_not_before}"
      - headerName: "X-Client-Cert-Valid-Not-After"
        headerValue: "{client_cert_valid_not_after}"
      - headerName: "X-Client-Cert-Issuer-Dn"
        headerValue: "{client_cert_issuer_dn}"
      - headerName: "X-Client-Cert-Subject-Dn"
        headerValue: "{client_cert_subject_dn}"
      - headerName: "X-Client-Cert-Leaf"
        headerValue: "{client_cert_leaf}"
      - headerName: "X-Client-Cert-Chain"
        headerValue: "{client_cert_chain}"
   

区域级

如需修改区域级外部应用负载均衡器或区域级内部应用负载均衡器的网址映射,请使用 gcloud compute url-maps edit 命令:

   gcloud compute url-maps edit URL_MAP_NAME --region=REGION
   

以下示例 YAML 文件展示了如何在自定义请求标头 (requestHeadersToAdd) 中使用变量。您可以使用相同的变量发送自定义响应标头 (responseHeadersToAdd)。

   defaultService: regions/REGION/backendServices/BACKEND_SERVICE_1
      name: regional-lb-map
      region: region/REGION
   headerAction:
      requestHeadersToAdd:
      - headerName: "X-Client-Cert-Present"
        headerValue: "{client_cert_present}"
      - headerName: "X-Client-Cert-Chain-Verified"
        headerValue: "{client_cert_chain_verified}"
      - headerName: "X-Client-Cert-Error"
        headerValue: "{client_cert_error}"
      - headerName: "X-Client-Cert-Hash"
        headerValue: "{client_cert_sha256_fingerprint}"
      - headerName: "X-Client-Cert-Serial-Number"
        headerValue: "{client_cert_serial_number}"
      - headerName: "X-Client-Cert-SPIFFE"
        headerValue: "{client_cert_spiffe_id}"
      - headerName: "X-Client-Cert-URI-SANs"
        headerValue: "{client_cert_uri_sans}"
      - headerName: "X-Client-Cert-DNSName-SANs"
        headerValue: "{client_cert_dnsname_sans}"
      - headerName: "X-Client-Cert-Valid-Not-Before"
        headerValue: "{client_cert_valid_not_before}"
      - headerName: "X-Client-Cert-Valid-Not-After"
        headerValue: "{client_cert_valid_not_after}"
      - headerName: "X-Client-Cert-Issuer-Dn"
        headerValue: "{client_cert_issuer_dn}"
      - headerName: "X-Client-Cert-Subject-Dn"
        headerValue: "{client_cert_subject_dn}"
      - headerName: "X-Client-Cert-Leaf"
        headerValue: "{client_cert_leaf}"
      - headerName: "X-Client-Cert-Chain"
        headerValue: "{client_cert_chain}"
   

后续步骤