Google Distributed Cloud (GDC) 网闸隔离配置提供了一个公钥基础架构 (PKI) API 来获取 Web 证书。本文档介绍了如何从一种 PKI 证书模式过渡到另一种模式。如需详细了解 PKI 模式 配置类型,请参阅 Web TLS 证书配置。
本文档面向平台管理员组内的受众群体,他们希望管理证书授权机构和证书颁发者。如需了解详情, 请参阅 GDC 网闸隔离配置文档的受众群体。
准备工作
在过渡 PKI 模式之前,您必须拥有必要的权限并准备好环境。
请求 IAM 角色
如需创建、更新和删除证书授权机构和证书颁发者,请与组织 IAM 管理员联系,以请求系统命名空间中的 PKI 基础架构管理员 (infra-pki-admin) 角色。
准备环境
生成 kubeconfig 文件 以配置
kubectl访问权限。
过渡到 BYO 子 CA 模式
本部分提供了一系列步骤,用于过渡到自带 (BYO) 子 CA 证书模式。
创建 BYO 子 CA
如需创建 BYO 子 CA,请将自定义资源应用于 Distributed Cloud 可用区。
创建
CertificateAuthority资源并将其另存为 YAML 文件。在以下示例中,您会看到一个示例CertificateAuthority资源apiVersion: pki.security.gdc.goog/v1 kind: CertificateAuthority metadata: name: CA_NAME namespace: pki-system spec: caProfile: commonName: COMMON_NAME duration: DURATION renewBefore: RENEW_BEFORE caCertificate: externalCA: {} certificateProfile: keyUsage: - digitalSignature - keyCertSign - crlSign extendedKeyUsage: - serverAuth secretConfig: secretName: SECRET_NAME执行以下变量替换操作:
- CA_NAME:子 CA 的名称。
- COMMON_NAME:CA 证书的通用名称。
- DURATION:CA 证书的请求生命周期。以小时为单位指定时长(例如
1000h)。不支持以天 (d) 或年 (y) 为单位。 - RENEW_BEFORE:CA 证书到期前的轮替时间。
- SECRET_NAME:将保存 私钥和已签名的 CA 证书的 Kubernetes Secret 的名称。
将自定义资源应用于 Distributed Cloud 可用区。
kubectl apply -f byo-subca.yaml --kubeconfig MANAGEMENT_API_SERVER将 MANAGEMENT_API_SERVER 替换为 Management API 服务器 kubeconfig 文件。
系统会生成子 CA 的 CSR,并等待您对其进行签名。如需对 CSR 进行签名,请按照 对 BYO 子 CA 证书进行签名部分中的说明操作。
对 BYO 子 CA 证书进行签名
从 GDC 环境获取证书签名请求 (CSR):
kubectl get certificateauthorities CA_NAME -n pki-system -ojson | jq -j '"echo ", .status.externalCA.csr, " | base64 -d > ","sub_ca.csr\n"' | bash该命令会在当前目录中生成文件
sub_ca.csr。此文件包含 X.509 CA 证书的 CSR。使用客户的根 CA 协议为
sub_ca.csr文件请求已签名的 CA 证书。对于已获批准的证书签名请求,您将获得由客户的根 CA 签名的 CA 证书。将证书存储到当前目录中的
sub_ca.crt文件。此外,获取客户的根 CA 证书并将其存储到当前目录中的ca.crt文件。如需确切说明,请与 PMO 联系。验证以下内容,以确保证书的完整性和准确性:
确保
sub_ca.crt符合标准 PEM 编码的证书格式:-----BEGIN CERTIFICATE----- <Certificate> -----END CERTIFICATE-----验证
sub_ca.crt在“基本限制”扩展项中是否为有效的证书授权机构 (CA):openssl x509 -text -noout -in sub_ca.crt | grep -A 1 "Basic Constraints"输出必须包含
CA:TRUE,否则需要进一步调查:X509v3 Basic Constraints: critical CA:TRUE验证 CA 证书的通用名称 (CN):
openssl x509 -noout -subject -in sub_ca.crt如果您的设置需要正文备用名称 (SAN) 扩展项,请验证证书中的 SAN 扩展项:
openssl x509 -text -noout -in sub_ca.crt | grep -A 1 "Subject Alternative Name"
生成规范以修补
CertificateAuthority资源:echo "spec: caCertificate: externalCA: signedCertificate: certificate: $(base64 -w0 sub_ca.crt) ca: $(base64 -w0 ca.crt)" > patch.txtpatch.txt文件中的内容类似于以下代码段:spec: caCertificate: externalCA: signedCertificate: certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURSekNDQ… ca: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURRVENDQ…修改
CertificateAuthority资源的规范:kubectl patch certificateauthority CA_NAME -n pki-system --patch-file patch.txt --type='merge'验证 BYO 子 CA 的就绪情况:
kubectl get certificateauthority CA_NAME -n pki-system -ojson | jq -r ' .status.conditions[] | select( .type as $id | "Ready" | index($id))'您将看到类似如下所示的输出:
{ "lastTransitionTime": "2024-04-30T22:10:50Z", "message": "Certificate authority is ready for use", "observedGeneration": 3, "reason": "Ready", "status": "True", "type": "Ready" }验证已签名的 CA 证书的到期时间:
kubectl -n pki-system get secret SECRET_NAME -ojson | jq -j '"echo ", .metadata.name, " $(echo ", .data["tls.crt"], "| base64 -d | openssl x509 -enddate -noout)\n"' | bash创建
CertificateIssuer资源 YAML 文件并保存该文件。例如,byo-subca-issuer.yaml:apiVersion: pki.security.gdc.goog/v1 kind: CertificateIssuer metadata: name: BYO_SUBCA_ISSUER namespace: pki-system spec: caaasConfig: certificateAuthorityRef: namespace: pki-system name: CA_NAME将 BYO_SUBCA_ISSUER 替换为 byo 子 CA 颁发者的名称。
使用
kubectlCLI 将自定义资源应用于 Management API 服务器中的 Distributed Cloud 可用区:kubectl apply -f byo-subca-issuer.yaml --kubeconfig MANAGEMENT_API_SERVER验证新颁发者的就绪情况:
kubectl -n pki-system get certificateissuer.pki.security.gdc.goog/BYO_SUBCA_ISSUER -ojson | jq -r ' .status.conditions[] | select( .type as $id | "Ready" | index($id))'
过渡到 BYO 证书模式
本部分提供了一系列步骤,用于过渡到 BYO 证书模式。
创建 BYO CertificateIssuer
创建
CertificateIssuer资源并将其另存为 YAML 文件,例如byo-cert-issuer.yaml。此 BYO 证书颁发者使用受管理的default-tls-ca作为后备 CA:apiVersion: pki.security.gdc.goog/v1 kind: CertificateIssuer metadata: name: BYO_CERT_ISSUER_NAME namespace: pki-system spec: byoCertConfig: fallbackCertificateAuthority: name: default-tls-ca namespace: pki-system将 BYO_CERT_ISSUER_NAME 替换为 BYO 证书 颁发者的名称。
将自定义资源应用于 Management API 服务器中的 Distributed Cloud 可用区:
kubectl apply -f byo-cert-issuer.yaml --kubeconfig MANAGEMENT_API_SERVER验证新颁发者的就绪情况。
kubectl -n pki-system get certificateissuer.pki.security.gdc.goog/BYO_CERT_ISSUER_NAME -ojson | jq -r ' .status.conditions[] | select( .type as $id | "Ready" | index($id))'输出类似于以下内容:
{ "lastTransitionTime": "2024-05-01T22:25:20Z", "message": "", "observedGeneration": 1, "reason": "FallbackCAReady", "status": "True", "type": "Ready" }
对 BYO 证书进行签名
在等待外部对 CSR 进行签名时,BYO 证书可以由 BYO 证书颁发者中指定的后备 CA 临时颁发。获取当前 BYO 证书
default-wildcard-cert状态:kubectl get certificate.pki.security.gdc.goog/default-wildcard-cert -n istio-system -o json | jq -r ' .status.conditions[] | select( .type as $id | "Ready" | index($id))'输出类似于以下内容:
{ "lastTransitionTime": "2024-05-03T08:42:10Z", "message": "Certificate is issued by a fallback CA", "observedGeneration": 1, "reason": "UsingFallbackCA", "status": "True", "type": "Ready" }就绪原因说明
UsingFallbackCA,表示后备 CA 颁发了证书。然后,该证书会存储在 Secret 中,并可供使用。获取证书 Secret 名称:
kubectl -n istio-system get certificate.pki.security.gdc.goog/default-wildcard-cert -ojson | jq -r '.spec.secretConfig.secretName'输出类似于以下内容:
web-tls从 Secret 检查颁发者:
kubectl get secret web-tls -n istio-system -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -text -noout | grep Issuer输出类似于以下内容:
Issuer: CN = GDC Managed ORG TLS CA自带证书 (BYO 证书) 在等待自己的 CSR 签名时,可以暂时使用匹配的证书。例如,dnsName 为
example-service.org-1.zone1.google.gdch.test的 example-service 证书与来自同一证书颁发者的 DNSName 为*.org-1.zone1.google.gdch.test的default-wildcard-cert匹配。example-service 证书在等待其 CSR 签名时可以保持以下状态:{ "lastTransitionTime": "2024-05-03T22:30:51Z", "message": "Using a matched issued Certificate: default-wildcard-cert/istio-system", "observedGeneration": 1, "reason": "UsingMatchedCert", "status": "True", "type": "Ready" }从证书状态获取 CSR:
kubectl -n istio-system get certificate.pki.security.gdc.goog/default-wildcard-cert -ojson | jq -r ' .status.byoCertStatus.csrStatus'输出类似于以下内容:
{ "conditions": [ { "lastTransitionTime": "2024-05-03T18:14:19Z", "message": "", "observedGeneration": 1, "reason": "WaitingForSigning", "status": "False", "type": "Ready" } ], "csr": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSB..." }根据外部 CA 配置,有多种方法可以对 CSR 进行签名。签名时,请使用 CSR 中的 SAN。例如:
function signCert() { certName=$1 ns=$2 # Download the CSR from the certificate kubectl get certificate.pki.security.gdc.goog $certName -n $ns -o jsonpath='{.status.byoCertStatus.csrStatus.csr}' | base64 -d > $certName.csr # Get SAN from the csr san=$(openssl req -in $certName.csr -noout -text | grep 'DNS:' | sed -s 's/^[ ]*//') # Save SAN to extension config cat <<EOF >$certName-csr.ext keyUsage=digitalSignature,keyEncipherment extendedKeyUsage=serverAuth,clientAuth subjectAltName=${san} EOF # Sign the CSR with an external CA. You need to prepare the external CA cert and key openssl x509 -req -in $certName.csr -days 365 -CA ext-ca.crt -CAkey ext-ca.key -CAcreateserial -extfile $certName-csr.ext -out $certName-signed.crt openssl x509 -in $certName-signed.crt -text -noout # Upload the externally signed certificate by patching. echo "spec: byoCertificate: certificate: $(base64 -w0 $certName-signed.crt) ca: $(base64 -w0 ext-ca.crt)" > patch.txt kubectl patch certificate.pki.security.gdc.goog $certName -n $ns --patch-file patch.txt --type='merge' } # Use the function to sign the default-wildcard-cert in the istio-system namespace signCert default-wildcard-cert istio-system验证以下详细信息:
- 证书的 CSR 状态为
Ready
kubectl -n istio-system get certificate.pki.security.gdc.goog/default-wildcard-cert -ojson | jq -r ' .status.byoCertStatus.csrStatus.conditions'[ { "lastTransitionTime": "2024-05-03T21:56:25Z", "message": "", "observedGeneration": 2, "reason": "Signed", "status": "True", "type": "Ready" } ]- 证书的状态为
Ready,原因是Issued
kubectl get certificate.pki.security.gdc.goog/default-wildcard-cert -n istio-system -o json | jq -r ' .status.conditions[] | select( .type as $id | "Ready" | index($id))'输出类似于以下内容:
{ "lastTransitionTime": "2024-05-03T08:42:10Z", "message": "Certificate is issued", "observedGeneration": 2, "reason": "Issued", "status": "True", "type": "Ready" }- Secret 已更新:
kubectl get secret web-tls -n istio-system -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -text -noout | grep Issuer输出类似于以下内容:
Issuer: CN = external-ca- 证书的 CSR 状态为
过渡到采用 ACME 模式的 BYO 证书
本部分提供了一系列步骤,用于过渡到采用 ACME 模式的 BYO 证书。
创建采用 ACME 配置的 CertificateIssuer
创建采用 ACME 配置的
CertificateIssuer资源,并将其另存为 YAML 文件,例如acme-issuer.yaml。apiVersion: pki.security.gdc.goog/v1 kind: CertificateIssuer metadata: name: ACME_ISSUER_NAME namespace: pki-system spec: acmeConfig: rootCACertificate: ROOT_CA_CERTIFICATE acme: server: ACME_SERVER_URL caBundle: CA_BUNDLE privateKeySecretRef: name: PRIVATE_KEY_SECRET_NAME执行以下变量替换操作:
- ACME_ISSUER_NAME:ACME 颁发者的名称。
- ROOT_CA_CERTIFICATE:由 ACME 服务器颁发的证书的根 CA 数据。
- ACME_SERVER_URL:用于访问 ACME 服务器 目录端点的网址。
- CA_BUNDLE:PEM CA 的 Base64 编码软件包,用于 验证 ACME 服务器提供的证书链。
- PRIVATE_KEY_SECRET_NAME:包含 ACME 账号私钥的 Secret 的名称。
如需使用现有的 ACME 账号私钥,请确保保存该私钥的 Secret 在与 ACME 颁发者相同的命名空间中使用 名称 PRIVATE_KEY_SECRET_NAME。如果您未提供此 Secret,系统会自动生成一个同名的新 Secret 来存储 ACME 账号私钥。
将自定义资源应用于 Distributed Cloud 可用区:
kubectl apply -f acme-issuer.yaml --kubeconfig MANAGEMENT_API_SERVER验证新颁发者的就绪情况:
kubectl --kubeconfig MANAGEMENT_API_SERVER -n pki-system get certificateissuer.pki.security.gdc.goog/ACME_ISSUER_NAME -ojson | jq -r ' .status.conditions[] | select( .type as $id | "Ready" | index($id))'您将看到类似如下所示的输出:
{ "lastTransitionTime": "2024-05-01T18:32:17Z", "message": "", "observedGeneration": 1, "reason": "ACMEClientReady", "status": "True", "type": "Ready" }
重新颁发证书
如需将默认颁发者切换为新的 ACME 颁发者,请参阅 更改默认证书颁发者
如需使用新的默认颁发者立即重新颁发证书,请参阅 手动重新颁发 PKI Web 证书。