PKCS#11을 AWS KMS 외부 키 스토어(XKS)로 구성하기

PKCS#11을 AWS KMS 외부 키 스토어(XKS)로 구성하기

참고: 이 문서에서는 예시 구현으로 AWS xks-proxy를 사용합니다.

Vault의 KMIP 시크릿 엔진은 AWS xks-proxy와 Vault PKCS#11 Provider를 함께 사용해 AWS KMS 외부 키 스토어(XKS, External Key Store) 프로토콜의 외부 키 스토어로 사용할 수 있습니다.

출처: 문서

본문

개요 (Overview)

이것은 고급 데이터 보호(KMIP 지원)가 있는 Vault 1.11.0 Enterprise(이상)에서 작동하는 것으로 테스트되었습니다.

전제 조건:

  • 포트 443에서 XKS Proxy를 실행할 수 있고 인터넷이나 VPC 엔드포인트에 노출된 서버. Vault 서버와 동일해도 됩니다.
  • XKS Proxy용 유효한 TLS 인증서가 있는 유효한 DNS 항목
  • 플랫폼용으로 releases.hashicorp.com에서 다운로드한 libvault-pkcs11.so가 XKS Proxy 서버에서 사용 가능
  • KMIP 시크릿 엔진이 있고 TCP 포트 5696이 XKS Proxy가 실행될 곳에서 접근 가능한 Vault Enterprise

이 설정에는 세 부분이 있습니다.

  • Vault KMIP 시크릿 엔진 표준 설정 (이 설정에는 XKS 특정 요소가 없습니다.)
  • PKCS#11 provider(libvault-pkcs11.so)가 Vault KMIP 시크릿 엔진과 통신하는 방법을 알려주는 Vault PKCS#11 설정 (이 설정에는 XKS 특정 요소가 없습니다.)
  • XKS Proxy 설정

중요: XKS는 엄격한 250ms 지연시간 요구사항이 있습니다. 이 지연시간으로 요청을 처리하려면 Vault와 XKS 프록시를 원하는 KMS 리전에 가능한 한 가깝게 호스팅하는 것을 권장합니다.

Vault 설정

Vault 서버에서 KMIP 시크릿 엔진을 설정해야 합니다.

  1. KMIP 시크릿 엔진과 리스너 시작하기.
vault secrets enable kmip
vault write kmip/config listen_addrs=0.0.0.0:5696
  1. 접근 가능할 AES 키를 담을 KMIP 스코프를 생성하기. KMIP 스코프는 본질적으로 격리된 네임스페이스입니다. 이 문서 전체에서 사용되는 my-service라는 스코프를 만드는 예시입니다.
vault write -f kmip/scope/my-service
  1. 스코프에 접근할 수 있는 KMIP 역할을 생성하기.
vault write kmip/scope/my-service/role/admin operation_all=true
  1. KMIP 역할에 대한 TLS 자격증명(인증서, 키, CA 번들)을 생성하기.

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

vault write -f -format=json kmip/scope/my-service/role/admin/credential/generate | tee kmip.json

credential/generate 엔드포인트의 응답은 JSON입니다. .data.certificate 항목에는 xks-proxy에서 KMIP에 연결하는 데 사용할 TLS 클라이언트 키와 인증서 번들이 들어 있습니다. .data.ca_chain[] 항목에는 KMIP 서버 인증서를 검증하는 CA 번들이 들어 있습니다. cert.pemca.pem 같은 파일로 저장하세요.

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

XKS Proxy 설정

나머지 단계는 XKS Proxy 서버에서 수행됩니다. 이 예시에서는 ngrok 같은 HTTPS 프록시 서비스를 사용해 XKS 프록시로 연결을 전달합니다. 이는 테스트용으로 유효한 도메인과 TLS 엔드포인트를 빠르게 설정하는 데 도움이 됩니다.

  1. ngrok 시작하기.
$ ngrok http 8000

나중에 KMS를 구성하는 데 사용할 수 있는 도메인(예: https://example.ngrok.io)이 출력됩니다.

  1. libvault-pkcs11.so 바이너리를 /usr/local/lib 같은 위치로 서버에 복사합니다. (아래 TOML 구성 파일과 동일해야 합니다.) 실행 가능하도록 chmod를 하세요.

  2. Vault 설정에서 TLS 인증서 번들(예: /etc/kmip/cert.pem)과 CA 번들(예: /etc/kmip/ca.pem)을 xks-proxy 서버로 복사합니다. (xks-proxy 프로세스가 접근할 수 있기만 하면 위치는 중요하지 않습니다.)

  3. XKS에서 Vault PKCS#11 구성용 settings_vault.toml 파일을 만들고, XKS_PROXY_SETTINGS_TOML 환경 변수가 그 파일 위치를 가리키도록 설정합니다.

변경할 중요 설정:

  • [[external_key_stores]]: URI 경로 접두사를 원하는 것으로 변경, 임의 액세스 ID 선택, 임의 시크릿 키 선택, XKS에 접근 가능한 키 라벨 집합(xks_key_id_set) 설정
  • [pkcs11]: PKCS11_HSM_MODULE을 releases.hashicorp.com에서 다운로드한 libvault-pkcs11.so(또는 .dylib) 파일 위치로 설정
[server]
  ip = "0.0.0.0"
  port = 8000
  region = "us-east-2"
  service = "kms-xks-proxy"

[server.tcp_keepalive]
  tcp_keepalive_secs = 60
  tcp_keepalive_retries = 3
  tcp_keepalive_interval_secs = 1

[tracing]
  is_stdout_writer_enabled = true
  is_file_writer_enabled = true
  level = "DEBUG"
  directory = "/var/local/xks-proxy/logs"
  file_prefix = "xks-proxy.log"
  rotation_kind = "HOURLY"

[security]
  is_sigv4_auth_enabled = true
  is_tls_enabled = true
  is_mtls_enabled = false

[tls]
  tls_cert_pem = "tls/server_cert.pem"
  tls_key_pem = "tls/server_key.pem"
  mtls_client_ca_pem = "tls/client_ca.pem"
  mtls_client_dns_name = "us-east-2.alpha.cks.kms.aws.internal.amazonaws.com"

[[external_key_stores]]
  uri_path_prefix = "/xyz"
  sigv4_access_key_id = "AKIA4G...2HPM"
  sigv4_secret_access_key = "1234567890123456789012345678901234567890123="
  xks_key_id_set = ["abc123"]

[pkcs11]
  session_pool_max_size = 30
  session_pool_timeout_milli = 0
  session_eager_close = false
  user_pin = ""
  PKCS11_HSM_MODULE = "/usr/local/lib/libvault-pkcs11.so"
  context_read_timeout_milli = 100

[limits]
  max_plaintext_in_base64 = 8192
  max_aad_in_base64 = 16384

[hsm_capabilities]
  can_generate_iv = false
  is_zero_iv_required = false

참고: vault-pkcs11-provider 0.1.0–0.1.2 버전은 마지막 두 줄을 can_generate_iv = trueis_zero_iv_required = true로 변경해야 합니다.

  1. 다음 내용으로 /etc/vault-pkcs11.hcl 파일을 만듭니다.
slot {
  server = "VAULT_ADDRESS:5696"
  tls_cert_path = "/etc/kmip/cert.pem"
  ca_path = "/etc/kmip/ca.pem"
  scope = "my-service"
}

이 파일은 libvault-pkcs11.so가 KMIP 서버를 찾고 통신하는 방법을 알기 위해 사용합니다. 사용 가능한 모든 매개변수와 용법은 Vault 문서를 참고하세요.

  1. Vault 로그를 보려면(오류 메시지를 찾는 데 유용) VAULT_LOG_FILE(기본 stdout)과 VAULT_LOG_LEVEL(기본 INFO)을 지정할 수 있습니다. VAULT_LOG_FILE/tmp/vault.log 또는 /var/log/vault.log 같은 것으로 설정하는 것을 권장합니다. 다른 유용한 로그 수준은 WARN(더 조용함)과 TRACE(매우 상세하며 원시 네트워크 패킷 같은 민감한 정보를 포함할 수 있음)입니다.

  2. KMIP에 AES-256 키를 만듭니다. 예를 들어 pkcs11-tool(보통 OpenSC 패키지와 함께 설치)을 사용합니다. 전체 설정은 Vault 문서를 참고하세요.

VAULT_LOG_FILE=/dev/null pkcs11-tool --module ./libvault-pkcs11.so --keygen -a abc123 --key-type AES:32 \
    --extractable --allow-sw
Key generated:
Secret Key Object; AES length 32
VALUE:
label:      abc123
Usage:      encrypt, decrypt, wrap, unwrap
Access:     none

AWS CLI에서 XKS 활성화

  1. XKS 프록시를 가리키는 적절한 매개변수로 KMS 커스텀 키 스토어를 만듭니다. (이 예시에서는 ngrok 경유)
$ aws kms create-custom-key-store \
    --custom-key-store-name myVaultKeyStore \
    --custom-key-store-type EXTERNAL_KEY_STORE \
    --xks-proxy-uri-endpoint https://example.ngrok.io \
    --xks-proxy-uri-path /xyz/kms/xks/v1 \
    --xks-proxy-authentication-credential AccessKeyId=AKIA4G...2HPM,RawSecretAccessKey=1234567890123456789012345678901234567890123= \
    --xks-proxy-connectivity PUBLIC_ENDPOINT
{
  "CustomKeyStoreId": "cks-d7a55fe93d63191d6"
}
  1. KMS에 키 스토어에 연결하라고 지시하기.
$ aws kms connect-custom-key-store --custom-key-store-id cks-d7a55fe93d63191d6
  1. 커스텀 키 스토어의 ConnectionStateCONNECTED가 될 때까지 기다립니다. 이는 몇 분이 걸릴 수 있습니다.
$ aws kms describe-custom-key-stores --custom-key-store-id cks-d7a55fe93d63191d6
  1. XKS 키 ID(이 예시에서는 abc123)와 연결된 KMS 키를 만듭니다.
$ aws kms create-key --custom-key-store-id cks-d7a55fe93d63191d6 \
    --xks-key-id abc123 --origin EXTERNAL_KEY_STORE
{
  "KeyMetadata": {
    "AWSAccountId": "111111111111",
    "KeyId": "a93f205a-2a37-4338-aa64-92b4a4b0b67d",
    "Arn": "arn:aws:kms:us-east-2:111111111111:key/a93f205a-2a37-4338-aa64-92b4a4b0b67d",
    "CreationDate": "2022-12-22T11:03:23.695000-08:00",
    "Enabled": true,
    "Description": "",
    "KeyUsage": "ENCRYPT_DECRYPT",
    "KeyState": "Enabled",
    "Origin": "EXTERNAL_KEY_STORE",
    "CustomKeyStoreId": "cks-16460f66b34705025",
    "KeyManager": "CUSTOMER",
    "CustomerMasterKeySpec": "SYMMETRIC_DEFAULT",
    "KeySpec": "SYMMETRIC_DEFAULT",
    "EncryptionAlgorithms": [ "SYMMETRIC_DEFAULT" ],
    "MultiRegion": false,
    "XksKeyConfiguration": {
      "Id": "abc123"
    }
  }
}
  1. 이 키로 일부 데이터를 암호화합니다.
$ aws kms encrypt --key-id a93f205a-2a37-4338-aa64-92b4a4b0b67d --plaintext YWJjMTIzCg==
{
  "CiphertextBlob": "somerandomciphertextblob=",
  "KeyId": "arn:aws:kms:us-east-2:111111111111:key/a93f205a-2a37-4338-aa64-92b4a4b0b67d",
  "EncryptionAlgorithm": "SYMMETRIC_DEFAULT"
}
  1. 결과 암호문을 복호화합니다.
$ aws kms decrypt --ciphertext-blob somerandomciphertextblob=
{
  "KeyId": "arn:aws:kms:us-east-2:111111111111:key/a93f205a-2a37-4338-aa64-92b4a4b0b67d",
  "Plaintext": "YWJjMTIzCg==",
  "EncryptionAlgorithm": "SYMMETRIC_DEFAULT"
}
  1. 선택적으로 키와 키 스토어를 정리합니다.
$ aws kms disable-key --key-id a93f205a-2a37-4338-aa64-92b4a4b0b67d
$ aws kms disconnect-custom-key-store --custom-key-store-id cks-16460f66b34705025
$ aws kms delete-custom-key-store --custom-key-store-id cks-16460f66b34705025

(aws kms delete-custom-key-store 명령은 키 스토어의 모든 키가 비활성화되고 삭제될 때까지 성공하지 않습니다.)

더 알아보기 (Learn more)