Vault Auto Unseal With AWS KMS
Intro
Sealing in Vault
Seal & Unseal
Auto-unseal Vault using AWS KMS | Vault | HashiCorp Developer

Vault Server는 기본적으로 시작 시, Sealed 상태로 시작하게 된다. Sealed 상태인경우 Secret에 대한 Decrypt가 불가능하다.
Unsealing is the process of constructing the master key necessary to decrypt the data encryption key
Encrypted Secret을 Decrypt하기 위해서는 Shared Key로 1차적으로 Unsealing을 하고, Root Key를 통한 Decrypt 과정이 필요하다.
Challenge
Vault unseal operation requires a quorum of existing unseal keys split by Shamir’s Secret sharing algorithm. This prevents one person from having full control of Vault
Vault Unsealing은 Shamir’s Secret Sharing Algorithm(SSS)으로 분할된 Key의 일정수를 요구한다. Sealing 상태를 1개의 Key로만 풀지못하도록 설계되었다. (하지만, 실제로는 가능하다)
하지만 Production Operation환경에서 다양한 원인(Evicted, Drain Pods…)으로 Vault Server가 Restart 등의 이유로 Sealing 상태로 변경되는 부분은 자주 있다.
현재의 Vault를 사용하는 Architecture 구조상에서 Appication Configurations, Secret Info을 Vault Agent Injector, Vault Static Secret Operator 등으로 Application이 Secret을 가져오는 구조로 되어있는데, Vault가 Sealing 상태로 있는경우 Secret을 가져오지 못하는 상태 (Pod Initializing)에 머무르게된다.
Solution
Vault는 다양한 Cloud Vendor에서의 Key-Value Management Solution을 통해 Auto Unsealing이 가능한 구성을 지원하고 있다.
- AliCloud KMS, AWS KMS, Azure Key Vault, Google Cloud KMS, and OCI KMS

Auto-unseal Vault using AWS KMS | Vault | HashiCorp Developer
해당 Docs에서는 AWS Credentials Key(’Access key’, ‘Secret Key’) 기준의 작업사항으로 설명되어 있어서, 실무환경에 맞게 IRSA(IAM Role for Service Account)를 통한 작업으로 우회해서 진행
- AWS KMS 생성
- AWS KMS에 접근하는 최소 정책을 가진 IRSA 생성
Configurations
Vault Standalone 모드 환경에서의 테스트는 아래 Repo 참고
k8s-lab/projects/vault/vault-auth-unseal-with-awskms at main · iamjjanga-ouo/k8s-lab
KMS 생성
Vault의 Auto UnSealing용 키를 등록하기 위한 AWS KMS를 생성한다.
1locals {
2 project = "vault"
3 env = "dev"
4 name = "auto-unseal-with-awskms"
5}
6
7data "aws_caller_identity" "current" {}
8
9module "kms" {
10 source = "terraform-aws-modules/kms/aws"
11
12 description = "Vault Auto-Unseal using AWS KMS Key"
13 ## IMPT: 암호화 및 복호화용 키 목적으로 반드시 "ENCRYPT_DECRYPT"로 설정
14 key_usage = "ENCRYPT_DECRYPT"
15 customer_master_key_spec = "SYMMETRIC_DEFAULT"
16
17 ## FIXME: key 관리용 IAM Role
18 key_administrators = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/__PLACE_HOLDER__"]
19
20 # Aliases
21 aliases = ["vault/auto-unseal-key"]
22
23 tags = {
24 Terraform = "true"
25 Environment = local.env
26 }
27}
IRSA(IAM Role for ServiceAccount) 생성
Service Account(여기서는 vault )가 생성된 AWS KMS에 접근할 수 있도록 IRSA용 IAM Policy와 IAM Role을 생성한다.
1module "iam-policy" {
2 depends_on = [module.kms]
3
4 source = "terraform-aws-modules/iam/aws//modules/iam-policy"
5
6 name = "${local.project}-${local.env}-${local.name}-policy"
7 path = "/"
8 description = "Created from the Terraform"
9 policy = jsonencode({
10 "Version" : "2012-10-17",
11 "Statement" : [
12 {
13 "Sid" : "AllowVaultAutoUnseal",
14 "Effect" : "Allow",
15 "Action" : [
16 "kms:Encrypt",
17 "kms:Decrypt",
18 "kms:ReEncrypt*",
19 "kms:GenerateDataKey*",
20 "kms:DescribeKey"
21 ],
22 "Resource" : module.kms.key_arn
23 }
24 ]
25 })
26
27 tags = {
28 Terraform = "true"
29 Environment = local.env
30 }
31}
32
33module "iam-irsa" {
34 depends_on = [module.iam-policy]
35
36 source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks"
37
38 role_name = "${local.project}-${local.env}-${local.name}-irsa"
39
40 role_policy_arns = {
41 AllowVaultAutoUnseal = "${module.iam-policy.arn}"
42 }
43
44 oidc_providers = {
45 default = {
46 ## FIXME: change eks oidc provider arn
47 provider_arn = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/oidc.eks.ap-northeast-2.amazonaws.com/id/__PLACE_HOLDER__"
48 namespace_service_accounts = ["vault:vault"]
49 }
50 }
51
52 tags = {
53 Terraform = "true"
54 Environment = local.env
55 }
56}
Vault (Helm)
Vault에서 Auto-Unseal을 사용하기 위한 백엔드 구성을 진행한다.
1server:
2 serviceAccount:
3 annotations:
4 eks.amazonaws.com/role-arn: "arn:aws:iam::__PLACE_HOLDER__:role/__PLACE_HOLDER__"
5
6## Standalone을 사용하는 경우
7 standalone:
8 config: |
9 ui = true
10
11 seal "awskms" {
12 region = "__PLACE_HOLDER__"
13 kms_key_id = "__PLACE_HOLDER__"
14 }
15
16## HA mode를 사용하는 경우
17ha:
18 enabled: true
19 replicas: 3
20 raft:
21 enabled: true
22 setNodeId: true
23
24 config: |
25 ui = true
26
27 seal "awskms" {
28 region = "__PLACE_HOLDER__"
29 kms_key_id = "__PLACE_HOLDER__"
30 }
Auto-Unseal을 등록하고서는 다음 2가지 경우가 있을 수 있다.
아직 Vault Init을 하지않은 경우
[Warning] Key 분실 시, Auto Unseal의 경우 복구가 힘들거나 어려울 수 있어서 반드시 백업이 필요
1# vault-cli 2kubectl exec vault-0 -- vault operator init \ 3 -format=json > cluster-keys.json이전에 Vault Init을 한 경우
- 이전에 생성된 UnSeal용 Key를 AWS KMS로 마이그레이션이 필요하다.
1vault operator unseal -migrate <unseal-key>
Auto-Unseal이 적용된 Vault의 상태 조회
1kubectl exec -it vault-0 -- vault status
2
3Key Value
4--- -----
5Seal Type awskms
6Recovery Seal Type shamir
7Initialized true
8Sealed false
9Total Recovery Shares 5
10Threshold 3
11Version 1.18.1
12Build Date 2024-10-29T14:21:31Z
13Storage Type raft
14Cluster Name vault-integrated-storage
15Cluster ID abcd-abcd-abcd
16HA Enabled true
17HA Cluster https://vault-2.vault-internal:8201
18HA Mode standby
19Active Node Address http://10.0.62.178:8200
20Raft Committed Index 8311
21Raft Applied Index 8311
실제로 Pod를 재시작해보면 아래와 같은 로그가 출력되면서 Auto-Unsealing이 된다.
1==> Vault server configuration:
22025-11-17T07:37:09.413Z [INFO] proxy environment: http_proxy="" https_proxy="" no_proxy=""
32025-11-17T07:37:09.558Z [INFO] incrementing seal generation: generation=1
42025-11-17T07:37:09.560Z [INFO] core: Initializing version history cache for core
52025-11-17T07:37:09.560Z [INFO] events: Starting event system
62025-11-17T07:37:09.560Z [INFO] core: stored unseal keys supported, attempting fetch
7...
82025-11-17T07:37:09.667Z [INFO] core: post-unseal setup complete
92025-11-17T07:37:09.667Z [INFO] core: vault is unsealed
102025-11-17T07:37:09.667Z [INFO] core: unsealed with stored key