hashicorp사의 Vault(볼트) - Tutorial-Real(With-REST-API) - 3
목차
- 들어가며
- Vault Real 서버 튜토리얼
- 참고문헌
들어가며
본 게시물은 Vault 공식 문서의 내용과 필자의 생각을 정리하였다. Vault는 무엇인지, 어디에 사용하는지, 왜 사용하는지, 어떻게 사용하는지 서술한다. Vault를 처음 접하는 인원은 Vault의 흐름과 골격을 이해할 수 있는 시간을 갖는다. 또한 Vault를 실질적으로 사용해보는 시간을 갖는다. Vault는 Dev 서버 모드를 지원한다. Dev 서버 모드는 사전 설정이 되어있는 데모 서버라고 생각하면 좋다. 사용자는 해당 데모 서버에서 Vault를 학습할 수 있다. 시간이 괜찮으면 Vault HA를 구성한다(시간이 있으면...).
본 게시물의 시리즈는 다음과 같다.
- hashicorp사의 Vault(볼트) - 개요 - 1
- hashicorp사의 Vault(볼트) - Tutorial-Dev(With-커맨드) - 2
- hashicorp사의 Vault(볼트) - Tutorial-Real(With-REST-API) - 3
- hashicorp사의 Vault(볼트) - Tutorial-Docker - 4
- hashicorp사의 Vault(볼트) - Tutorial-HA - 5
- hashicorp사의 Vault(볼트) - Java-Spring With Vault - 6
Vault Real 서버 튜토리얼
[Vault 최종 디렉토리 구성]
- config.hcl: Vault 엔진 설정 정보
- data: 데이터를 보관하는 장소
- keyinfo.txt: SSS 알고리즘으로 분할한 키와 Root 토큰 정보
- start.sh: Vault를 기동하기 위한 쉘 스크립트
- stop.sh: Vault를 종료하기 위한 쉘 스크립트
굵게 표시한 것은 필수적으로 구성해야 하는 것이며, 기울여서 표시한 것은 편리를 위해 구성한 것이다. 그러나 프로덕트 환경에서는 keyinfo.txt 파일은 별도 디바이스에 보관해야 한다.
[환경 구성]
CentOS 기준, yum 명령어를 사용하여 Vault를 설치한다. 설치방법은 Vault Tutorial 페이지에서 확인할 수 있다.
$mkdir vault
$cd vault
$vi config.hcl
storage "raft" {
path = "./data"
node_id = "node1"
}
listener "tcp" {
address = "127.0.0.1:8200"
tls_disable = "true"
}
api_addr="http://127.0.0.1:8200"
cluster_addr="https://127.0.0.1:8201"
ui = true
$mkdir data
아래와 같이 VAULT_ADDR 환경변수 설정
$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" 상태로 전이할 수 있다.
$vault operator unseal G7SnjSZPOaZwkMX9rvCyK8ssdoIMAdAYu+oDo1b9uZ+j
$vault operator unseal jNfpkii4QiJsuIUVwkuIm1jjIz+bzh5oalsfevXGs5Wc
$vault operator unseal NnruCilytFhgdQ4zCQmKeSrrV4e8Ijws663trVHAamyl
위의 작업을 완료하면 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" 옵션을 위한 분기 사용을 권한다.
[Vault 사용 - REST API - 서버 상태 확인]
$curl http://127.0.0.1:8200/v1/sys/init | jq
[Vault 사용 - REST API - auth method 활성화]
(Root 토큰을 환경변수에 지정한다(VAULT_TOKEN).)
$curl -X POST -H "X-Vault-Request: true" -H "X-Vault-Token: $VAULT_TOKEN" -d '{"type":"approle","description":"","config":{"options":null,"default_lease_ttl":"0s","max_lease_ttl":"0s","force_no_cache":false},"local":false,"seal_wrap":false,"external_entropy_access":false,"options":null}' http://127.0.0.1:8200/v1/sys/auth/approle
[Vault 사용 - REST API - 정책 추가]
$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
커맨드 명령어를 사용하여, 추가한 정책을 확인한다.
$vault policy list
[Vault 사용 - REST API - SecretPath 생성]
$curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{ "type":"kv-v2" }' \
-D - http://127.0.0.1:8200/v1/sys/mounts/secret
[Vault 사용 -REST API - 정책 기반으로 Role 생성]
$curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{"policies": ["my-policy"]}' \
-D - http://127.0.0.1:8200/v1/auth/approle/role/my-role
커맨드 명령어를 사용하여, 추가한 Role을 확인한다.
$vault list auth/approle/role
$vault read auth/approle/role/my-role
$vault read auth/approle/role/my-role/role-id
REST API를 사용하여, 추가한 Role을 확인한다.
$curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
http://127.0.0.1:8200/v1/auth/approle/role/my-role/role-id | jq -r ".data"
[Vault 사용 - REST API - Secret-ID 생성/확인]
$curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
http://127.0.0.1:8200/v1/auth/approle/role/my-role/secret-id | jq -r ".data"
//응답
{
"secret_id": "c7d3485f-403d-0c57-320d-3eb97697d85a",
"secret_id_accessor": "b0e25931-9e7e-4a4d-80b6-11a0087671d5",
"secret_id_ttl": 0
}
[Vault 사용 - REST API - AppRole 인증 및 클라이언트 토큰 반환]
ㄴㅇ
$curl --request POST \
--data '{"role_id": "93bfae74-3356-9b0d-08b3-8c2cdc76f55a", "secret_id": "c7d3485f-403d-0c57-320d-3eb97697d85a"}' \
http://127.0.0.1:8200/v1/auth/approle/login | jq -r ".auth"
// 응답
{
"client_token": "s.DOqgLc4sIVKJjmgVIzCIJVeZ",
"accessor": "eRxKIqBlT3eKsKRCfvt80sLO",
"policies": [
"default",
"my-policy"
],
"token_policies": [
"default",
"my-policy"
],
"metadata": {
"role_name": "my-role"
},
"lease_duration": 2764800,
"renewable": true,
"entity_id": "d624b3eb-0e52-fb88-439f-f456a8519fa2",
"token_type": "service",
"orphan": true
}
[Vault 사용 - REST API - 클라이언트 토큰으로 Secret 저장]
먼저 클라이언트 토큰을 환경변수에 저장한다.
$export VAULT_TOKEN="s.DOqgLc4sIVKJjmgVIzCIJVeZ"
REST API를 사용하여 Secret을 저장한다.
$curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
--request POST \
--data '{ "data": {"password": "my-long-password"} }' \
http://127.0.0.1:8200/v1/secret/data/creds | jq -r ".data"
이렇게 Dev 모드가 아닌 실제 서버를 설정하였다. 해당 서버는 vault 커맨드를 사용하여 제어할 수 있으며, REST API를 사용하여 제어할 수 있다. 본 게시글은 curl 명령과 함께 REST API를 사용하였다. 실질적으로 프로덕션 레벨에서는 클라이언트 토큰을 생성 후, Secret을 제어하는 것이다. 해당 사항은 Java/Spring환경을 구성한 후 테스트 예정이다.
참고문헌
'개발관련 > 삽질' 카테고리의 다른 글
Vanilla(Pure)-JavaSciprt 게시판 페이징 - 1(기본/응용) (0) | 2021.07.27 |
---|---|
hashicorp사의 Vault(볼트) - Tutorial-Docker - 4 (0) | 2021.07.06 |
hashicorp사의 Vault(볼트) - Tutorial-Dev(With-커맨드) - 2 (0) | 2021.07.01 |
hashicorp사의 Vault(볼트) - 개요 - 1 (0) | 2021.06.29 |
Spring-Legacy to Spring-Boot 마이그레이션(Feat. 외장/내장-Tomcat/JSP/Multiple-Datasource(With-JNDI)/External-Lib) (0) | 2021.04.28 |