iamjjanga blog

Vault Auto Unseal With AWS KMS

0. Intro

1. Sealing in Vault

1.1 Seal & Unseal

Auto-unseal Vault using AWS KMS | Vault | HashiCorp Developer

alt text

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 과정이 필요하다.

1.2 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)에 머무르게된다.

1.3 Solution

Vault는 다양한 Cloud Vendor에서의 Key-Value Management Solution을 통해 Auto Unsealing이 가능한 구성을 지원하고 있다.

alt text

Auto-unseal Vault using AWS KMS | Vault | HashiCorp Developer

해당 Docs에서는 AWS Credentials Key(’Access key’, ‘Secret Key’) 기준의 작업사항으로 설명되어 있어서, 실무환경에 맞게 IRSA(IAM Role for Service Account)를 통한 작업으로 우회해서 진행

2. Configurations

Vault Standalone 모드 환경에서의 테스트는 아래 Repo 참고

k8s-lab/projects/vault/vault-auth-unseal-with-awskms at main · iamjjanga-ouo/k8s-lab

2.1 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}

2.2 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}

2.3 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가지 경우가 있을 수 있다.

  1. 아직 Vault Init을 하지않은 경우

    [Warning] Key 분실 시, Auto Unseal의 경우 복구가 힘들거나 어려울 수 있어서 반드시 백업이 필요

    1# vault-cli
    2kubectl exec vault-0 -- vault operator init \
    3	-format=json > cluster-keys.json
    
  2. 이전에 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

99. Ref

How to Configure AWS KMS for Vault Auto-Unseal

Vault not booting on AWS using awskms seal · Issue #368 · hashicorp/vault-helm

#Vault #Aws #Kms