Vault의 PKCS#11 지원

Vault의 PKCS#11 지원

PKCS11 provider는 KMIP 시크릿 엔진의 일부이며, 고급 데이터 보호(ADP, Advanced Data Protection) 모듈이 포함된 Vault Enterprise가 필요합니다. PKCS11 provider는 키 생성, 암호화, 복호화, 키 저장 작업의 하위 집합을 지원합니다. PKCS11 provider를 사용하려면 Enterprise ADP-KM 라이선스가 있어야 합니다.

출처: 문서

본문

PKCS#11은 기기의 암호화 기능에 접근하는 수단을 제공하는 개방형 표준 C API입니다. 예를 들어 하드웨어 보안 모듈(HSM)(예: Yubikey)에 로컬 프로그램(예: GPG)에서 접근할 때 자주 사용됩니다.

Vault는 PKCS#11 라이브러리(또는 provider)를 제공하므로 Vault를 SSM(Software Security Module) 으로 사용할 수 있습니다. 이를 통해 사용자는 Vault를 다른 PKCS#11 기기처럼 취급해 PKCS#11 호출로 Vault에서 키·개체를 관리하고 암호화·복호화를 수행할 수 있습니다. PKCS#11 라이브러리는 Vault의 KMIP 시크릿 엔진에 연결되어 암호화 작업과 개체 저장을 제공합니다.

플랫폼 지원

이 라이브러리는 KMIP 시크릿 엔진과 함께 라이선스에 고급 데이터 보호 모듈이 포함된 Vault Enterprise 1.11+와 함께 작동합니다.

운영 체제 아키텍처 배포판 glibc
Linux x86-64 RHEL 8 호환 2.28
Linux x86-64 RHEL 9 호환 2.34
Linux x86-64 RHEL 10 호환 2.34
Linux s390X RHEL 9 호환 2.34
Linux s390X RHEL 10 호환 2.34
macOS x86-64
macOS arm64

참고: vault-pkcs11-provider는 모든 glibc 기반 Linux 배포판에서 실행됩니다. 위 버전은 RHEL 호환 GLIBC 버전으로 제공됩니다. 배포판의 glibc 버전에 대해 배포판이 제공하는 것과 같거나 더 오래된 버전에 대해 빌드된 vault-pkcs11-provider를 선택하세요.

provider는 공유 C 라이브러리 형태로 제공되며, Linux에서는 libvault-pkcs11.so, macOS에서는 libvault-pkcs11.dylib입니다. releases.hashicorp.com에서 다운로드할 수 있습니다.

빠른 시작 (Quick start)

  1. provider를 사용하려면 KMIP 시크릿 엔진이 있는 Vault Enterprise 인스턴스에 접근할 수 있어야 합니다. 예를 들어 VAULT_LICENSE 환경 변수에 라이선스가 있다면 로컬에서 시작할 수 있습니다.
docker pull hashicorp/vault-enterprise && docker run --name vault \
  -p 5696:5696 \
  -p 8200:8200 \
  --cap-add=IPC_LOCK \
  -e VAULT_LICENSE=$(printenv VAULT_LICENSE) \
  -e VAULT_ADDR=http://127.0.0.1:8200 \
  -e VAULT_TOKEN=root \
  hashicorp/vault-enterprise \
  server -dev -dev-root-token-id root -dev-listen-address 0.0.0.0:8200
  1. KMIP 시크릿 엔진과 KMIP 스코프(scope)를 구성합니다. 스코프는 키와 개체를 보관하는 데 사용됩니다.

참고: 이 명령은 자격증명을 평문으로 출력합니다.

vault secrets enable kmip
vault write kmip/config listen_addrs=0.0.0.0:5696
vault write -f kmip/scope/my-service
vault write kmip/scope/my-service/role/admin operation_all=true
vault write -f -format=json kmip/scope/my-service/role/admin/credential/generate | tee kmip.json

중요: 프로덕션에서 KMIP를 구성할 때 server_hostnamesserver_ips 구성 매개변수를 설정해야 할 것입니다. 그렇지 않으면 인증서 검증 오류로 KMIP 시크릿 엔진에 대한 TLS 연결이 실패합니다.

마지막 줄은 KMIP 서버에 연결하는 데 사용할 인증서, 키, CA 인증서 체인이 담긴 JSON 파일을 생성합니다. PKCS#11 provider가 사용할 수 있도록 파일로 저장해야 합니다.

jq --raw-output --exit-status '.data.ca_chain[]' kmip.json > ca.pem
jq --raw-output --exit-status '.data.certificate' kmip.json > cert.pem

KMIP 시크릿 엔진의 인증서 파일에는 키도 포함되어 있습니다.

  1. vault-pkcs11.hcl 구성 파일을 만듭니다.
slot {
  server = "127.0.0.1:5696"
  tls_cert_path = "cert.pem"
  ca_path = "ca.pem"
  scope = "my-service"
}

사용 가능한 모든 매개변수는 아래를 참고하세요.

  1. KMIP 자격증명의 인증서를 구성 파일에 지정된 파일(예: cert.pem, ca.pem)에 복사합니다.

  2. 이제 libvault-pkcs11.so(또는 .dylib) 라이브러리를 사용해 OpenSC의 pkcs11-tool 같은 PKCS#11 호환 도구로 Vault의 KMIP 시크릿 엔진에 접근할 수 있어야 합니다.

$ VAULT_LOG_FILE=/dev/null pkcs11-tool --module ./libvault-pkcs11.so -L
Available slots:
Slot 0 (0x0): Vault                     slot 0
  token label        : Token 0
  token manufacturer : HashiCorp
  token model        : Vault Enterprise
  token flags        : token initialized, PIN initialized, other flags=0x60
  hardware version   : 1.12
  firmware version   : 1.12
  serial num         : 1234
  pin min/max        : 0/255
$ VAULT_LOG_FILE=/dev/null pkcs11-tool --module ./libvault-pkcs11.so --keygen -a abc123 --key-type AES:32 \
    --extractable --allow-sw 2>/dev/null
Key generated:
Secret Key Object; AES length 32
VALUE:
label:      abc123
Usage:      encrypt, decrypt, wrap, unwrap
Access:     none

VAULT_LOG_FILE=/dev/null 설정은 Vault PKCS#11 드라이버 로그가 stdout에 나타나는 것을 방지하기 위한 것입니다(기본적으로 파일을 지정하지 않으면 stdout에 표시됨). 프로덕션에서는 VAULT_LOG_FILE/var/log/vault.log 같은 더 영구적인 위치로 설정하는 것이 좋습니다.

구성 (Configuration)

PKCS#11 Provider는 HCL 파일과 환경 변수를 통해 구성할 수 있습니다.

HCL 파일에는 PKCS#11 기기 슬롯(논리 기기)을 Vault 인스턴스와 KMIP 스코프에 매핑하는 지시문이 포함되며, 라이브러리가 KMIP에(클라이언트 TLS 인증서로) 어떻게 인증할지 구성합니다. PKCS#11 라이브러리는 기본적으로 vault-pkcs11.hcl/etc/vault-pkcs11.hcl에서 이 파일을 찾거나, VAULT_KMIP_CONFIG 환경 변수를 설정해 재정의할 수 있습니다.

예를 들어:

slot {
    server = "127.0.0.1:5696"
    tls_cert_path = "cert.pem"
    ca_path = "ca.pem"
    scope = "my-service"
}

slot 블록은 첫 번째 PKCS#11 슬롯이 Vault를 가리키도록 구성합니다. 대부분의 프로그램은 슬롯 하나만 사용합니다.

  • server(필수): Vault 서버의 IP 또는 DNS 이름과 포트 번호(기본 5696)
  • tls_cert_path(필수): KMIP 엔진에 인증하는 데 사용하는 클라이언트 TLS 인증서 위치
  • tls_key_path(선택, 기본 tls_cert_path의 값): KMIP 엔진에 인증하는 데 사용하는 암호화 또는 비암호화 TLS 키 위치
  • ca_path(필수): 서버 인증서를 검증하는 데 사용할 CA 번들 위치
  • scope(필수): 인증할 KMIP 스코프이자 TDE 마스터 키와 관련 메타데이터가 저장될 곳
  • cache(선택, 기본 true): provider가 C_GetAttributeValue(KMIP: GetAttributes) 호출 성능을 위해 캐시를 사용하는지 여부
  • emulate_hardware(선택, 기본 false): provider가 하드웨어 기기에 연결되었다고 보고할지 여부

PKCS#11 라이브러리가 구성 파일을 찾는 기본 위치는 현재 디렉토리(vault-pkcs11.hcl)와 /etc/vault-pkcs11.hcl이지만, VAULT_KMIP_CONFIG 환경 변수를 어떤 파일로든 설정해 재정의할 수 있습니다.

환경 변수로도 이러한 매개변수와 그 이상을 구성할 수 있습니다.

  • VAULT_KMIP_CONFIG: HCL 구성 파일 위치. 기본적으로 provider는 ./vault-pkcs11.hcl/etc/vault-pkcs11.hcl을 확인합니다.
  • VAULT_KMIP_CERT_FILE: KMIP 엔진에 인증하는 데 사용하는 TLS 인증서 위치
  • VAULT_KMIP_KEY_FILE: KMIP 엔진에 인증하는 데 사용하는 TLS 키 위치
  • VAULT_KMIP_KEY_PASSWORD: 암호화된 경우 TLS 키 파일의 비밀번호
  • VAULT_KMIP_CA_FILE: KMIP 엔진에 대한 연결 인증에 사용하는 TLS CA 번들 위치
  • VAULT_KMIP_SERVER: 암호화와 저장에 사용할 KMIP 엔진의 주소와 포트
  • VAULT_KMIP_SCOPE: 암호화와 저장에 사용할 KMIP 스코프
  • VAULT_KMIP_CACHE: C_GetAttributeValue(KMIP: GetAttributes) 호출을 캐시할지 여부
  • VAULT_LOG_LEVEL: provider가 사용할 로그 수준. 기본값은 WARN. 유효한 값은 TRACE, DEBUG, INFO, WARN, ERROR, OFF.
  • VAULT_LOG_FILE: provider가 로깅에 사용할 파일 위치. 기본값은 표준 출력.
  • VAULT_EMULATE_HARDWARE: provider가 하드웨어 기기로 지원된다고 보고할지 여부

암호화된 TLS 키 지원

KMIP 엔진이 반환하는 TLS 키는 기본적으로 암호화되어 있지 않습니다. 그러나 PKCS#11 provider는 키에 대해 RFC 1423을 사용하는 (제한된) 암호화 옵션을 지원합니다. 사용 가능한 알고리즘 중 AES-256-CBC만 권장합니다.

KMIP의 키는 ECDSA 키여야 하며, OpenSSL로 비밀번호로 암호화할 수 있습니다.

openssl ec -in cert.key -out encrypted.key -aes-256-cbc

PKCS#11 provider는 TLS 키를 복호화하려면 비밀번호에 접근해야 합니다. 비밀번호는 두 가지 방법으로 provider에 제공할 수 있습니다.

  • VAULT_KMIP_KEY_PASSWORD 환경 변수, 또는
  • 암호화된 TLS 키를 복호화하려 시도할 때 C_Login PKCS#11 함수의 "PIN" 매개변수

VAULT_KMIP_KEY_PASSWORD로는 단일 비밀번호만 제공할 수 있으므로, HCL 파일의 여러 슬롯이 암호화된 TLS 키를 사용한다면 같은 비밀번호로 암호화해야 하거나, C_Login 메서드를 사용해 비밀번호를 지정해야 합니다.

오류 처리 (Error handling)

오류가 발생하면 가장 먼저 VAULT_LOG_FILE에서 관련 오류 메시지를 확인하세요.

PKCS#11 provider가 0x30(CKR_DEVICE_ERROR) 오류 코드를 반환하면 C_SessionInfo 호출에서 추가 기기 오류 코드를 사용할 수 있습니다. provider가 반환하는 알려진 기기 오류 코드는 다음과 같습니다.

코드 의미
400 구성 또는 PKCS#11 호출에 잘못된 입력이 제공되었습니다.
401 잘못된 자격증명이 제공되었습니다.
404 개체, 속성, 또는 키를 찾을 수 없습니다.
600 알 수 없는 I/O 오류가 발생했습니다.
601 KMIP 엔진 오류가 발생했습니다.

기능 (Capabilities)

Vault PKCS#11 provider는 다음 PKCS#11 provider 프로필을 구현합니다.

  • Baseline
  • Extended

현재 지원되는 키 생성 메커니즘:

이름 메커니즘 번호 Provider 버전 Vault 버전
RSA-PKCS 0x0000 0.2.0 1.13
AES key generation 0x1080 0.1.0 1.12

현재 지원되는 암호화 메커니즘:

이름 메커니즘 번호 Provider 버전 Vault 버전
RSA-PKCS 0x0001 0.2.0 1.13
RSA-PKCS-OAEP 0x0009 0.2.0 1.13
AES-ECB 0x1081 0.2.0 1.13
AES-CBC 0x1082 0.1.0 1.12
AES-CBC Pad 0x1085 0.1.0 1.12
AES-CTR 0x1086 0.1.0 1.12
AES-GCM 0x1087 0.1.0 1.12
AES-OFB 0x2104 0.2.0 1.13
AES-CFB128 0x2107 0.2.0 1.13

현재 지원되는 서명 메커니즘:

이름 메커니즘 번호 Provider 버전 Vault 버전
RSA-PKCS 0x0001 0.2.0 1.13
SHA256-RSA-PKCS 0x0040 0.2.0 1.13
SHA384-RSA-PKCS 0x0041 0.2.0 1.13
SHA512-RSA-PKCS 0x0042 0.2.0 1.13
SHA224-RSA-PKCS 0x0046 0.2.0 1.13
SHA512-224-HMAC 0x0049 0.2.0 1.13
SHA512-256-HMAC 0x004D 0.2.0 1.13
SHA256-HMAC 0x0251 0.2.0 1.13
SHA224-HMAC 0x0256 0.2.0 1.13
SHA384-HMAC 0x0261 0.2.0 1.13
SHA512-HMAC 0x0271 0.2.0 1.13
  • 암호화 및 복호화: C_EncryptInit, C_Encrypt, C_EncryptUpdate, C_EncryptFinal, C_DecryptInit, C_Decrypt, C_DecryptUpdate, C_DecryptFinal
  • 키 관리: C_GenerateKey, C_GenerateKeyPair, C_WrapKey, C_UnwrapKey, C_DeriveKey
  • 개체: C_CreateObject, C_DestroyObject, C_GetAttributeValue, C_FindObjectsInit, C_FindObjects, C_FindObjectsFinal, C_SetAttributeValue, C_CopyObject, C_GetObjectSize
  • 관리: C_Initialize, C_Finalize, C_Login(제공 시 PIN은 TLS 암호화 키의 패스프레이즈로 사용), C_Logout, C_GetInfo, C_GetSlotList, C_GetSlotInfo, C_GetTokenInfo, C_GetMechanismList, C_GetMechanismInfo, C_OpenSession, C_CloseSession, C_CloseAllSessions, C_GetSessionInfo, C_InitToken, C_InitPIN, C_SetPIN, C_GetOperationState, C_SetOperationState, C_GetFunctionStatus, C_CancelFunction, C_WaitForSlotEvent
  • 서명: C_SignInit, C_Sign, C_SignUpdate, C_SignFinal, C_SignRecoverInit, C_SignRecover, C_VerifyInit, C_Verify, C_VerifyUpdate, C_VerifyFinal, C_VerifyRecoverInit, C_VerifyRecover
  • 다이제스트: C_DigestInit, C_Digest, C_DigestUpdate, C_DigestKey, C_DigestFinal, C_DigestEncryptUpdate, C_DecryptDigestUpdate, C_SignEncryptUpdate, C_DecryptVerifyUpdate
  • 난수 생성(아래 참고): C_SeedRandom, C_GenerateRandom

제한 사항 및 참고 (Limitations and notes)

Vault, KMIP 시크릿 엔진, PKCS#11의 특성 때문에 알아야 할 몇 가지 제한 사항이 있습니다.

  • C_FindObjects 등이 반환하는 키·개체 ID는 각 세션에 대해 무작위화되며, 세션 간에 공유할 수 없고 세션이 닫힌 후에는 의미가 없습니다. PKCS#11 개체를 저장하는 데 사용되는 KMIP 개체는 긴 무작위 문자열을 ID로 가지지만, PKCS#11 개체 ID는 32비트 정수로 제한되기 때문입니다. 또한 PKCS#11 provider는 로컬 스토리지가 없습니다.
  • PKCS#11 provider의 성능은 Vault 서버까지의 지연시간과 성능에 크게 의존합니다. 거의 모든 PKCS#11 API 호출(일부 개체 속성 호출은 로컬로 캐시될 수 있음)이 1:1로 KMIP 호출로 번역되기 때문입니다. 여러 세션을 동시에 안전하게 사용할 수 있으며, 단일 Vault 서버 노드가 수천 개의 진행 중인 세션을 지원하는 것으로 테스트되었습니다.
  • 개체 속성 캐시는 세션당 단일 개체에만 유효하며, 다른 개체의 속성이 조회되면 지워집니다.
  • 난수 생성기 함수 C_GenerateRandom은 현재 Go의 crypto/rand 패키지를 호출해 라이브러리 내에서 소프트웨어로 구현되며, Vault를 호출하지 않습니다.

변경 로그 (Changelog)

  • v0.2.3: IBM s390X CPU 아키텍처 지원 추가. EL7 지원 제거.
  • v0.2.2: PKCS#11 클라이언트의 세션 풀 지원 수정. 개인 RSA 키의 C_GetAttributeValue 버그 수정. 개인 RSA 키의 올바른 등록을 방해하던 버그 수정. 빅엔디안 아키텍처에서 provider 빌드 문제 수정. Go 1.25.4 및 Go 종속성 업데이트.
  • v0.2.1: Go 1.22.7 및 Go 종속성 업데이트. 산출물에 라이선스 파일 추가.
  • v0.2.0: RSA 및 HMAC 작업 지원 도입.
  • v0.1.3: Go 1.19.4 및 Go 종속성 업데이트. EL9 빌드에 누락된 체크섬 추가.
  • v0.1.2: macOS arm64 지원 추가. Go 1.19.2 및 Go 종속성 업데이트.
  • v0.1.1: KMIP: Vault 1.12가 요구하는 활성화 날짜 속성 설정. KMIP: 파기 전 키 폐지.
  • v0.1.0: 최초 릴리스.

더 알아보기 (Learn more)