본문 바로가기
Security/Vault

Vault Transit Secret Engine 사용하기

by wlsdn3004 2024. 4. 1.
728x90
반응형

 

Vault Transit Secret Engine란?

Vault의 Transit Secret Engine은 데이터를 암호화하고 복호화하는 데 사용되는 서비스로, 키 관리와 암호화 서비스를 중앙화하여 제공한다. Transit Secret Engine은 전송 중인 데이터에 대한 암호화/복호화를 처리하고, 데이터를 저장하지 않는다는 특징이 있다.

 

즉 애플리케이션 외부에서 암호화하고, 애플리케이션은 암호화된 형태로 데이터를 처리하게 되기 때문에 데이터 유출 위험이 감소하게 되고, 애플리케이션 개발자의 암호화/복호화에 대한 부담을 덜어준다는 장점이 있다.

 

Transit의 암호화/복호화 동작 과정은 다음과 같다.

 

글 작성 기준 Transit Secret Engine은 다음 키 유형을 지원한다.

참고: https://developer.hashicorp.com/vault/docs/secrets/transit#key-types

 

이번 글에서는 실습을 통해 Vault의 Transit Secret Engine 기능을 통해 평문을 암호화/복호화하고, 암호문(ciphertext) 키를 간단하게  순환(rotate), 재암호화(rewrap)하는 실습을 다룬다. 

 

실습 환경

  • Amazon EKS 1.27.7
  • Helm Cli v3.8.2
  • Vault 1.15.2 (Vault 설치 참고: [Vault 설치])

 

 

Information Panel

참고

Vault의 Auto unseal 기능을 사용하지 않으면, Unseal 후 실습을 진행해야 한다.

1. Transit 사용을 위한 유저 생성 및 정책 설정


먼저, Vault 서버에 접근한다.

$ kubectl exec -it -n vault sts/vault -- /bin/sh

 

초기 Secret Engine 활성화 및 정책 생성을 위해 "root token"권한이 필요하므로 환경변수를 설정한다.

# ROOT TOKEN 환경변수 설정
$ export VAULT_TOKEN=<ROOT_TOKEN>

 

 transit secret engine을 활성화한다.

Information Panel

참고

이미 transit secret engine이 활성화되어 있으면 해당 과정은 진행하지 않아도 된다.

# transit secrets engine 활성화
$ vault secrets enable -path=transit transit
Success! Enabled the transit secrets engine at: transit/

 

transit 관리 권한을 위해 "transit-test"라는 이름의 정책을 생성한다.

$ vault policy write transit-test -<<EOF
path "sys/mounts/transit" {
  capabilities = [ "create", "read", "update", "delete", "list" ]
}

path "sys/mounts" {
  capabilities = [ "read" ]
}

path "transit/*" {
  capabilities = [ "create", "read", "update", "delete", "list" ]
}
Success! Uploaded policy: transit-test

 

유저 생성을 위해 "Username & Password" 인증 방법을 활성화한다.

$ vault auth enable userpass

 

앞전에 생성한 "transit-test" 정책을 사용할 수 있는 "transit-test" 이름으로 유저를 생성한다.

$ vault write auth/userpass/users/transit-test \
    password=<비밀번호 입력> \
    policies=transit-test
Success! Data written to: auth/userpass/users/transit-test

 

생성한 유저로 로그인한다.

$ vault login -method userpass username=transit-test password=<비밀번호 입력>

Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.

Key                    Value
---                    -----
token                  hvs.VBcTlMRVk4bUlDSTQ
token_accessor         UaO2Ri64YggpyjtZQBbH
token_duration         768h
token_renewable        true
token_policies         ["default" "transit-test"]
identity_policies      []
policies               ["default" "transit-test"]
token_meta_username    transit-test

 

 

2. Transit Secret Engine 암호화/복호화


test라는 이름의 암호화 키를 생성한다.

$ vault write -f transit/keys/test
Key                       Value
---                       -----
allow_plaintext_backup    false
auto_rotate_period        0s
deletion_allowed          false
derived                   false
exportable                false
imported_key              false
keys                      map[1:1711941597]
latest_version            1
min_available_version     0
min_decryption_version    1
min_encryption_version    0
name                      test
supports_decryption       true
supports_derivation       true
supports_encryption       true
supports_signing          false
type                      aes256-gcm96

 

test 키로 "hello"라는 평문을 암호화한다.

$ vault write transit/encrypt/test \
      plaintext=$(echo "hello" | base64)
Key            Value
---            -----
ciphertext     vault:v1:gh+XRqymJFiBtYXJJaTAiZAJ7QilXXGgL4B+O75awvLqQA==
key_version    1

 

앞전에 나온 ciphertext의 값으로 복호화하여 plaintext 내용을 확인한다.

$ vault write transit/decrypt/test \
      ciphertext="vault:v1:gh+XRqymJFiBtYXJJaTAiZAJ7QilXXGgL4B+O75awvLqQA=="
Key          Value
---          -----
plaintext    aGVsbG8K

 

복호화하여 나온 plaintext의 값으로 base64 디코딩하여 메세지를 확인한다.

$ echo "aGVsbG8K" | base64 -d
hello

 

위 과정을 다음과 같이 한 번에 입력하여 복호화할 수 있다.

$ vault write -field=plaintext transit/decrypt/test ciphertext="vault:v1:gh+XR
qymJFiBtYXJJaTAiZAJ7QilXXGgL4B+O75awvLqQA==" | base64 -d
hello

 

 

3. Transit Secret Engine 암호화 키 순환 (rotate)


"rotate" 기능은 암호화 키의 새로운 버전을 생성하는 데 사용된다. 이 기능은 기존의 암호화 키를 새로운 것으로 교체하는 과정을 단순화하여, 키 관리를 더 안전하고 효율적으로 만든다.

 

다음 명령을 통해 암호화 키를 순환한다.

$ vault write -f transit/keys/test/rotate
Key                       Value
---                       -----
allow_plaintext_backup    false
auto_rotate_period        0s
deletion_allowed          false
derived                   false
exportable                false
imported_key              false
keys                      map[1:1711941597 2:1711950639]
latest_version            2
min_available_version     0
min_decryption_version    1
min_encryption_version    0
name                      test
supports_decryption       true
supports_derivation       true
supports_encryption       true
supports_signing          false
type                      aes256-gcm96

keys 값이 2개로 늘어나고, latest_version이 2로 변경된 것을 확인할 수 있다.

 

다시 "hello"라는 평문을 암호화하면 ciphertext 값이 변경되고, "key_version"이 2로 보이는 것을 확인할 수 있다.

$ vault write transit/encrypt/test \
      plaintext=$(echo "hello" | base64)
Key            Value
---            -----
ciphertext     vault:v2:Ycy/4en8B/S/z8O5pGG7NecK4XjOd+3+yeN8FRMqnHKz0w==
key_version    2

 

이제 v2의 ciphertext 값과 v1의 ciphertext 값으로 복호화를 진행할 수 있다.

# v1 ciphertext 사용
$ vault write -field=plaintext transit/decrypt/test ciphertext="vault:v1:gh+XRqymJFiBtYXJJaTAiZAJ7QilXXGgL4B+O75awvLqQA==" | base64 -d
hello

# v2 ciphertext 사용
$ vault write -field=plaintext transit/decrypt/test ciphertext="vault:v2:Ycy/4en8B/S/z8O5pGG7NecK4XjOd+3+yeN8FRMqnHKz0w==" | base64 -d
hello

 

 

4. Transit Secret Engine 암호화 키 재암호화 (rewrap)


시간이 지남에 따라 암호화 키를 새로운 버전으로 업데이트해야 할 필요가 있을 수 있다. 이런 경우, "rewrap" 기능을 사용하여 이미 암호화된 데이터를 새로운 키 버전으로 다시 암호화할 수 있다.

 

다음 명령을 통해 맨 처음 만들었던 v1 ciphertext 값을 재암호화하여 v2로 만든다.

$ vault write transit/rewrap/test \
     ciphertext="vault:v1:gh+XRqymJFiBtYXJJaTAiZAJ7QilXXGgL4B+O75awvLqQA=="
Key            Value
---            -----
ciphertext     vault:v2:XwqAnrt5BjftO4nNG3QaSHLMDb/0Gem4PGURj/gHE9hfMA==
key_version    2

기존 v1 ciphertext 값이 rewrap 되어 "vault:v2:xxxxx"로 변경되고, key_version도 2로 변경된 것을 확인할 수 있다.

 

이제 v1의 ciphertext 값과 rewrap을 통해 v2가 된 ciphertext 값 두 개로 복호화를 진행한다.

# v1의 ciphertext 값
$ vault write -field=plaintext transit/decrypt/test ciphertext="vault:v1:gh+XRqymJFiBtYXJJaTAiZAJ7QilXXGgL4B+O75awvLqQA==" | base64 -d
hello

# v1를 rewrap한 v2 ciphertext 값
$ vault write -field=plaintext transit/decrypt/test ciphertext="vault:v2:XwqAnrt5BjftO4nNG3QaSHLMDb/0Gem4PGURj/gHE9hfMA==" | base64 -d
hello

동일한 결과가 나오는 것을 확인할 수 있다. 

 

 

5. Transit Secret Engine 기존 암호화 키 파기


test라는 transit key를 조회해 보면 "min_decryption_version"이 1인 것을 확인할 수 있다.

$ vault read transit/keys/test
Key                       Value
---                       -----
allow_plaintext_backup    false
auto_rotate_period        0s
deletion_allowed          false
derived                   false
exportable                false
imported_key              false
keys                      map[1:1711941597 2:1711950639]
latest_version            2
min_available_version     0
min_decryption_version    1
min_encryption_version    0
name                      test
supports_decryption       true
supports_derivation       true
supports_encryption       true
supports_signing          false
type                      aes256-gcm96

 

"min_decryption_version" 값을 2로 올리면 기존 v1에 사용했던 ciphertext 값을 통해 복호화를 진행할 수 없다.

다음 명령을 통해 "min_decryption_version" 값을 2로 설정한다.

$ vault write transit/keys/test/config min_decryption_version=2	
Key                       Value
---                       -----
allow_plaintext_backup    false
auto_rotate_period        0s
deletion_allowed          false
derived                   false
exportable                false
imported_key              false
keys                      map[2:1711950639]
latest_version            2
min_available_version     0
min_decryption_version    2
min_encryption_version    0
name                      test
supports_decryption       true
supports_derivation       true
supports_encryption       true
supports_signing          false
type                      aes256-gcm96

keys의 값에 [1:xxxx]는 사라지고, "min_decryption_version" 값이 2로 변경된 것을 확인할 수 있다.

 

이제 v1 ciphertext 값으로 복호화를 진행해 보자.

$ vault write -field=plaintext transit/decrypt/test ciphertext="vault:v1:gh+XRqymJFiBtYXJJaTAiZAJ7QilXXGgL4B+O75awvLqQA==" | base64 -d
Error writing data to transit/decrypt/test: Error making API request.

URL: PUT http://127.0.0.1:8200/v1/transit/decrypt/test
Code: 400. Errors:

* ciphertext or signature version is disallowed by policy (too old)

오래된 버전으로 허용되지 않는다는 메세지와 함께 실패하게 된다.

 

v2 ciphertext 값으로 복호화가 되는지 확인한다.

$ vault write -field=plaintext transit/decrypt/test ciphertext="vault:v2:XwqAnrt5BjftO4nNG3QaSHLMDb/0Gem4PGURj/gHE9hfMA==" | base64 -d
hello

정상적으로 되는 것을 확인할 수 있다.

 

첫 번째 rewrap을 통해 생성된 v2 ciphertext 값으로 다시 rewrap을 진행해 보자. (두 번째 rewrap 진행)

$ vault write transit/rewrap/test \
    ciphertext="vault:v2:XwqAnrt5BjftO4nNG3QaSHLMDb/0Gem4PGURj/gHE9hfMA=="
Key            Value
---            -----
ciphertext     vault:v2:+P0b8WahrnbBqvGP/bTk/9F/ufxVRzIlsNmsyLT2qqXR3Q==
key_version    2

 

두 번째 rewrap으로 생성된 ciphertext 값으로 복호화를 진행한다.

$ vault write -field=plaintext transit/decrypt/test ciphertext="vault:v2:+P0b8WahrnbBqvGP/bTk/9F/ufxVRzIlsNmsyLT2qqXR3Q==" | base64 -d
hello

 

첫 번째 rewarp 진행한 ciphertext 값도 복호화가 되는지 확인한다.

$ vault write -field=plaintext transit/decrypt/test ciphertext="vault:v2:XwqAnrt5BjftO4nNG3QaSHLMDb/0Gem4PGURj/gHE9hfMA==" | base64 -d
hello

 

"min_decryption_version" 값이 2이기 때문에 v2 ciphertext 값으로 복호화가 되는 것을 확인할 수 있다.

반응형

댓글