Keyfactor EJBCA 참조 구현

개요

이 가이드에서는 에어 갭 적용 Google Distributed Cloud(GDC)의 서드 파티 인증 기관 (CA)으로 Keyfactor EJBCA Enterprise (외부 어플라이언스로 배포됨)를 통합하는 방법을 설명합니다.

Keyfactor EJBCA Enterprise는 조직이 이기종 환경에서 공개 키 인프라 (PKI)를 관리할 수 있도록 지원하는 확장성이 뛰어나고 강력하며 FIPS를 준수하는 인증 기관 플랫폼입니다.

GDC 에어갭에는 호스팅된 클라우드 경계 내에서 자동 키 및 인증서 관리를 위한 기본 제공 인증 기관 서비스가 포함되어 있습니다. 하지만 GDC 외부의 기존 워크로드에 Keyfactor EJBCA를 기반으로 PKI 인프라를 표준화한 조직은 에어 갭 GDC 환경 내에서 실행되는 워크로드에 동일한 일관된 CA 아키텍처 및 관리 정책을 활용하는 것을 선호할 수 있습니다.

이 가이드에서는 GDC 네트워킹, 내부 DNS, Kubernetes cert-manager를 구성하여 인증서 수명 주기 관리 (ACME)를 자동화하고 등록 기관 (RA) 패턴을 사용하여 대량의 프로그래매틱 발급을 지원하는 방법을 보여줍니다.

가정

이 가이드를 진행하기 전에 다음 가정을 충족하는지 확인하세요.

  • Keyfactor EJBCA는 소프트웨어 어플라이언스 또는 하드웨어 어플라이언스로 배포되며 서비스에 안정적인 IP 주소가 구성됩니다.
  • 루트, 하위, 관리 인증 기관 (CA)이 EJBCA 인스턴스에 생성되었습니다.
  • 종단 개체 (EE) 프로필이 구성되었습니다 (예: TLS 서버 인증서의 경우).
  • 관리 CA 사용자의 인증서가 다운로드되었습니다.
  • EJBCA 인스턴스에서 필수 프로토콜 (예: ACME)이 사용 설정되어 있습니다.
  • 이 가이드에서는 RSA 서명 알고리즘을 사용합니다. 특정 요구사항이나 EJBCA 인스턴스에 구성된 내용에 따라 서명 알고리즘을 변경할 수 있습니다.

아키텍처

이 아키텍처는 EJBCA 서버와 지원 하드웨어 보안 모듈 (HSM)이 물리적 GDC 경계 외부에서 호스팅되지만 네트워크를 통해 액세스할 수 있는 외부 인증 기관 모델을 따릅니다. EJBCA 서버는 하드웨어 또는 소프트웨어 어플라이언스로 외부에서 배포할 수 있습니다. 이 가이드에 설명된 핵심 통합에서는 안정적인 IP 주소를 사용하여 외부 EJBCA 서버에 연결할 수 있어야 합니다.

Keyfactor EJBCA 아키텍처 다이어그램

이 아키텍처의 주요 구성요소는 다음과 같습니다.

  • EJBCA Enterprise Server: Keyfactor 하드웨어 어플라이언스 또는 소프트웨어 어플라이언스로 외부에 배포되어 CA (루트 및 하위)를 호스팅하고 CC EAL4+ 인증 HSM 내에서 모든 CA 키 자료를 생성합니다.
  • GDC Standard Kubernetes 클러스터: 고객 워크로드, cert-manager, 통합 프록시를 실행하는 컴퓨팅 환경입니다.
  • GDC 내부 DNS: ACME DNS-01 챌린지를 해결하는 데 사용되는 로컬 비공개 DNS 영역을 관리합니다 (환경 변수에 구성된 비공개 도메인 이름 사용).
  • GDC 이그레스 게이트웨이: 클러스터 포드에서 외부 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 Standard 클러스터 만들기

이 섹션에서는 GDC 내에 표준 Kubernetes 클러스터를 배포하고 GDC 표준 클러스터 관리자 역할과 로컬 Harbor 컨테이너 레지스트리 사용자 인증 정보를 구성합니다.

1 다음 명령어를 실행하여 사용 가능한 가상 머신 이미지 유형을 식별합니다.

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

2. 클러스터 작업자 노드에 적합한 머신 유형을 선택합니다.

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

3. 영역 관리 API를 사용하여 워커 노드가 2개인 표준 클러스터를 만듭니다.

```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 로봇 계정을 만들고 사용자 이름과 보안 비밀 키를 기록합니다.

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 설정

도메인 확인을 설정하려면 외부 EJBCA 서버를 로컬 도메인 이름에 매핑하는 비공개 DNS 영역 및 레코드 세트를 배포하여 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 게이트웨이 설정

다음으로 Kubernetes 워크로드 (예: cert-manager 및 등록 기관 클라이언트)가 아웃바운드 트래픽을 EJBCA 서버로 안전하게 라우팅할 수 있도록 맞춤 서브넷과 NAT 게이트웨이를 설정하여 GDC 이그레스 네트워킹을 구성합니다.

  • 프로젝트 및 조직 수준 네트워크 개발자 역할을 할당합니다.

    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 내에서 인증서 프로필을 설정하여 관리 인증서의 기술 속성 및 암호화 제약 조건 (예: 알고리즘 및 유효 기간)을 정의합니다.

  • EJBCA 관리 UI를 열고 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 기능 > 엔드 엔티티 프로필로 이동합니다.
  • Add End Entity Profile(최종 엔티티 프로필 추가)에서 GDC ADMIN EE PROFILE를 입력하고 Add Profile(프로필 추가)을 클릭합니다.
  • 프로필을 수정하고 다음 설정을 구성합니다.
    • 기본 인증서 프로필: GDC ADMIN PROFILE
    • 사용 가능한 인증서 프로필: GDC ADMIN PROFILE
    • 기본 CA: GDC Subordinate CA
    • 사용 가능한 CA: GDC Subordinate CA
  • 저장을 클릭합니다.

관리자 인증서 등록

프로필이 설정되면 EJBCA 등록 기관 (RA) 인터페이스를 사용하여 관리 ID를 등록하고 비공개 키, 공개 인증서, 신뢰 체인을 추출하여 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 인증서가 있는 신뢰 체인):

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

역할 및 액세스 규칙 구성

마지막으로 EJBCA에서 관리 역할을 만들고 이를 cert-manager 인증서 일련번호에 바인딩하여 발급자에게 인증서를 승인하고 요청하는 데 필요한 최소 권한 집합만 부여합니다.

  • EJBCA 관리 UI에서 RA Functions > Search End Entities로 이동합니다.
  • cert-manager 최종 엔티티를 검색하고 인증서 일련번호를 기록합니다.
  • 시스템 기능 > 역할 및 액세스 규칙으로 이동하여 추가를 클릭합니다.
  • 역할 이름을 cert-manager로 지정하고 기록한 일련번호를 사용하여 새 구성원을 추가합니다.
  • 액세스 규칙 수정을 클릭하고 다음 권한을 구성합니다.
    • 역할 템플릿: RA 관리자
    • 승인된 CA: GDC Subordinate CA
    • 최종 항목 규칙: 최종 항목 승인, 생성, 수정
    • 엔드 엔티티 프로필: GDC TLS SERVER EE PROFILE
    • 기타 규칙: 감사 로그 보기 선택 해제
  • 저장을 클릭합니다.

GDC 클러스터 준비

GDC 환경을 준비하려면 표준 Kubernetes 클러스터로 인증하고 추출된 EJBCA 관리 사용자 인증 정보를 Kubernetes 보안 비밀 내부에 저장하여 cert-manager 발급자 포드에서 안전하게 액세스할 수 있도록 합니다.

  • Standard 클러스터 사용자 인증 정보를 검색합니다.

    gdcloud clusters get-credentials "${GDC_CLUSTER_NAME}" \
      --standard \
      --project "${GDC_PROJECT_ID}" \
      --zone "${GDC_ZONE}"
    
  • 맞춤 발급자의 타겟 네임스페이스를 만듭니다.

    kubectl create ns ejbca-issuer-system
    
  • TLS 인증 보안 비밀을 배포합니다.

    kubectl create secret tls ejbca-secret \
      -n ejbca-issuer-system \
      --cert=client.crt \
      --key=client.key
    
  • EJBCA 신뢰 체인 보안 비밀을 배포합니다.

    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 이미지 풀 보안 비밀을 만듭니다.

    # 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 권한을 설정하고 EJBCA 서버를 Kubernetes cert-manager 프레임워크 내에서 신뢰할 수 있는 서명 소스로 등록하는 전역 ClusterIssuer 리소스를 배포합니다.

  • GDC의 cert-manager 컨트롤러가 커스텀 EJBCA 발급자를 사용할 수 있도록 RBAC 권한을 구성합니다.

    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 관리 UI에서 System Configuration(시스템 구성) > ACME Configuration(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에 배포합니다.

  • DNS 전파를 위해 약 30초간 기다린 후 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}/에 성공적으로 기록되었는지 확인합니다.