Keyfactor EJBCA 参考实现

概览

本指南介绍了如何将 Keyfactor EJBCA Enterprise(部署为外部设备)集成为 Google Distributed Cloud (GDC) 气隙环境的第三方证书颁发机构 (CA)。

Keyfactor EJBCA Enterprise 是一款高度可伸缩、稳健且符合 FIPS 标准的证书授权机构平台,可帮助组织在异构环境中管理公钥基础架构 (PKI)。

GDC 网闸隔离配置包含一个内置的证书授权机构服务,用于在托管云边界内自动管理密钥和证书。不过,如果组织已针对 GDC 以外的现有工作负载将 PKI 基础架构标准化为 Keyfactor EJBCA,则可能更倾向于针对在气隙 GDC 环境中运行的工作负载利用相同的一致 CA 架构和管理政策。

本指南演示了如何配置 GDC 网络、内部 DNS 和 Kubernetes cert-manager,以自动执行证书生命周期管理 (ACME),并使用注册机构 (RA) 模式支持大批量程序化签发。

前提

在继续阅读本指南之前,请确保满足以下假设条件:

  • Keyfactor EJBCA 部署为软件设备或硬件设备,并为该服务配置了稳定的 IP 地址。
  • 已在 EJBCA 实例中创建根证书授权机构 (CA)、从属证书授权机构和管理证书授权机构。
  • 已配置实体 (EE) 配置文件(例如,用于 TLS 服务器证书)。
  • 已下载管理 CA 用户的证书。
  • EJBCA 实例上已启用必需的协议(例如 ACME)。
  • 本指南中使用的是 RSA 签名算法。您可以根据具体要求或 EJBCA 实例中的配置更改签名算法。

架构

该架构遵循外部证书授权机构模型,其中 EJBCA 服务器及其后端的硬件安全模块 (HSM) 托管在物理 GDC 边界之外,但可通过网络访问。EJBCA 服务器可以部署在外部,可以是硬件设备,也可以是软件设备。本指南中介绍的核心集成仅要求外部 EJBCA 服务器可通过稳定的 IP 地址访问。

Keyfactor EJBCA 架构图。

此架构的关键组件包括:

  • EJBCA Enterprise Server:在外部部署为 Keyfactor 硬件设备或软件设备,其中包含 CA(根 CA 和从属 CA),并在经过 CC EAL4+ 认证的 HSM 中生成所有 CA 密钥材料。
  • GDC Standard Kubernetes 集群:运行客户工作负载、cert-manager 和集成代理的计算环境。
  • GDC 内部 DNS:管理用于解析 ACME DNS-01 质询的本地专用 DNS 区域(使用在环境变量中配置的专用域名)。
  • GDC 出站网关:将集群 pod 的出站流量定向到外部 EJBCA 服务器 IP 地址。
  • Harbor 私有注册表:托管镜像容器映像(例如 EJBCA cert-manager 签发者),用于气隙部署。

准备工作

在开始集成之前,请确保您的 GDC 环境满足以下要求:

  • 首先,创建一个项目,用于存放本指南中生成的所有资源。
  • 配置本指南中将引用的环境变量。根据需要修改这些值,以匹配您的特定环境:

    # GDC Environment Configuration
    export GDC_ORG="your-org-name"
    export GDC_ZONE="your-zone-name"
    export GDC_PROJECT_ID="your-project-id"
    export GDC_USER_NAME="your-gdc-user-email"
    export GDC_CLUSTER_NAME="your-cluster-name"
    
    # EJBCA Server Configuration
    export EJBCA_DNS_ZONE="example.internal"
    export EJBCA_HOSTNAME="ejbca.${EJBCA_DNS_ZONE}"
    export EJBCA_LB_IP="XX.XX.XX.XX" # Stable IP of your EJBCA Server
    export EJBCA_CA_NAME="GDC Subordinate CA"
    export EJBCA_NAMESPACE="ejbca-ee"
    export CERTIFICATE_PROFILE_NAME="GDC TLS SERVER PROFILE"
    export END_ENTITY_PROFILE_NAME="GDC TLS SERVER EE PROFILE"
    
    # Harbor Private Registry Configuration
    export HARBOR_INSTANCE_URL="your-harbor-url.internal"
    export HARBOR_PROJECT="your-harbor-project"
    export HARBOR_ROBOT_ACCOUNT="robot$your-robot-name"
    export HARBOR_ROBOT_SECRET="your-robot-secret"
    export HARBOR_PULL_SECRET_NAME="harbor-secret"
    
  • 网络注意事项:本指南假设该脚本是从堡垒节点运行的,该节点可以访问 GDC 网闸隔离配置 API,还可以访问互联网来下载所需的清单和容器映像。如果您是从无法访问互联网的机器运行此命令,则必须单独获取这些资源(例如,使用 docker save 从已联网的机器导出图片,并使用 docker load 导入这些图片),然后安全地将它们上传到您的环境中,才能继续操作。

配置 kubectl 别名

在本部分中,您将为 GDC 的区域管理和全局 API 创建便捷的命令行别名:

  • 为区域管理 API 创建别名(将 MANAGEMENT_API_KUBECONFIG 替换为管理 API 的 kubeconfig 的路径):

    alias km="kubectl --kubeconfig MANAGEMENT_API_KUBECONFIG"
    
  • 为全局 API 创建别名(将 GLOBAL_API_KUBECONFIG 替换为全局 API 的 kubeconfig 路径):

    alias kg="kubectl --kubeconfig GLOBAL_API_KUBECONFIG"
    

创建 GDC 标准集群

在本部分中,您将在 GDC 中部署标准 Kubernetes 集群,并配置 GDC 标准集群管理员角色和本地 Harbor 容器注册表凭据:

1 运行以下命令,确定可用的虚拟机映像类型:

```shell
gdcloud compute machine-types list
```

2 为集群工作器节点选择合适的机器类型:

```shell
export MACHINE_TYPE="n3-standard-8-gdc"
```

3 使用可用区级管理 API 创建具有两个工作器节点的标准集群:

```shell
km create -f - <<EOF
apiVersion: cluster.gdc.goog/v1
kind: Cluster
metadata:
  name: ${GDC_CLUSTER_NAME}
  namespace: ${GDC_PROJECT_ID}
spec:
  nodePools:
  - machineTypeName: ${MACHINE_TYPE}
    nodeCount: 2
    name: ${GDC_CLUSTER_NAME}-node-pool
EOF
```

This creates a simple GDC cluster. Cluster creation
can take up to 60 minutes to complete. To check the status, use the
following command:

```shell
km get clusters/${GDC_CLUSTER_NAME} \
  -n ${GDC_PROJECT_ID} \
  --watch
```

After the cluster is ready, the output should show a STATE of `Running`.

4 集群准备就绪后,检索其凭据:

```shell
KUBECONFIG=kubeconfig-${GDC_CLUSTER_NAME}.yaml gdcloud clusters \
  get-credentials ${GDC_CLUSTER_NAME} \
  --standard \
  --project ${GDC_PROJECT_ID} \
  --zone ${GDC_ZONE}
```

5 为 GDC 用户分配 GDC 标准集群管理员角色:

```shell
gdcloud projects add-iam-policy-binding ${GDC_PROJECT_ID} \
  --member="user:${GDC_USER_NAME}" \
  --role=cluster-admin

gdcloud projects add-iam-policy-binding ${GDC_PROJECT_ID} \
  --member="user:${GDC_USER_NAME}" \
  --role=standard-cluster-admin
```

6 在 GDC 中创建 Harbor 实例和 Harbor 项目,以托管镜像容器映像:

```shell
gdcloud projects add-iam-policy-binding ${GDC_PROJECT_ID} \
  --member="user:${GDC_USER_NAME}" \
  --role=harbor-instance-admin
```

7 创建 Harbor Robot 账号并记录其用户名和密钥。

8 使用您的 Harbor 实例进行身份验证:

```shell
docker --config=./docker-harbor login ${HARBOR_INSTANCE_URL} \
  -u ${HARBOR_ROBOT_ACCOUNT} \
  -p ${HARBOR_ROBOT_SECRET}
```

This saves the robot account credentials to
`./docker-harbor/config.json` for subsequent Secret creation.

基础架构和网络配置

在本部分中,您将配置底层 GDC 基础架构和网络设置。这样可确保 Kubernetes 工作负载能够解析外部 EJBCA 主机域名,并成功将出站 API 调用路由到其 IP 地址。

GDC 网闸隔离配置中的专用 DNS 设置

为了建立网域解析,您需要部署专用 DNS 区域和记录集,以将外部 EJBCA 服务器映射到本地网域名称,从而允许 GDC 内的服务使用稳定的主机名(而不是原始 IP 地址)进行连接:

  • 为用户分配“受管 DNS 项目管理员”角色:

    gdcloud projects add-iam-policy-binding ${GDC_PROJECT_ID} \
      --member=user:${GDC_USER_NAME} \
      --role=managed-dns-project-admin
    
  • 部署全局 ManagedDNSZone 资源:

    kubectl --kubeconfig GLOBAL_API_KUBECONFIG apply -f - <<EOF
    apiVersion: networking.global.gdc.goog/v1
    kind: ManagedDNSZone
    metadata:
      name: private-example-internal
      namespace: ${GDC_PROJECT_ID}
    spec:
      dnsName: ${EJBCA_DNS_ZONE}
      visibility: PRIVATE
    EOF
    
  • 部署指向 EJBCA 设备 IP 地址的 ResourceRecordSet:

    kubectl --kubeconfig GLOBAL_API_KUBECONFIG apply -f - <<EOF
    apiVersion: networking.global.gdc.goog/v1
    kind: ResourceRecordSet
    metadata:
      name: ${EJBCA_HOSTNAME}
      namespace: ${GDC_PROJECT_ID}
    spec:
      name: ${EJBCA_HOSTNAME}
      ttlSeconds: 600
      type: A
      rrData:
      - ${EJBCA_LB_IP}
      dnsZone: private-example-internal
    EOF
    

出站 NAT 网关设置

接下来,您可以通过设置自定义子网和 NAT 网关来配置 GDC 出站流量网络,以允许 Kubernetes 工作负载(例如 cert-manager 和注册机构客户端)安全地将出站流量路由到 EJBCA 服务器:

  • 分配项目级和组织级网络开发者角色:

    gdcloud projects add-iam-policy-binding ${GDC_PROJECT_ID} \
      --member=user:${GDC_USER_NAME} \
      --role=cloud-nat-developer
    
    gdcloud projects add-iam-policy-binding ${GDC_PROJECT_ID} \
      --member=user:${GDC_USER_NAME} \
      --role=subnet-project-admin
    
    gdcloud organizations add-iam-policy-binding ${GDC_ORG} \
      --member="user:${GDC_USER_NAME}" \
      --role=subnet-org-admin
    
  • 创建出站子网:

    kubectl --kubeconfig MANAGEMENT_API_KUBECONFIG apply -f - <<EOF
    apiVersion: ipam.gdc.goog/v1
    kind: Subnet
    metadata:
      name: ejbca-cluster-egress
      namespace: ${GDC_PROJECT_ID}
    spec:
      ipv4Request:
        prefixLength: 32
      parentReference:
        name: data-network-segment-${GDC_ZONE}-group
        namespace: platform
        type: SubnetGroup
      type: Leaf
    EOF
    
  • 创建与 cert-manager 颁发者选择器匹配的 CloudNATGateway:

    kubectl --kubeconfig MANAGEMENT_API_KUBECONFIG apply -f - <<EOF
    apiVersion: networking.gdc.goog/v1
    kind: CloudNATGateway
    metadata:
      name: ejbca-egress-gateway
      namespace: ${GDC_PROJECT_ID}
    spec:
      subnetRefs:
      - ejbca-cluster-egress
      workloadSelector:
        labelSelector:
          clusters:
            matchLabels:
              kubernetes.io/metadata.name: ${GDC_CLUSTER_NAME}
          workloads:
            matchLabels:
              app.kubernetes.io/name: ejbca-cert-manager-issuer
    EOF
    

Kubernetes cert-manager 集成

在本部分中,您将自定义 EJBCA cert-manager 颁发者与 GDC 的 cert-manager 服务集成。这样一来,您就可以为容器化服务建立自动证书配置、续订和生命周期管理。

EJBCA cert-manager 集成示意图。

为签发者配置 EJBCA

如需集成签发者,您需要在 EJBCA 服务器内配置必要的配置文件、注册管理客户端凭据,并设置角色绑定。这样一来,便可建立一个安全的管理渠道,让 cert-manager 能够向 EJBCA 进行身份验证并从中请求证书。

创建管理员证书配置文件

首先,在 EJBCA 中建立证书配置文件,以定义管理证书的技术属性和加密限制(例如算法和有效期):

  • 打开 EJBCA 管理界面,依次前往 CA Functions > Certificate Profiles。
  • 克隆 ENDUSER 配置文件并将其命名为 GDC ADMIN PROFILE。
  • 修改 GDC ADMIN PROFILE 并配置以下设置:
    • 可用的密钥算法:RSA
    • 可用的位长度:2048、3072、4096
    • 签名算法:SHA512WithRSA
    • 有效性:200d
    • 发卡机构备用名称:清除 使用
    • CRL 分发点:选中使用
    • 使用 CA 定义的 CRL 分发点:选中使用
    • 授权信息访问:检查使用情况
    • 使用 CA 定义的 OCSP 定位器:选中使用
    • 使用 CA 定义的 CA 颁发者:选中使用
    • 可用的 CA:选择 GDC Subordinate CA
  • 点击保存。

创建管理员最终实体个人资料

接下来,您需要在 EJBCA 中创建一个最终实体配置文件,以定义默认字段和 CA 分配,从而简化注册和颁发管理证书的过程:

  • 依次前往 RA Functions > End Entity Profiles。
  • 在添加最终实体配置文件下,输入 GDC ADMIN EE PROFILE,然后点击添加配置文件。
  • 修改配置文件并配置以下设置:
    • 默认证书配置文件:GDC ADMIN PROFILE
    • 可用的证书配置文件:GDC ADMIN PROFILE
    • 默认 CA:GDC Subordinate CA
    • 可用的 CA:GDC Subordinate CA
  • 点击保存。

注册管理员证书

在建立配置文件后,您可以使用 EJBCA 注册机构 (RA) 接口注册管理身份,并提取私钥、公共证书和信任链,以生成对 cert-manager 进行身份验证所需的实体凭据文件:

  • 前往 RA Web 标签页。
  • 点击提交新请求,然后配置:
    • 证书类型:GDC ADMIN EE PROFILE
    • 密钥对生成:由 CA 完成
    • 密钥算法:RSA 4096 位
    • 通用名称 (CN):cert-manager
    • 用户名:cert-manager
    • 注册代码:abcd
  • 点击下载 PEM,然后将其另存为 cert-manager.pem。
  • 将 PEM 文件拆分为三个文件:

    • client.key(密钥):

      openssl pkey -in cert-manager.pem -out client.key
      
    • client.crt(公开证书):

      openssl x509 -in cert-manager.pem -out client.crt
      
    • ca.crt(包含从属 CA 证书和根 CA 证书的信任链):

      awk '/BEGIN CERTIFICATE/{i++} i>1' cert-manager.pem > ca.crt
      

配置角色和访问权限规则

最后,您在 EJBCA 中创建一个管理角色,并将其绑定到 cert-manager 证书序列号,以确保签发者仅拥有批准和请求证书所需的最低权限集:

  • 在 EJBCA 管理界面中,依次前往 RA Functions > Search End Entities。
  • 搜索 cert-manager 最终实体,并记录其证书序列号。
  • 依次前往系统功能 > 角色和访问权限规则,然后点击添加。
  • 将该角色命名为 cert-manager,然后使用您记录的序列号添加新成员。
  • 点击修改访问权限规则,然后配置以下权限:
    • 角色模板:RA 管理员
    • 已获授权的 CA:GDC Subordinate CA
    • 最终实体规则:批准、创建和修改最终实体
    • 最终实体配置文件:GDC TLS SERVER EE PROFILE
    • 其他规则:清除查看审核日志
  • 点击保存。

准备 GDC 集群

为了准备 GDC 环境,您需要使用标准 Kubernetes 集群进行身份验证,并将提取的 EJBCA 管理凭据存储在 Kubernetes Secret 中,以便 cert-manager 签发者 Pod 可以安全地访问这些凭据:

  • 检索标准集群凭据:

    gdcloud clusters get-credentials "${GDC_CLUSTER_NAME}" \
      --standard \
      --project "${GDC_PROJECT_ID}" \
      --zone "${GDC_ZONE}"
    
  • 为自定义签发者创建目标命名空间:

    kubectl create ns ejbca-issuer-system
    
  • 部署 TLS 身份验证 Secret:

    kubectl create secret tls ejbca-secret \
      -n ejbca-issuer-system \
      --cert=client.crt \
      --key=client.key
    
  • 部署 EJBCA 信任链 Secret:

    kubectl create secret generic ejbca-ca-secret \
      -n ejbca-issuer-system \
      --from-file=ca.crt
    

安装 EJBCA 颁发者

如需配置部署,请将 EJBCA cert-manager 签发者容器映像镜像到您的私有 Harbor 注册表中,然后部署 Helm 图表。此命令会实例化将 Kubernetes 证书请求转换为 EJBCA API 调用所需的自定义控制器:

  • 在签发者的命名空间中创建 Harbor 映像拉取 Secret:

    # Authenticate with the private Harbor registry
    docker --config=./docker-harbor login ${HARBOR_INSTANCE_URL} \
      -u ${HARBOR_ROBOT_ACCOUNT} \
      -p ${HARBOR_ROBOT_SECRET}
    
    kubectl create secret docker-registry ${HARBOR_PULL_SECRET_NAME} \
      --from-file=.dockerconfigjson=./docker-harbor/config.json \
      -n ejbca-issuer-system
    
  • 将官方 EJBCA cert-manager 签发者映像镜像到 Harbor:

    docker pull keyfactor/ejbca-cert-manager-issuer:latest --platform linux/amd64
    
    docker tag keyfactor/ejbca-cert-manager-issuer:latest \
      ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/ejbca-cert-manager-issuer:latest
    
    docker --config=./docker-harbor push \
      ${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/ejbca-cert-manager-issuer:latest
    
  • 添加 Helm 代码库并下载图表:

    helm repo add ejbca-issuer https://keyfactor.github.io/ejbca-cert-manager-issuer
    helm repo update
    helm pull ejbca-issuer/ejbca-cert-manager-issuer --untar
    
  • 使用镜像映像代码库部署 Helm 图表:

    helm install ejbca-cert-manager-issuer ./ejbca-cert-manager-issuer \
      --namespace ejbca-issuer-system \
      --set image.repository=${HARBOR_INSTANCE_URL}/${HARBOR_PROJECT}/ejbca-cert-manager-issuer \
      --set "imagePullSecrets[0].name=${HARBOR_PULL_SECRET_NAME}" \
      --set image.tag=latest
    

创建提供方资源

接下来,您将建立 GDC RBAC 权限并部署全局 ClusterIssuer 资源,该资源会将 EJBCA 服务器注册为 Kubernetes cert-manager 框架内的可信签名源:

  • 配置 RBAC 权限,以允许 GDC 的 cert-manager 控制器使用自定义 EJBCA 签发者:

    kubectl apply -f - <<EOF
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: cert-manager-controller-approve:issuers-ejbca-issuer-keyfactor-com
    rules:
    - verbs:
      - approve
      apiGroups:
      - cert-manager.io
      resources:
      - signers
      resourceNames:
      - issuers.ejbca-issuer.keyfactor.com/*
      - clusterissuers.ejbca-issuer.keyfactor.com/*
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: cert-manager-controller-approve:issuers-ejbca-issuer-keyfactor-com
    subjects:
    - kind: ServiceAccount
      name: cert-manager
      namespace: cert-manager
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: cert-manager-controller-approve:issuers-ejbca-issuer-keyfactor-com
    EOF
    
  • 部署全局 ClusterIssuer 资源:

    kubectl apply -f - <<EOF
    apiVersion: ejbca-issuer.keyfactor.com/v1alpha1
    kind: ClusterIssuer
    metadata:
      name: clusterissuer-ejbca
    spec:
      hostname: "${EJBCA_HOSTNAME}"
      ejbcaSecretName: "ejbca-secret"
      caBundleSecretName: "ejbca-ca-secret"
      certificateAuthorityName: "${EJBCA_CA_NAME}"
      certificateProfileName: "${CERTIFICATE_PROFILE_NAME}"
      endEntityProfileName: "${END_ENTITY_PROFILE_NAME}"
      endEntityName: ""
    EOF
    
  • 验证签发者的状态:

    kubectl get clusterissuer.ejbca-issuer.keyfactor.com/clusterissuer-ejbca \
      -o "custom-columns=NAME:.metadata.name,STATUS:.status.conditions[0].message"
    

    输出应如下所示:

    NAME                  STATUS
    clusterissuer-ejbca   Success
    

请求证书

如需验证集成,您可以部署标准 Kubernetes 证书资源,以测试端到端 cert-manager 流程,并确认 EJBCA 是否成功签名并预配所请求的证书:

创建测试 Certificate 资源以验证集成是否成功:

kubectl apply -f - <<EOF
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: ejbca-test-certificate
  namespace: ${EJBCA_NAMESPACE}
spec:
  commonName: example.com
  secretName: ejbca-certificate
  issuerRef:
    name: clusterissuer-ejbca
    group: ejbca-issuer.keyfactor.com
    kind: ClusterIssuer
EOF

验证证书是否已创建并准备就绪:

kubectl get certificates.cert-manager.io -n ${EJBCA_NAMESPACE}

输出应如下所示:

NAME                     READY   SECRET              AGE
ejbca-test-certificate   True    ejbca-certificate   12s

通过 DNS-01 验证自动执行 ACME

在本部分中,您将配置 EJBCA 的 ACME 服务,并利用 GDC 内部 DNS 资源自动执行网域验证证书颁发。这样一来,标准 cert-manager 或 Certbot 客户端便可使用标准自动化 ACME 协议请求证书。

为 ACME 配置 EJBCA

为准备服务器,您需要在 EJBCA 中启用 ACME 服务,并配置具有专用 DNS 解析器的 ACME 别名。这会准备 EJBCA 服务器,以便在 GDC 中处理和验证 DNS-01 质询响应:

  • 在 EJBCA 管理界面中,依次前往系统配置 > ACME 配置。
  • 点击添加,然后配置以下内容:
    • 名称:default
    • 最终实体配置文件:GDC TLS SERVER EE PROFILE
    • 允许颁发通配符证书:选中
    • 挑战响应 MPIC 验证 DNS 标识符挑战类型:选择 dns-01
    • DNS 解析器:输入全局 DNS 的 IP。
    • 验证 DNSSEC:通过(因为这是本地专用环境)
  • 点击保存。

创建 ACME 环境变量

在本部分中,您将创建以下环境变量来配置 Certbot 客户端。根据需要修改这些值:

# ACME Alias created in the EJBCA configuration
export ACME_ALIAS="default"

# Arbitrary email address used for ACME registration
export ACME_EMAIL="your-email@example.com"

注册 Certbot 客户端

接下来,您需要安装标准 Certbot 客户端,并将其注册到 EJBCA 的私有 ACME 端点。这会建立执行自动化证书操作所需的受信任的客户账号:

  • 在工作站上安装 certbot。例如,对于 macOS:

    brew install certbot
    
  • 创建用于存储配置和日志的本地文件夹:

    mkdir -p ./certbot/config ./certbot/work ./certbot/logs
    
  • 向 EJBCA ACME 目录端点注册客户端:

    certbot register \
      --config-dir ./certbot/config \
      --work-dir ./certbot/work \
      --logs-dir ./certbot/logs \
      --server https://${EJBCA_HOSTNAME}/ejbca/acme/${ACME_ALIAS}/directory \
      --email ${ACME_EMAIL} \
      --agree-tos \
      --no-eff-email
    

使用 DNS 质询颁发证书

最后,您执行手动 Certbot 请求并部署临时 GDC DNS TXT 资源,以解决 DNS-01 质询。这会验证您对目标网域的所有权,并触发自动证书颁发:

  • 运行手动验证命令:

    certbot certonly \
      --manual \
      --preferred-challenges dns \
      --key-type rsa \
      --rsa-key-size 2048 \
      --config-dir ./certbot/config \
      --work-dir ./certbot/work \
      --logs-dir ./certbot/logs \
      --server https://${EJBCA_HOSTNAME}/ejbca/acme/${ACME_ALIAS}/directory \
      -d test.${EJBCA_DNS_ZONE}
    

    终端将停止并显示质询值。输出示例:

    Please deploy a DNS TXT record under the name:
    
    _acme-challenge.test.example.internal.
    
    with the following value:
    
    q3pCmzXfIhsTpT4f4JAulHmHaAR3udC_9Wf1G498ER0
    
    Before continuing, verify the TXT record has been deployed.
    
  • 使用 Certbot 提供的字符串将 TXT 记录部署到您的全局 DNS。

  • 等待大约 30 秒,让 DNS 传播完毕,然后返回 Certbot 终端,并按 Enter 键。

    输出示例:

    Successfully received certificate.
    Certificate is saved at:./certbot/config/live/test.example.internal/fullchain.pem
    Key is saved at:./certbot/config/live/test.example.internal/privkey.pem
    This certificate expires on 2026-11-16.
    These files will be updated when the certificate renews.
    
  • 验证证书是否已成功写入 ./certbot/config/live/test.${EJBCA_DNS_ZONE}/。