본 게시물은Vault 공식 문서의 내용과 필자의 생각을 정리하였다. Vault는 무엇인지, 어디에 사용하는지, 왜 사용하는지, 어떻게 사용하는지 서술한다. Vault를 처음 접하는 인원은 Vault의 흐름과 골격을 이해할 수 있는 시간을 갖는다. 또한 Vault를 실질적으로 사용해보는 시간을 갖는다. Vault는 Dev 서버 모드를 지원한다. Dev 서버 모드는 사전 설정이 되어있는 데모 서버라고 생각하면 좋다. 사용자는 해당 데모 서버에서 Vault를 학습할 수 있다. 시간이 괜찮으면 Vault HA를 구성한다(시간이 있으면...).
hashicorp사의 Vault(볼트) - Java-Spring With Vault - 6
Vault Docker 환경 구성
[개요]
yum 패키지 설치 기능을 사용하여 Vault 환경을 구성할 수 있다. 이번에는 Docker를 활용하여 Vault 환경을 구성한다. 해당 환경을 구성하기 위해 Docker는 당연히 사용하며, Docker-Compose까지 사용한다. 디렉토리의 구조는 아래와 같다. 환경 구성 후 가동 및 테스트 API만 호출한다.
본 게시물은Vault 공식 문서의 내용과 필자의 생각을 정리하였다. Vault는 무엇인지, 어디에 사용하는지, 왜 사용하는지, 어떻게 사용하는지 서술한다. Vault를 처음 접하는 인원은 Vault의 흐름과 골격을 이해할 수 있는 시간을 갖는다. 또한 Vault를 실질적으로 사용해보는 시간을 갖는다. Vault는 Dev 서버 모드를 지원한다. Dev 서버 모드는 사전 설정이 되어있는 데모 서버라고 생각하면 좋다. 사용자는 해당 데모 서버에서 Vault를 학습할 수 있다. 시간이 괜찮으면 Vault HA를 구성한다(시간이 있으면...).
$vi ./.bash_profile
VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_ADDR
$source ./.bash_profile
// 또는
$ export VAULT_ADDR='http://127.0.0.1:8200'
// 확인
$set | grep VAULT_ADDR
[Vault 서버 가동 및 초기화]
Vault 서버 가동
"-config"에는 config.hcl의 경로를 지정한다.
$vault server -config=/home1/irteamsu/vault/config.hcl &
Vault 서버 초기화 및 Unsealing
Vault 서버 가동 후 최초 1회 초기화 작업을 진행한다. 해당 초기화 작업으로 Vault 설정정보에 따라 SSS 분할키와 Root 토큰을 생성한다. 별도의 설정 정보가 없을 경우 threshold는 (3, 5)이다. 즉 5개의 분할키를 부여하며, 원본을 만들기 위해서는 최소 3개의 분할키가 필요하다. 필자의 경우 프로덕트 환경이 아니기 때문에 아래의 분할키와 Root 토큰을 keyinfo.txt 파일에 보관하였다.
$vault operator init
2021-06-15T16:43:36.202+0900 [INFO] core: pre-seal teardown complete
Unseal Key 1: Iv9H20vmAUMkDaAfyuar2rSWyGnZgvBOhQPl7df4lrib
Unseal Key 2: G7SnjSZPOaZwkMX9rvCyK8ssdoIMAdAYu+oDo1b9uZ+j
Unseal Key 3: jNfpkii4QiJsuIUVwkuIm1jjIz+bzh5oalsfevXGs5Wc
Unseal Key 4: NnruCilytFhgdQ4zCQmKeSrrV4e8Ijws663trVHAamyl
Unseal Key 5: pqb+bP30/wAraxLITsnjza1ibDyqKIcAHTEZkDzf902W
Initial Root Token: s.ZPBA2pFTJEtmlaUfIEHk1Lq6
Vault initialized with 5 key shares and a key threshold of 3. Please securely
distribute the key shares printed above. When the Vault is re-sealed,
restarted, or stopped, you must supply at least 3 of these keys to unseal it
before it can start servicing requests.
Vault does not store the generated master key. Without at least 3 key to
reconstruct the master key, Vault will remain permanently sealed!
It is possible to generate new unseal keys, provided you have a quorum of
existing unseal keys shares. See "vault operator rekey" for more information.
서버 가동, 초기화 작업을 완료하였다. 그러나 Vault는 아직 "Sealed" 상태이다. 위의 분할키는 Vault의 상태를 "Unsealed" 상태로 전이할 수 있다.
위의 작업을 완료하면 Sealed false 값을 확인할 수 있다. Root 토큰으로 로그인한 사용자는 "vault operator seal" 명령을 사용하여 Vault 서버에 Sealing을 할 수 있다. root 사용자의 경우, vault operator seal을 통해 sealing을 다시 할 수 있다. 이제 Vault를 마음껏 사용할 수 있다.
[Vault 가동 스크립트 작성]
Vault를 기동할 때 "Unsealing" 절차는 필수이다. 해당 절차의 편리를 위해 스크립트를 작성한다. 스크립트는 아래와 같다.
start.sh
#!/bin/bash
partOfKey1=$1
partOfKey2=$2
partOfKey3=$3
if [ "$#" != 3 ]
then
echo "argument is not 3"
exit
else
vault server -config=/home1/irteamsu/vault/config.hcl &
sleep 1
echo -ne '\n'
vault operator unseal $1
vault operator unseal $2
vault operator unseal $3
fi
stop.sh
#!/bin/bash
pid=`ps aux | grep 'vault server' | grep -v grep | awk '{print $2}'`
if [ -z "$pid" ]
then
echo "server is not running"
else
echo "shutdown..."
kill -9 $pid
fi
추가 분기를 사용하여 kill -9, -15 옵션을 결정할 수 있다. 필자는 그냥 "-9"를 사용하였다. 프로덕트 환경의 경우, "-15" 옵션을 위한 분기 사용을 권한다.
$curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request PUT \
--data '{"policy":"# Dev servers have version 2 of KV secrets engine mounted by default, so will\n# need these paths to grant permissions:\npath \"secret/data/*\" {\n capabilities = [\"create\", \"update\"]\n}\n\npath \"secret/data/foo\" {\n capabilities = [\"read\"]\n}\n"}' \
-D - http://127.0.0.1:8200/v1/sys/policies/acl/my-policy
이렇게 Dev 모드가 아닌 실제 서버를 설정하였다. 해당 서버는 vault 커맨드를 사용하여 제어할 수 있으며, REST API를 사용하여 제어할 수 있다. 본 게시글은 curl 명령과 함께 REST API를 사용하였다. 실질적으로 프로덕션 레벨에서는 클라이언트 토큰을 생성 후, Secret을 제어하는 것이다. 해당 사항은 Java/Spring환경을 구성한 후 테스트 예정이다.
본 게시물은Vault 공식 문서의 내용과 필자의 생각을 정리하였다. Vault는 무엇인지, 어디에 사용하는지, 왜 사용하는지, 어떻게 사용하는지 서술한다. Vault를 처음 접하는 인원은 Vault의 흐름과 골격을 이해할 수 있는 시간을 갖는다. 또한 Vault를 실질적으로 사용해보는 시간을 갖는다. Vault는 Dev 서버 모드를 지원한다. Dev 서버 모드는 사전 설정이 되어있는 데모 서버라고 생각하면 좋다. 사용자는 해당 데모 서버에서 Vault를 학습할 수 있다. 시간이 괜찮으면 Vault HA를 구성한다(시간이 있으면...).
$vault policy list
$vault policy read default
$vault policy write my-policy - << EOF
# Dev servers have version 2 of KV secrets engine mounted by default, so will
# need these paths to grant permissions:
path "secret/data/*" {
capabilities = ["create", "update"]
}
path "secret/data/foo" {
capabilities = ["read"]
}
EOF
$vault token lookup
$vault token create -policy=my-policy
$export VAULT_TOKEN="$(vault token create -field token -policy=my-policy)"
$vault kv put secret/creds password="my-long-password"
$vault kv put secret/creds password="my-long-password-1"
$vault kv get secret/creds //(안됨)
$export VAULT_TOKEN="s.kZw14yyEbEIkDSRRSLEsVM8M" //(root 토큰)
$vault kv get secret/creds(됨)
설명
토큰 생성 시 정책을 적용할 수 있다.
정책은 Secret에 대해 접근제어를 실시한다.
정책 "my-policy의 설명은 다음과 같다.
"secret/data 이하의 경로에 대해 create와 update 작업을 실시할 수 있다(udpate는 put을 통한 갱신 작업).
"secret/data/foo에 해당하는 경로는 read 작업을 실시할 수 있다.
다음의 설명은 생략한다.
[Vault 사용 - AppRole]
위의 "토큰 생성" 부분에서 Vault는 사용자의 토큰을 인증 절차 없이 생성한다. 이유는 다음과 같다. 현재 적용된 토큰은 "루트 토큰"이다. 그래서 인증 절차 없이 사용자의 토큰을 생성할 수 있다. 그러나 일반적인 상황에서는 인증 절차가 필요하다. 대표적인 인증 절차는 ID/PW 방식을 사용할 수 있다. Vault의 AppRole은 식별값(ID)/인증값(PW)을 이용해서 토큰을 발급한다. 또한 정책을 적용할 수 있으며, 토큰에 적용 가능하다.
// approle 확인
$vault auth list | grep 'approle/'
// 리스트업이 되지 않을 경우, approle 활성화
$vault auth enable approle
// approle 확인
$vault auth list | grep 'aaprole/'
//approle에 my-role(사용자) 생성
$vault write auth/approle/role/my-role \
secret_id_ttl=10m \
token_num_uses=10 \
token_ttl=20m \
token_max_ttl=30m \
secret_id_num_uses=40 \
token_policies=my-policy
// approle 조회
$vault list auth/approle/role
$vault read auth/approle/role/my-role
$vault read auth/approle/role/my-role/role-id
$vault read -field=role_id auth/approle/role/my-role/role-id
// ROLE_ID(식별자) 환경 변수 적용 및 조회
$export ROLE_ID="$(vault read -field=role_id auth/approle/role/my-role/role-id)"
$set | grep -e VAULT -e ROLE_ID
// SECRET_ID 설정(AppRole 인증을 위한 비밀번호 개념과 비슷하다.)
// SECRET_ID(인증값) 환경 변수 적용 및 조회
// vault write를 별도로 진행해도 괜찮다.
$export SECRET_ID="$(vault write -f -field=secret_id auth/approle/role/my-role/secret-id)"
$set | grep -e SECRET_ID -e VAULT -e ROLE_ID
// 토큰 요청
// approle 인증 완료 후, 토큰을 반환받을 수 있다.
$vault write auth/approle/login role_id="$ROLE_ID" secret_id="$SECRET_ID"
본 게시물은 Vault 공식 문서의 내용과 필자의 생각을 정리하였다. Vault는 무엇인지, 어디에 사용하는지, 왜 사용하는지, 어떻게 사용하는지 서술한다. Vault를 처음 접하는 인원은 Vault의 흐름과 골격을 이해할 수 있는 시간을 갖는다. 또한 Vault를 실질적으로 사용해보는 시간을 갖는다. Vault는 Dev 서버 모드를 지원한다. Dev 서버 모드는 사전 설정이 되어있는 데모 서버라고 생각하면 좋다. 사용자는 해당 데모 서버에서 Vault를 학습할 수 있다. 시간이 괜찮으면 Vault HA를 구성한다(시간이 있으면...).
hashicorp사의 Vault(볼트) - Java-Spring With Vault - 6
개요
HashiCorp의 Vault는 민감한 데이터를 안전하게 저장하는 저장소이다. 민감한 데이터의 종류는 다음과 같다. 1)Secret 2)Credential 3)Password 4)Enctyption-Key 등이다. 이와 같이 기밀성이 요구되는 정보는 DBMS에 단순 저장하면 안 된다. Vault는 위의 개체들을 암호화하여 안전하게 저장한다.
용어 정의
Storage Backend
Vault의 암호화된 Secret을 보관하는 곳이다.
Barrier
Barrier는 Vault의 일부 구성요소를 감싸고 있다. 때문에 Vault와 Storage Backend 간의 통신은 Barrier를 거쳐야 하며, Barrier가 프록시 역할(대문 역할)을 한다. Barrier의 구성요소들은 서로 Trust 한 관계를 유지/성립한다.
Vault는 암호화된 데이터만 밖으로 나오게 한다.
Vault는 Barrier의 상태가 “unsealed”가 되어야 접근할 수 있다.
Secret Engine
Secret의 관리를 책임진다.
Secret 관련 작업은 Secret Engine으로 전달하고 Engine의 구현체마다 상이한 방식으로 저장한다.
Secret Engine의 인터페이스를 활용하여 DB, File System 또는 유저가 정의한 방식으로 저장한다.
Audit Device
모든 Vault의 Request/Respones는 Audit Device에 의해 감사 로깅이 된다.
Auth Method
Vault에 접근하는 클라이언트를 인증한다.
인증된 클라이언트의 토큰을 반환한다.
Client Token
HTTP에서의 세션 ID와 같은 토큰을 반환한다.
Vault의 REST API를 사용하는 경우 HTTP 헤더에 토큰을 적재한다.
Secret
Vault에서 관리하는 비밀 객체이다.
Secret은 일정 주기를 가지며, 해당 주기가 만료되면 폐기해야 한다.
아키텍처 개요
[전체 흐름]
Vault는 기밀성이 요구되는 데이터(이하 Secret)를 안전하게 보관하는 저장소이다. Vault를 사용하기 위해서는 “unsealing”과초기화 작업이 필요하다. Vault 서버 초기화 시 Vault는 “sealed” 상태이다. “Unsealed-Key”는 “sealed” 상태를 “unsealed” 상태로 전이할 수 있다. “unsealed” 상태가 되면 Barrier안에 있는 Vault의 모든 기능 및 구성요소에 원활하게 접근할 수 있다.
Vault에서 실질적으로 Secret을 암/복호화하는 키는 "Encryption-Key"이다.
“Encryption-Key”는“Secret”을 안전하게 암/복호화한다. “Secret”들은 “Storage backend”에 보관하며, “Secret”에 접근하기 위해서는 REST API를 사용한다. REST API는 Create, Register, Rotate, Destroy 등의 명령을 제공하며, "Secret"을 제어할 수 있다. REST API를 사용하기 위해서는 "토큰 인증"과 "토큰에 상응하는 정책 인가" 작업이 필요하다.
[고가용성]
Vault는 HA를 구성할 수 있다. HA의 구조는 Active-Standby 구조이다. 오픈 소스 버전의 경우 Standby는 Read-Only 기능을 제공하지 않는다. Standby에 요청이 들어오면 요청을 Active에 포워딩한다. Read-Only 기능은 엔터프라이즈에서 제공한다. 그래도 오픈 소스 버전에서 Hot-Standby를 제공하기 때문에 Failover는 문제없다. 제일 큰 단점은 Standby의 read-only의 미지원이다. Product 레벨에서 Vault를 사용하기 위해서는 해당 기능이 제일 필요할 것 같다.
Replication 방식은 PostgreSQL의 방식과 같이 Active-Standby 구성이며, Active의 변경/추가/삭제된 것에 대한 로그(WAL, Write Ahead Log)를 Standby에 전송한다. 데이터 처리에 있어 보통의 DBMS과 같이 WAL 기법을 사용하는 것 같다.
[보안 특성]
Vault와 클라이언트 상호 인증은 제공하지 않는다. 다만 서버에서 제공하는 네트워크 계층 보안, TLS를 제공한다.
정상 토큰을 보유한 주체는 리소스("Secret")에 접근할 수 있다.
토큰 인가 정책은 리소스에 접근하는 주체를 제어한다.
Secret에 접근하는 모든 행위를 감사 로깅한다.
"Secret"을 암호화하여 Storage Backend에 저장한다.
Vault의 Barrier를 통과하는 모든 요청과 반환은 AES-256(GCM)으로 암호화한다. IV의 경우, 자동으로 임의로 생성한다.
SSS(Shamir Secret Sharing) 알고리즘으로 MasterKey를 분리 보관한다.
[Key 회전(갱신)]
rekey 명령은 Unsealed-Key와 Master-Key를 갱신한다. 갱신된 Master-Key는 Encryption-Key를 재암호화하며,갱신된 Unsealed-Key는 SSS에 의해 다시 분리하여 보관하여야 한다.
rotate 명령은 Encryption-Key를 갱신한다. 기존 Encryption-Key는 별도의 keyring에 보관한다. 후의 요청들은 새로운 Encryption-Key로 암호화를 한다. Keyring에 있는 Encryption-Key는 복호화 용도에만 사용한다. 이와 같이 사용하면 re-encryption을 수행하지 않아도 괜찮다(keyring에 예전 Encryption-Key를 다 보관하고 있다. 갱신에 의미가 있나?).
[정책]
사용자는 Identifier/Authentication값을 요청한다. 요청 성공 시 토큰을 반환받는다. 해당 토큰은 다음과 같이 화이트 리스트 정책을 갖고 있다
# This section grants all access on "secret/*". Further restrictions can be # applied to this broad policy, as shown below. path "secret/*" { capabilities = ["create", "read", "update", "delete", "list"] } # Permit reading secret/foo/bar/teamb, secret/bar/foo/teamb, etc. path "secret/+/+/teamb" { capabilities = ["read"] } # Policies can also specify allowed, disallowed, and required parameters. Here # the key "secret/restricted" can only contain "foo" (any value) and "bar" (one # of "zip" or "zap"). path "secret/restricted" { capabilities = ["create"] allowed_parameters = { "foo" = [] "bar" = ["zip", "zap"] } }