Google Distributed Cloud (GDC) 网闸隔离配置提供公钥基础架构 (PKI) API,用于获取 Web 证书。本文档提供了从一种 PKI 证书模式转换到另一种模式的说明。如需详细了解 PKI 模式配置类型,请参阅 Web TLS 证书配置。
本文档适用于希望管理证书授权机构和证书颁发者的平台管理员群组中的受众群体。如需了解详情,请参阅适用于 GDC 网闸隔离配置文档的受众群体。
准备工作
在转换 PKI 模式之前,您必须拥有必要的权限并准备好环境。
申请 IAM 角色
如需创建、更新和删除证书授权机构和证书颁发机构,请与您的 IAM 组织管理员联系,请求在系统命名空间中授予 PKI Infra Admin (infra-pki-admin) 角色。
准备环境
生成 kubeconfig 文件以配置
kubectl访问权限。
转换为 BYO subCA 模式
本部分提供了一系列步骤,用于过渡到自带 (BYO) SubCA 证书模式。
创建 BYO subCA
如需创建 BYO subCA,请将自定义资源应用于 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 subCA 证书进行签名部分中的说明操作。
对 BYO subCA 证书进行签名
从 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 subCA 的就绪情况:
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 subCA 签发者的名称。
使用
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-cert 模式。
创建 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-cert 颁发者的名称。
在 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-cert 颁发者中指定的后备 CA 可以临时颁发 BYO-cert。获取当前的 BYO-cert
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-cert) 在等待其自己的 CSR 签名时,可以暂时使用匹配的证书。dnsName 为
example-service.org-1.zone1.google.gdch.test的 example-service 证书与来自同一证书颁发机构、DNSName 为*.org-1.zone1.google.gdch.test的default-wildcard-cert匹配。在等待其 CSR 签名时,example-service 证书可以保持以下状态:{ "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" }- 密钥已更新:
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 状态为“
过渡到 BYO 证书(采用 ACME 模式)
本部分提供了一系列步骤,用于过渡到采用 ACME 模式的 BYO-cert。
创建具有 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:采用 Base64 编码的 PEM CA 捆绑包,用于验证 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 证书。