인증서 발급 외부 정책 서비스

인증서 발급 외부 정책 서비스 (CIEPS)

이 문서는 CIEPS(Certificate Issuance External Policy Service)와 통신할 때 Vault PKI 시크릿 엔진이 사용하는 높은 수준의 아키텍처와 서비스 API를 다룰게요.

출처: 문서

본문

CIEPS(Certificate Issuance External Policy Service)란 무엇인가요?

HashiCorp Vault의 PKI 시크릿 엔진은 임의 구조의 리프(leaf) 인증서를 발급하는 메커니즘인 .well-known / pki/sign-verbatim을 제공해요. 이를 위해서는 조직이 인증서 발급 요청을 인증·승인·검증하는(아마도 키 쌍 생성도 처리하는) 애플리케이션/사용자 접근 가능 서비스를 운영하고, 그다음 PKI에 높은 권한의 Vault 토큰으로 결과 CSR과 리프 인증서에 서명하도록 요청해야 해요. 원래 요청자의 CSR에 어떤 속성이 빠져 있어도, sign-verbatim은 제어 서비스가 요청을 수정할 수 있게 하지 않기 때문에 원래 서비스는 요청을 거부해야 합니다.

CIEPS 프로토콜은 검증과 인증서 템플릿 작업을 PKI 뒤에 배치함으로써 이 문제를 해결해요. 다음 문제를 해결합니다.

  1. 감사(Auditing) — 원래 요청자가 여전히 식별되고, 원래 요청과 후속 응답이 모두 추적되도록 해요.
  2. 중앙 접근(Central access) — 애플리케이션이 인증서를 요청할 때 새 URL 하나만 사용하면 되게 해요.
  3. 인증서 수정(Certificate modification) — 요청자가 제출한 내용의 커스터마이즈가 이 외부 서비스에 노출될 수 있게 해요.
  4. 외부 검증(External validation) — 역할 기반 시스템과 비교했을 때, CIEPS 구현이 검증을 위해 고객이 정의한 외부 시스템에 접근할 수 있어요.

이 두 메커니즘 모두 조직이 Vault PKI 시크릿 엔진을 활용해 나만의 유연한 발급 제어 아키텍처를 구축하고, Vault를 PKI-as-a-Service 플랫폼으로 활용할 수 있게 해요. 그러나 CIEPS는 조직에 sign-verbatim 방식보다 훨씬 더 큰 통제권을 부여해요.

sign-verbatim을 사용한 커스텀 정책

sign-verbatim을 사용하면 정책 검증 서비스가 Vault 앞에 위치해서, 사용자(사용자는 Vault 인증을 사용할 수 없으며 이 서비스에 별도로 인증해야 함)의 요청을 처리해야 해요. 이 RA 서비스는 Vault에 대한 자신의 인증을 처리하고, PKI 플러그인을 통해 서명 기능을 제공해요.

애플리케이션이 CSR을 제공해 자신의 키 자료를 제어할 때, 정책 서비스는 요청된 CSR을 수정할 수 없으므로 결과 인증서도 수정할 수 없어요. 운영자가 호출 애플리케이션에게 구현 세부 사항을 숨길 수 없이, 요청을 승인하거나 거부할 수만 있어요. PKI의 sign-verbatim 엔드포인트는 Vault API 호출자(이 경우 앞에 있는 정책 서비스)가 제공된 CSR과 무관하게 인증서를 수정할 수 있는 기능이 없기 때문이에요.

그러나 정책 서비스가 키 자료를 제어할 수 있다면(그리고 이것이 조직에게 허용 가능한 위험이라면), 정책 서비스는 호출 애플리케이션을 대신해 요청을 수정할 수 있어요. 하지만 여전히 외부 애플리케이션은 이 외부 정책 서비스에 인증하는 방법을 알아야 해요.

또한 Vault와의 호환성을 보장하려면, 이 정책 서비스(와 그 개발자)는 ACME 프로토콜 지원을 추가해야 해요. Vault가 향후 지원하는 새 프로토콜마다, 이 서비스도 호환성을 유지하기 위해 지원을 구현해야 합니다.

CIEPS를 사용한 커스텀 정책

CIEPS를 사용하면 사용자는 여전히 Vault에 인증하고 일반 요청 워크플로로 인증서를 서명·발급하며, ACME를 통해서도 가능해요. 그러나 Vault의 PKI 엔진은 호출 애플리케이션에게 투명하게, 설정된 CIEPS 구현에 접근해 요청된 인증서를 검증하고 템플릿 작업을 수행해요.

특히 애플리케이션은 키 자료에 대한 완전한 제어를 유지하거나, 키 생성을 신뢰할 수 있는 Vault 서비스에 위임할 수 있어요. CIEPS가 제공할 수 있는 기능에는 영향이 없어요. CIEPS 서비스는 단일 PKI 마운트 또는 여러 마운트의 요청에 응답하도록 범위를 정할 수 있고, 요청한 사용자와 CIEPS 메시지의 Vault PKI 인스턴스에 대한 정보를 얻어요.

CIEPS 서비스는 요청 검증과 최종 인증서 구조 템플릿 작업에 대한 지식만 필요하므로, 개발자는 키 자료 생성이나 다른 발급 프로토콜 지원 재구현 같은 더 넓은 PKI 문제가 아니라 비즈니스 정책 로직에만 신경 쓰면 돼요.

CIEPS 웹훅 형식

CIEPS 프로토콜은 REST 기반이며 선택적으로 mTLS로 보호되는 웹훅이에요. 외부 서비스 설정은 Vault가 형식화된 CIEPS 요청을 POST할 단일 URL을 지정해요. CIEPS 서비스를 사용할 수 없을 때(잘못된 설정이나 중단 때문이든), Vault는 요청을 거부하고 클라이언트가 나중에 요청을 재시도하는 것은 클라이언트 책임이에요.

편의상 이 struct들의 Go 버전은 Vault SDK에서 사용할 수 있어요.

Vault → CIEPS 요청 형식

이 문서는 CIEPS 요청/응답 버전 1을 설명해요.

application/json 콘텐츠 타입을 사용해 Vault는 다음 요청 본문을 JSON 객체로 POST해요.

  • request_version (int: 1) — Vault가 보낸 CIEPS 요청의 버전입니다. 호환되는 응답 형식이 기대돼요.

  • request_uuid (string) — 이 요청을 식별하는 무작위 UUID입니다. 이 값은 응답에서 보내야 해요.

  • synchronous (bool: true) — 요청이 동기인지 여부를 나타내는 불리언입니다. 현재는 true로 설정돼요. 비동기 응답은 이해되지 않습니다.

  • user_request_key_values (map[string]interface{}) — 사용자가 보낸 검증되지 않은 요청 파라미터입니다. 사용하기 전에 검증하는 것은 CIEPS 서비스의 몫이에요. 다음 필드가 있을 수 있으며, 사용자가 제출한 다른 필드도 포함될 수 있어요.

    • csr (string) — 클라이언트가(/sign 또는 ACME 요청의 경우) 또는 클라이언트를 대신해(/issue 요청의 경우, 키 자료는 Vault가 생성) 제출한 PEM 형식 CSR입니다.
  • identity_request_key_values (map[string]interface{}) — 사용자 신원과 관련된 값입니다. 요청 유형이 ACME이면 이 값은 채워지지 않아요. 목록은 다음과 같아요.

    • entity_id (string) — 인증 후 요청의 엔티티 식별자입니다.
    • entity (map[string]interface{}) — 인증 후 사용자의 해석된 전체 logical.Entity입니다. 설정의 entity_jmsepath 파라미터로 변경될 수 있어요.
    • groups ([]map[string]interface{}) — 인증 후 사용자의 해석된 logical.Groups 집합입니다. 설정의 group_jmsepath 파라미터로 변경될 수 있어요.

    참고: 직접 토큰 백엔드나 루트 토큰을 사용하는 경우 엔티티 정보가 없을 수 있어요. 두 경우 모두 identity_request_key_values는 생략됩니다.

  • acme_request_key_values (map[string]interface{}) — 완료된 주문에 첨부된 ACME 인증 챌린지와 관련된 값입니다. 요청 유형이 ACME일 때만 존재해요. 목록은 다음과 같아요.

    • authorizations (map[string]interface{}) — 클라이언트가 이 주문을 finalization 상태로 옮기기 위해 해결한 인증과 챌린지입니다.
    • account (map[string]interface{}) — 요청을 발급한 ACME 계정과 관련된 정보입니다. 목록은 다음과 같아요.
      • id (string) — ACME 계정의 UUID입니다.
      • directory (string) — 이 계정이 요청한 ACME 디렉토리 경로입니다.
      • contact ([]string) — 생성 시 요청 ACME 계정이 제출한 검증되지 않은 연락처 정보입니다.
      • created_date (string: RFC 3999 format) — 계정이 생성된 타임스탬프입니다.
      • eab (map[string]interface{}, optional) — 있을 때 Vault 인증으로 이 계정을 승인하는 데 사용된 EAB의 세부 사항입니다. 없으면 이 ACME 계정은 EAB 바인딩 없이 생성된 것입니다.
        • key_id (string) — 이 계정이 사용한 EAB 바인딩의 식별자입니다.
        • key_type (string) — 이 계정이 사용한 EAB 바인딩의 키 유형입니다.
        • created_date (string: RFC 3999 format) — 계정이 생성된 타임스탬프입니다.
  • vault_request_values (map[string]interface{}) — Vault가 검증했거나 생성한 요청 값입니다. 이 값은 검증되지 않은 user_request_key_values보다 신뢰도가 높아요. 목록은 다음과 같아요.

    • policy_name (string: "") — 요청자가 지정한 선택적 정책 이름입니다. 발급 모드가 ACME가 아니면(또는 ACME이고 EAB가 시행된 경우), Vault의 ACL 시스템이 이를 검증했어요.
    • mount (string) — PKI 플러그인이 알고 있는 요청의 마운트 경로입니다.
    • namespace (string) — PKI 플러그인이 알고 있는 마운트 경로가 존재하는 요청의 네임스페이스입니다.
    • vault_is_performance_standby (bool) — 요청 노드가 스탠바이 노드일 때 단언됩니다. 서비스가 응답에서 스토리지가 필요하다고 표시하면 Vault는 사용자의 HTTP 요청을 활성 노드로 전달하고, 활성 노드가 CIEPS 요청을 다시 제출하게 해요. 이 경우 서비스가 항상 인증서를 저장해야 한다는 것을 알고 스탠바이 노드에서 요청을 본다면, 정책·템플릿 평가를 건너뛰거나 결과를 두 번째 통과를 위해 캐시할 수 있어요.
    • vault_is_performance_secondary (bool) — 요청 노드가 프라이머리 클러스터가 아닌 퍼포먼스 세컨더리에서 온 것일 때 단언됩니다.
    • issuance_mode (string: "sign", "issue", "ica", or "acme") — 요청 유형입니다: /external-policy/sign(/:policy), /external-policy/issue(/:policy), /external-policy/sign-intermediate(/:policy) REST 호출인지, 아니면 ACME 요청인지에 따라 달라집니다.
    • vault_generated_private_key (bool) — 이 요청 뒤의 키 자료를 Vault가 생성했는지 여부입니다. 현재는 issuance_mode="issue"일 때만 true로 설정돼요.
    • requested_issuer_name (string) — 사용자가 요청한 발급자 이름입니다. 응답의 issuer_ref 값을 수정해 변경할 수 있어요.
    • requested_issuer_id (string) — 사용자가 요청한 발급자의 UUID입니다. 응답의 issuer_ref 값을 수정해 변경할 수 있어요.
    • requested_issuer_cert (string) — 사용자가 요청한 발급자의 PEM 형식 인증서입니다. 응답의 issuer_ref 값을 수정해 변경할 수 있어요.
    • requested_issuance_config (map[string]interface{}) — 리프 인증서 발급에 사용되는 설정입니다. 목록은 다음과 같아요.
      • aia_values (map[string]interface{}) — 제안된 발급자의 AIA 값(CA, CRL, OCSP)입니다. 응답에 issuer_ref가 설정되면 실제 발급에 사용되는 값과 다를 수 있어요.
      • leaf_not_after_behavior (string: "err", "truncate", or "permit") — 제안된 발급자의 리프 유효 기간 동작입니다.
      • mount_default_ttl (string) — 마운트 튜닝에 설정된 제안된 기본 TTL입니다.
      • mount_max_ttl (string) — 마운트 튜닝에 설정된 최대 TTL입니다.

CIEPS → Vault 응답 형식

CIEPS 엔진은 인증서를 발급해야 하는지 여부와 무관하게 이 POST 응답에 200 OK 상태로 회신해야 해요. 리다이렉트는 Vault가 따르지 않아요. 프록시나 로드 밸런싱 기능은 호출자에게 엄격히 투명해야 합니다. 200이 아닌 상태 코드가 반환한 어떤 verbatim 메시지도 Vault 서버 로그나 사용자에게 반환되지 않아요.

위 요청에 대한 응답에서는 certificate 또는 error 필드 중 하나만 지정해야 해요. certificateerror가 모두 있으면 error가 반환된 warnings에 추가되고 certificate가 발급됩니다.

application/json 콘텐츠 타입을 사용해 서버는 다음 JSON 객체로 회신해야 해요.

  • request_uuid (string) — 서버가 이 요청을 식별하는 데 사용한 무작위 UUID입니다.
  • error (string, optional) — 요청이 실패한 이유를 사용자에게 반환할 오류 메시지입니다. error 또는 certificate 응답 파라미터 중 하나만 지정해야 해요.
  • warnings ([]string, optional) — 요청의 사소한 문제에 대해 사용자에게 반환할 선택적 경고입니다.
  • certificate (string, optional) — Vault 서비스가 서명할 PEM 형식 인증서입니다. error 또는 certificate 응답 파라미터 중 하나만 지정해야 해요.
  • issuer_ref (string) — 이 요청에 서명하는 데 사용할 발급자 참조입니다. 사용자의 발급자 선택(requested_issuer_id 안)이 괜찮다면 이 필드에 설정해야 해요.
  • store_certificate (bool: false) — 서명된 인증서를 저장할지 여부입니다.
  • generate_lease (bool: false) — Vault가 인증서에 대한 관련 리스를 생성해야 하는지 여부입니다. 리스를 생성하려면 store_certificatetrue로 설정해야 하며, 그렇지 않으면 리스가 생성되지 않아요.

인증서의 서명은 무시되고 지정된 발급자가 만든 서명으로 교체돼요. 이 발급자와 호환되는 서명 알고리즘이 인증서에 지정되어 있으면 보존되고, 그렇지 않으면 이 발급자의 키 유형의 기본 서명 알고리즘이 사용됩니다.

인증서의 AIA 정보는 지정된 발급자의 정보가 있으면 그것으로 교체되고, 없으면 전역 AIA URL이 설정되어 AIA URI와 CRL 배포 지점 확장을 교체해요. 또한 RFC 5280에서 요구하는 대로 Authority Key Identifier 확장은 발급자의 Subject Key Identifier 확장 값으로 교체됩니다.

튜토리얼 (Tutorial)

PKI 시크릿 엔진 사용 예시에 대한 다음 튜토리얼을 참고하세요.

API

PKI 시크릿 엔진은 완전한 HTTP API를 제공해요. 자세한 내용은 PKI 시크릿 엔진 API 문서를 참고해 주세요.

더 알아보기 (Learn more)

  • CIEPS Go struct 정의는 Vault SDK에서 확인하세요.
  • Vault PKI 시크릿 엔진 전체 API는 PKI API 문서를 참고하세요.