$ ethtool -a eth0
Pause parameters for eth0:
Autonegotiate: on
RX: on
TX: off
8. ethtool 명령어에 -p 옵션 사용 → 특정 포트에 LED를 깜빡
어뎁터가 4개의 포트를 가지고 있다고 가정하고, eth3번이 어떤 포트인지 알고 싶을때 LED 를 깜빡 거리게 하여 알려줌
$ ethtool -p eth3
9. ethtool 명령어에 -k 옵션 사용 → 디바이스의 Offload 정보 출력
Offload는 이더넷 카드에서 TOE 기능을 지원하게 되면 사용할 수 있는 기능
TOE
NIC(Network Interface Cards)에서 사용되는 기술
보통 운영체제 상에서 처리되는 TCP/IP 스택을 네트워크 컨트롤러로 내려서 처리
네트워크 처리가 크게 필요한 기가비트나 10G 기가비트같은 고속네트워크에서 유용하게 사용
$ ethtool -k eth0
Offload parameters for eth0:
rx-checksumming: on
tx-checksumming: on
scatter-gather: on
tcp-segmentation-offload: on
udp-fragmentation-offload: off
generic-segmentation-offload: on
generic-receive-offload: on
large-receive-offload: off
rx-vlan-offload: on
tx-vlan-offload: on
ntuple-filters: off
receive-hashing: off
10. ethtool 명령어 이외에 lshw명려어를 이용해 network 관련한 정보를 확인 가능
lshw(Hardware Lister)는 메모리, 펌웨어 버전, 메인보드, CPU, 네트워크, 디스크 등의 정보를 알려주는 명령어
Usage: vegeta [global flags] <command> [command flags]
global flags:
-cpus int
Number of CPUs to use (defaults to the number of CPUs you have)
-profile string
Enable profiling of [cpu, heap]
-version
Print version and exit
attack command:
-body string
Requests body file
-cert string
TLS client PEM encoded certificate file
-chunked
Send body with chunked transfer encoding
-connections int
Max open idle connections per target host (default 10000)
-duration duration
Duration of the test [0 = forever]
-format string
Targets format [http, json] (default "http")
-h2c
Send HTTP/2 requests without TLS encryption
-header value
Request header
-http2
Send HTTP/2 requests when supported by the server (default true)
-insecure
Ignore invalid server TLS certificates
-keepalive
Use persistent connections (default true)
-key string
TLS client PEM encoded private key file
-laddr value
Local IP address (default 0.0.0.0)
-lazy
Read targets lazily
-max-body value
Maximum number of bytes to capture from response bodies. [-1 = no limit] (default -1)
-max-workers uint
Maximum number of workers (default 18446744073709551615)
-name string
Attack name
-output string
Output file (default "stdout")
-proxy-header value
Proxy CONNECT header
-rate value
Number of requests per time unit [0 = infinity] (default 50/1s)
-redirects int
Number of redirects to follow. -1 will not follow but marks as success (default 10)
-resolvers value
List of addresses (ip:port) to use for DNS resolution. Disables use of local system DNS. (comma separated list)
-root-certs value
TLS root certificate files (comma separated list)
-targets string
Targets file (default "stdin")
-timeout duration
Requests timeout (default 30s)
-unix-socket string
Connect over a unix socket. This overrides the host address in target URLs
-workers uint
Initial number of workers (default 10)
encode command:
-output string
Output file (default "stdout")
-to string
Output encoding [csv, gob, json] (default "json")
plot command:
-output string
Output file (default "stdout")
-threshold int
Threshold of data points above which series are downsampled. (default 4000)
-title string
Title and header of the resulting HTML page (default "Vegeta Plot")
report command:
-buckets string
Histogram buckets, e.g.: "[0,1ms,10ms]"
-every duration
Report interval
-output string
Output file (default "stdout")
-type string
Report type to generate [text, json, hist[buckets], hdrplot] (default "text")
examples:
echo "GET http://localhost/" | vegeta attack -duration=5s | tee results.bin | vegeta report
vegeta report -type=json results.bin > metrics.json
cat results.bin | vegeta plot > plot.html
cat results.bin | vegeta report -type="hist[0,100ms,200ms,300ms]"
vegeta 부하테스트의 기본 컨맨드 설명
1. attack
공격을 어떻게 할 것인지에 대한 명령
-duration 옵션
대상에 요청을 발행하는 시간을 지정 → 얼마동안 공격을 할 것인가 대한 값
내부 동시성 구조의 설정은 -duration 값을 변수로 가지고 있음
테스트의 실제 실행 시간은 응답 지연으로 인해 지정된 것보다 더 길 수 있음
무한 공격에 0 사용
5초 동안 공격 예시
-duration=5s
-rate 옵션
대상에 대해 발행할 시간 단위당 요청 비율을 지정
실제 요청 비율은 가비지 수집 등으로 인해 약간 다를 수 있지만 전반적으로 지정된 값에 매우 가깝게 유지됨
기본적으로 1초에 몇개를 보낼 것인지 결정 → 설정하지 않은 경우 50/1s
만약 0으로 하게 되면 무한으로 요청보내게 되는데 그럴 경우에는 추가적으로 max-workers의 수를 지정 필요
host 당 1초에 10번 요청
-rate=10
-max-workers 옵션
max-workers는 vegeta를 실행할 때 같이 설정할 수 있는 옵션
worker는 만들어져서 공격을 하게 되는데 최대 몇개의 worker을 사용할 것인가에 해당하는 값을 지정
-max-workers는 공격에 사용되는 최대 작업자 수 지정
공격에서 사용하는 동시성 수준을 제어하는 데 사용 가능
-max-workers=10
2. report
결과값에 대해서 어떤 형식으로 볼 것인지에 대해서 설정하는 command
기본 설정인 text 출력 (-type=text)
Requests → 테스트 중에 전송된 총 요청 수와 요청 비율을 출력
Duration → 테스트의 총 기간, 애플리케이션에 대한 부하를 시뮬레이션하는 공격 기간 및 대기 시간을 출력
Latencies → 공격에 포함된 모든 요청의 지연 시간과 인식된 최대 지연 시간의 평균 지연 시간(각각 50번째, 95번째, 99번째 백분위수)을 출력
Bytes In → 요청 본문과 함께 전송 또는 수신된 바이트 수
Bytes Out → 응답 본문과 함께 출력 또는 송신된 바이트 수
Success → 애플리케이션으로 전송된 성공적인 요청의 백분위수를 출력
Status Codes → 수신된 HTTP 응답 코드 및 해당 발생에 대한 카운터를 제공 (0 상태 코드는 요청 전송에 실패를 의미)
$ vault policy write require-ssh-sign sign_policy.tf
Success! Uploaded policy: require-ssh-sign
# 생성된 정책 확인
$ vault policy list
default
require-ssh-sign
9. SSH Client에서 VAULT 서버로 접속할 Token 생성 → VAULT의 token값을 사용하기 위해서는 별도 저장 필요
※ ssh-client에서 export 시켜주면 Vault에서 CA 사인할 수 있는 public 키를 가져올 수 있음
SSH Server 설정 → SSH를 통해 접속하는 대상 서버
1. SSH Server에서 Vault server 접근할 수 있도록 환경변수 설정
VAULT_TOKEN 값은 SSH-Server에서 key를 read할 수 있도록 정책 설정 → s.fX6YPfJI8xvi8NKZiI8O12UF
VAULT 접속 도메인 설정 → [테스트 도메인]:8200
# 환경 변수 적용
export VAULT_ADDR=https://[테스트 도메인]:8200
export VAULT_TOKEN=s.fX6YPfJI8xvi8NKZiI8O12UF
# 영구적인 환경 변수 적용
$ echo -e "\n#SSH\nexport VAULT_ADDR=https://[테스트 도메인]:8200" >> /etc/bashrc
$ echo -e "export VAULT_TOKEN=s.fX6YPfJI8xvi8NKZiI8O12UF" >> /etc/bashrc
2. Vault server에서 CA의 public Key를 SSH Server에 전송
Vault server에서 public key 추출
$ vault read -field=public_key ssh-client-signer/config/ca > /root/trusted-user-ca-keys.pem
# 생성한 CA의 public key 확인
$ cat /root/trusted-user-ca-keys.pem
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDALoH6ItfBjGnqNJAwFa1xUzOJ38WVosCNZQ3o2BlFJxhXvejU1CalDQDCZXEK8SIxeOqKC3mu/nIGMLYR5lwWRgl5r3janyLw8174MSM1wgSy9ZcURZrivicafKrH2WQAXJ6TKsrlhR5GODwxRCciD02l8LgbvaBs8pt1SRmvCc17xBAMuwu/A0pBU+tHotfiBqeLlQThi2mhpRSZ9u2cIt4neP/g+1/hMDxjlhmge7ehQBNYyWc2n8HDubCYT+z2GANk8vk6DhXs5iaLozM1lALXQZlbK3MpIVh1HySnIewuw3rjgBlOc9sJMcrnQYdrb/EnJzLrcL4Sb4NmzB5gPW29vTc0Thkt4T4ghTCriOLCFjKihlc9sO8rsZ6fV10i/qfUONcrZYp1wVS18WOKQEBblgXp94L/Kl/mRVHFRicNDSVsZij9pHZovRprE3RkqO87qF67ZhcL3yzAVfkoRrWqDzG5PFpjGHLa3mV3nmL1vBKhL9/tkxbxz6svWkPYFSbxZx+JRSzzp3VPqFzSEiBmFNloCCVZfdSUMi5RlAD7r2NaCUR0+tXf0Io/YzXDuzMWk4Gq0FbJ+LWgfo1mXpj+iElmW4YS+oI6jyLVyQZEHZMvGcdiXyIZI76cdvqsjWL2C5e7O7p0ktTFmZfiBxHUUt3FbVZ+PqXk6H86uQ==
# scp를 통해 /etc/ssh 디렉토리 아래로 trusted-user-ca-keys.pem 파일 이동
$ ls -al /etc/ssh/trusted-user-ca-keys.pem
-rw-r--r-- 1 root root 725 Mar 1 17:39 /etc/ssh/trusted-user-ca-keys.pem
3. SSH 설정 → TrustedUserCAKeys /etc/ssh/trusted-user-ca-keys.pem 설정
$ vi /etc/ssh/sshd_config
Port 22000
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
# TrustedUserCAKeys 추가
TrustedUserCAKeys /etc/ssh/trusted-user-ca-keys.pem
4. SSH 재시작 및 상태 확인
$ systemctl restart sshd
# 상태 확인
$ systemctl status sshd
● sshd.service - OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2022-03-01 17:47:07 KST; 3s ago
Docs: man:sshd(8)
man:sshd_config(5)
Main PID: 62539 (sshd)
Tasks: 1
Memory: 1.0M
CGroup: /system.slice/sshd.service
└─62539 /usr/sbin/sshd -D
SSH Client 설정 → SSH 서버에 접속하는 SSH 클라이언트 서버
1. SSH Client에서 Vault server 접근할 수 있도록 환경변수 설정
VAULT_TOKEN 값은 SSH-Client에서 Vault Server에 CA사인 요청할 수 있도록 정책 설정 → s.HI8wvigrGvJuhUsk1H9ANmcl
VAULT 접속 도메인 설정 → https://[테스트 도메인]:8200
# 환경 변수 적용
export VAULT_ADDR=https://[테스트 도메인]:8200
export VAULT_TOKEN=s.HI8wvigrGvJuhUsk1H9ANmcl
# 영구적인 환경 변수 적용
echo -e "\n#SSH\nexport VAULT_ADDR=https://[테스트 도메인]:8200" >> /etc/bashrc
echo -e "export VAULT_TOKEN=s.HI8wvigrGvJuhUsk1H9ANmcl" >> /etc/bashrc
2. SSH key 생성 → 모두 enter로 넘어감
$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:ubVlwjtNjjxM9xoOdw6h8rSTF+zGfTeGt64/E1FIUwU root@180-70-134-115
The key's randomart image is:
+---[RSA 2048]----+
| .E++|
| ...|
| .|
| o . |
| S =.* .|
| * &oo . |
| o %+*o+ .|
| +oB=B.*o|
| o+o.B=*|
+----[SHA256]-----+
3. 생성한 key를 Vault server에 사인 요청하고 응답 결과 key를 저장
$ vault write -field=signed_key ssh-client-signer/sign/my-role public_key=@/root/.ssh/id_rsa.pub > /root/.ssh/id_rsa-cert.pub
# id_rsa.pub에 사인 요청을 해서 접속 확인
$ cat /root/.ssh/id_rsa-cert.pub
ssh-rsa-cert-v01@openssh.com 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
4. SSH Client 에서 SSH Server로 접속 확인 → 결과 정상 접속
$ ssh -p 22000 hippo@[SSH 접속 서버 IP]
Last login: Tue Mar 1 17:59:26 2022 from [SSH 클라이언트 서버 IP]
5. 5분뒤 접속 가능한지 확인 → Vault server에서 sign 유효 시간을 5분으로 설정
test하기 위해 5분 뒤에 생성했던 id_rsa-cert.pub로 접속 시도 → 실패
인증서 서명 유효기간이 만료되어 password로 접속 시도 하는 것을 확인 → 직접 비밀번호를 모르기에 오류 발생
새롭게 id_rsa-cert.pub을 생성한 후에 다시 로그인 시도
$ ssh -p 22000 hippo@[SSH 접속 서버 IP]
no such identity: /root/.ssh/id_ed25519: No such file or directory
hippo@[SSH 접속 서버 IP]'s password:
# 새롭게 인증서 만들어서 로그인 시도
$ vault write -field=signed_key ssh-client-signer/sign/my-role public_key=@/root/.ssh/id_rsa.pub > /root/.ssh/id_rsa-cert.pub
$ ssh -p 22000 hippo@[SSH 접속 서버 IP]
Last login: Tue Mar 1 17:59:55 2022 from [SSH 클라이언트 서버 IP]
$ vault login
Token (will be hidden):
WARNING! The VAULT_TOKEN environment variable is set! This takes precedence
over the value set by this command. To use the value set by this command,
unset the VAULT_TOKEN environment variable or set it to the token displayed
below.
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 s.asQ2M2u8kefJAH7pTRK9VZuY
token_accessor DhyddellBSpndis790yPJCIp
token_duration ∞
token_renewable false
token_policies ["root"]
identity_policies []
policies ["root"]
Sealing된 상태에서 Vault 서버에 로그인 → 로그인 시 에러 발생
$ vault login
Token (will be hidden):
Error authenticating: error looking up token: Error making API request.
URL: GET https://[테스트 도메인]:8200/v1/auth/token/lookup-self
Code: 503. Errors:
* Vault is sealed
Vault 서버는 sealed(봉인) 상태로 시작 → sealed(봉인) 상태는 저장된 정보를 어떤 경우에도 평문으로 볼 수 없음
Vault 데이터를 암호화하여 저장하기에, Unsealing(개봉) 전에는 거의 모든 작업이 불가능
암호화 키로 데이터를 암호화하고, 암호화 키는 키링에 보관하여 데이터와 함께 저장
키링은 마스터 키로 알려진 다른 암호화 키로 암호화
Vault는 데이터를 복호화하기 위하여 먼저 암호화 키를 마스터 키를 이용하여 복호화 → Unsealing(복호화)는 마스터 키에 접근하는 프로세스
마스터 키도 다른 모든 데이터와 함께 저장되지만 또 다른 메커니즘인 봉인해제 키(unseal key)에 의해 암호화
1. 데이터는 키링의 암호화 키로, 암호화 키는 마스터 키로, 마스터 키는 봉인해제 키로 암호화
"봉인해제 키 → 마스터 키 → 암호화 키 → 데이터"
2. Shamir’s Secret Sharing 샤미르의 비밀 공유
봉인해제 키는 샤미르의 비밀 공유 알고리즘을 사용하여 여러 조각으로 분할되어 생성 (RSA에 'S'의 그 Shamir)
각 봉인해제 키는 분리된 공간에 저장할 것을 권장
봉인해제 시에 각 키를 입력 받아 임계치 이상의 키가 입력이 되면 봉인해제
Vault에서는 기본 값으로 5개의 키가 생성이 되고, 3개의 키가 입력되면 봉인해제
Unsealing(봉인해제)
Unsealing는 아래의 과정 중 하나를 통하여 수행
터미널에서 vault operator unseal 명령을 입력 후 Unsealing 키를 차례로 입력
Unseal API 호출
WebUI에서 키를 차례로 입력
Unsealing 상태에서 다시 sealing 상태가 되는 경우는 아래 중 하나의 방법으로 수행
Seal API 호출
Vault 서버 재시작
Vault 저장소에서 복구할 수 없는 오류가 발생
Sealing(봉인)
sealing API를 호출하면 메모리에 있는 마스터 키가 폐기 → sealing 상태가 되면 vault를 사용하기 위해서 Unsealing 과정이 필요
sealing에는 루트 권한이 있는 단일 작업자만 필요
침입이 감지되었을 때 Vault 데이터를 빠르게 잠가 피해를 최소화 가능
Vault server 초기화할 때 unseal key 발행
key-shares → 발행되는 unseal key 개수
key-threshold → 인증할 때 unseal key 사용 개수
key-shares와 key-threshold 옵션을 사용 X → 5개의 unseal key 발행되고, 그 중 3개를 입력해야 vault CLI 명령 사용 가능
vault 서버 초기화할 때는 vault 서버의 API를 설정 필요
# VAULT_ADDR이 설정
VAULT_ADDR='https://[테스트 도메인]:8200'
1. vault 서버 초기화
5개의 unseal key 발행되고, 그 중 3개를 입력해야 VAULT 사용 가능
# unseal key 발행
$ vault operator init
Unseal Key 1: ayPqZuzG7bBN3uRp/GYfUBIVg9MGrbIotnHrjYXNWQIm
Unseal Key 2: iRntqlhFUfybvnjzLCHHxq/GQfDDtuPupxJyFqpLqpNc
Unseal Key 3: ibTmbjiieSQPLB2ZnUNY2hrplvrr6ab1m8FnyY8moMMu
Unseal Key 4: RdU4jDtYmAlF9bDFg8J3/l67Nph72ZFuyXlGWTzsP/ja
Unseal Key 5: yO+uE3m3eCy/IgzU6qQFz4QC2mIlG6ZcVXC8ZH65u0Rr
Initial Root Token: s.asQ2M2u8kefJAH7pTRK9VZuY
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 keys 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.
2. unseal키 수동 설정하여 vault 서버 초기화 (예시)
unseal 키 1개 설정하였으며, 1개의 unseal키를 입력하면 vault 서버 사용 가능
# unseal key 발행
$ vault operator init -key-shares=1 -key-threshold=1
Unseal Key 1: 8vTbeSYOS0yWMve+NFy2eisJQkbqaPOb6ocp3zkHS1c= # Unseal key 1개 발행 확인 -> 보관 필요
Initial Root Token: s.s15mhZCNj4oOwcYji8TuIx5h # Root Token 도 1개 발행 -> 보관 필요
Vault initialized with 1 key shares and a key threshold of 1. Please securely
distribute the key shares printed above. When the Vault is re-sealed,
restarted, or stopped, you must supply at least 1 of these keys to unseal it
before it can start servicing requests.
Vault does not store the generated master key. Without at least 1 keys 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.
3. vault 초기화 후 vault 서버 상태 확인
$ vault status
Key Value
--- -----
Seal Type shamir
Initialized true
Sealed true
Total Shares 5 # unseal 발행 개수
Threshold 3 # unseal 인증 개수
Unseal Progress 0/3
Unseal Nonce n/a
Version 1.9.3
Storage Type file
HA Enabled false
Root Token인 VAULT_TOKEN을 환경 변수 지정
VAULT_TOKEN은 Vault를 초기화(init)할 때 root token이라고 획득 → s.asQ2M2u8kefJAH7pTRK9VZuY
Vault 서버의 루트 권한이 있는 토큰
서버의 모든 작업을 가능
sealed 상태로 변경 가능
unseal 상태로 변경은 불가능
vault 토큰은 VAULT_TOKEN 환경변수에 저장하면 vault 클라이언트에서 사용 가능
# vault token을 환경 변수에 지정
$ export VAULT_TOKEN=s.asQ2M2u8kefJAH7pTRK9VZuY
$ echo -e "export VAULT_TOKEN=s.asQ2M2u8kefJAH7pTRK9VZuY" >> /root/.bashrc
# VAULT에서 지정한 환경변수 확인
$ env | grep -i vault
VAULT_ADDR=https://[테스트 도메인]:8200
VAULT_TOKEN=s.asQ2M2u8kefJAH7pTRK9VZuY
Vault Server를 unseal
vault init을 할 때 받은 unseal key를 입력 → 초기화할 때 발행받은 5개 중에 3개만 입력하면 됨
첫번째 : iRntqlhFUfybvnjzLCHHxq/GQfDDtuPupxJyFqpLqpNc
두번째 : ibTmbjiieSQPLB2ZnUNY2hrplvrr6ab1m8FnyY8moMMu
기본적으로 Vault server를 초기화하면 Sealed 상태가 됨 → 즉, 잠겨있어서 Vault 서버에서 정보를 읽는 등 작업 불가능
Vault server를 init에 알려준 Unseal Key를 이용하면 Unsealed 상태로 변경 → Vault 서버의 정보 읽기, 쓰기 등 여러 작업 가능
1. vault Server unseal (봉인 해제)
3번의 vault operator unseal을 통해 봉인 해제
unseal 명령어를 성공할 때마다 Unseal Progress의 수치가 올라가서 3/3이 되었을 때 unseal이 됨
unseal이 완료 → Sealed : false
# 첫번째 Vault unseal
$ vault operator unseal
Unseal Key (will be hidden):
Key Value
--- -----
Seal Type shamir
Initialized true
Sealed true
Total Shares 5
Threshold 3
Unseal Progress 1/3
Unseal Nonce ccbf047b-5956-fdd8-29f9-bad6969cdd45
Version 1.9.3
Storage Type file
HA Enabled false
# 두번째 Vault unseal
$ vault operator unseal
Unseal Key (will be hidden):
Key Value
--- -----
Seal Type shamir
Initialized true
Sealed true
Total Shares 5
Threshold 3
Unseal Progress 2/3
Unseal Nonce ccbf047b-5956-fdd8-29f9-bad6969cdd45
Version 1.9.3
Storage Type file
HA Enabled false
# 세번째 Vault unseal
$ vault operator unseal
Unseal Key (will be hidden):
Key Value
--- -----
Seal Type shamir
Initialized true
Sealed false
Total Shares 5
Threshold 3
Version 1.9.3
Storage Type file
Cluster Name vault-cluster-0b89b3d2
Cluster ID dbea1671-61fa-c4c8-387e-e32390ace762
HA Enabled false
※ unseal 참고 사항
연속적으로 unseal을 3번 실행하여 Vault 서버를 열 수 있다.
하지만, 한사람이 unseal key를 다 가지는 것은 위험 → 키를 5명이 나누어 갖고 3명이 unseal을 하면 Vault 서버를 엶
Vault에 중요한 정보가 있음으로 서버를 재시작하거나 보안 문제 발생으로 sealed 상태로 바꾸었을 때, 다시 서버를 열려면 unseal 단계를 거쳐야 함
unseal 과정은 서버가 기억하고 있으므로 한자리에 모일 필요 없이 각자의 자리에서 unseal을 하기만 하면 됨
unseal은 시간 제한도 없기에 충분히 시간을 두고 진행 가능
스토리지 백엔드에도 암호화된 정보가 저장되어 있고, 복호화하려면 unseal 단계가 필수적 → unseal 키 3개가 없으면 Vault 서버도 복호화키도 만들어 낼 수 없음
DB가 통째로 털려도 Vault 서버가 통째로 털려도 unseal 키 3개가 없다면 공격자는 정보를 볼 수 없게 되어 안전함
2. unseal할 때 출력한 vault server 상태와 vault status 명령어로 출력되는 상태가 같은 지 확인
vault server가 unseal됨 → token을 입력해야 서버 내부 접근 가능
$ vault status
Key Value
--- -----
Seal Type shamir
Initialized true
Sealed false
Total Shares 5
Threshold 3
Version 1.9.3
Storage Type file
Cluster Name vault-cluster-0b89b3d2
Cluster ID dbea1671-61fa-c4c8-387e-e32390ace762
HA Enabled false
Vault Server를 Sealing
vault를 서버에 보안 문제가 있거나, 안전하게 관리하기 위해서 unsealing되어있는 것을 sealing으로 변경
$ vault operator seal
Success! Vault is sealed.
다시 sealing된 vault 서버의 상태 확인
$ vault status
Key Value
--- -----
Seal Type shamir
Initialized true
Sealed true
Total Shares 5
Threshold 3
Unseal Progress 0/3
Unseal Nonce n/a
Version 1.9.3
Storage Type file
HA Enabled false
$ mkdir /vault
$ cp -r /opt/vault/* /vault/
$ ls /vault/
data tls
$ mkdir /vault/config/
# vault-config를 설정할 hcl 생성
$ vi /vault/config/vault-config.hcl
# ui 사용 허가
ui = true
# Vault 데이터가 저장되는 스토리지 백엔드를 구성
storage "file" {
path = "/vault/data"
}
# API 서버의 IP와 PORT 선언
api_addr = "https://[Vault 서버 도메인]:8200"
# HTTP listener -> HTTP 사용 X
#listener "tcp" {
# address = "0.0.0.0:8200"
# tls_disable = 1
#}
# HTTPS listener -> HTTPS 사용
listener "tcp" {
address = "0.0.0.0:8200"
tls_cert_file = "/vault/tls/tls.crt"
tls_key_file = "/vault/tls/tls.key"
}
# 기본 VAULT_ADDR은 "https://127.0.0.1:8200"으로 되어있기에 vault 서버의 API를 사용하는 주소를 설정
# VAULT_ADDR='https://[Vault 서버 도메인]:8200'
$ export VAULT_ADDR='https://[Vault 서버 도메인]:8200'
$ echo -e "export VAULT_ADDR='https://[Vault 서버 도메인]:8200'" >> /root/.bashrc
$ echo $VAULT_ADDR
https://[Vault 서버 도메인]:8200
2. vault.service를 재시작하여 설정 적용
$ systemctl daemon-reload
$ systemctl start vault.service
$ systemctl status vault
● vault.service - Vault secret store
Loaded: loaded (/etc/systemd/system/vault.service; disabled; vendor preset: disabled)
Active: active (running) since Sun 2022-02-27 16:42:28 KST; 24s ago
Main PID: 14832 (vault)
CGroup: /system.slice/vault.service
└─14832 /usr/bin/vault server -config=/vault/config/vault-config.hcl
3. config 설정을 적용한 vault 서버가 정상적으로 실행되는 지 확인 → API
# jq 패키지 설치
$ yum install -y jq
# 외부에서 https://[Vault 서버 도메인]:8200 도메인 요청하여 vault server에게 API 성공 확인
$ curl https://[Vault 서버 도메인]:8200/v1/sys/seal-status | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 168 100 168 0 0 29 0 0:00:05 0:00:05 --:--:-- 40
{
"type": "shamir",
"initialized": false,
"sealed": true,
"t": 0,
"n": 0,
"progress": 0,
"nonce": "",
"version": "1.9.3",
"migration": false,
"recovery_seal": false,
"storage_type": "file"
}
4. config 설정을 적용한 vault 서버에 status 확인
# vault 서버에서 vault status 명령어 확인
$ vault status
Key Value
--- -----
Seal Type shamir
Initialized false
Sealed true
Total Shares 0
Threshold 0
Unseal Progress 0/0
Unseal Nonce n/a
Version 1.9.3
Storage Type file
HA Enabled false
Vault UI 웹페이지 Open
https://[Vault 서버 도메인]:8200으로 접속
아직 Unseal을 하지 않았기 때문에 접근은 불가능 → unseal을 하면 웹 페이지 안에 접근 가능
$ yum install -y yum-utils
$ yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
$ yum -y install vault
# 설치한 vault 패키지 버전 확인
$ vault -v
Vault v1.8.0 (82a99f14eb6133f99a975e653d4dac21c17505c7)
Vault server를 DEV 모드로 실행
1. 환경변수 등록
vault CLI 를 사용하기 위해 환경변수 등록이 필요
# 수동으로 환경 변수 등록
$ export VAULT_ADDR='http://127.0.0.1:8200'
# 영구적으로 환경 변수 등록
$ echo "export VAULT_ADDR='http://127.0.0.1:8200'" >> /root/.bashrc
$ source /root/.bashrc
# 설정 확인
$ echo $VAULT_ADDR
http://127.0.0.1:8200
2. 테스트를 위해 -dev 모드로 백그라운드에서 서버를 실행
dev모드는 미리 준비된 설정으로 서버를 구동
dev 모드는 모든 데이터는 in-memory 저장, 암호화
localhost로 listen되며 TLS가 없음
자동 봉인 해제 → 봉인 해제된 키와 엑세스 토큰을 보여줌
프로덕션 모드에서는 -dev 옵션 사용을 권장 X
$ vault server -dev &
==> Vault server configuration:
Api Address: http://127.0.0.1:8200
Cgo: disabled
Cluster Address: https://127.0.0.1:8201
Go Version: go1.16.5
Listener 1: tcp (addr: "127.0.0.1:8200", cluster address: "127.0.0.1:8201", max_request_duration: "1m30s", max_request_size: "33554432", tls: "disabled")
Log Level: info
Mlock: supported: true, enabled: false
Recovery Mode: false
Storage: inmem
Version: Vault v1.8.0
Version Sha: 82a99f14eb6133f99a975e653d4dac21c17505c7
==> Vault server started! Log data will stream in below:
2021-08-02T14:07:10.555Z [INFO] proxy environment: http_proxy="" https_proxy="" no_proxy=""
2021-08-02T14:07:10.556Z [WARN] no `api_addr` value specified in config or in VAULT_API_ADDR; falling back to detection if possible, but this value should be manually set
2021-08-02T14:07:10.557Z [INFO] core: security barrier not initialized
2021-08-02T14:07:10.557Z [INFO] core: security barrier initialized: stored=1 shares=1 threshold=1
2021-08-02T14:07:10.558Z [INFO] core: post-unseal setup starting
2021-08-02T14:07:10.572Z [INFO] core: loaded wrapping token key
2021-08-02T14:07:10.572Z [INFO] core: successfully setup plugin catalog: plugin-directory=""
2021-08-02T14:07:10.572Z [INFO] core: no mounts; adding default mount table
2021-08-02T14:07:10.573Z [INFO] core: successfully mounted backend: type=cubbyhole path=cubbyhole/
2021-08-02T14:07:10.574Z [INFO] core: successfully mounted backend: type=system path=sys/
2021-08-02T14:07:10.574Z [INFO] core: successfully mounted backend: type=identity path=identity/
2021-08-02T14:07:10.582Z [INFO] core: successfully enabled credential backend: type=token path=token/
2021-08-02T14:07:10.589Z [INFO] core: restoring leases
2021-08-02T14:07:10.603Z [INFO] rollback: starting rollback manager
2021-08-02T14:07:10.603Z [INFO] expiration: lease restore complete
2021-08-02T14:07:10.604Z [INFO] identity: entities restored
2021-08-02T14:07:10.604Z [INFO] identity: groups restored
2021-08-02T14:07:10.604Z [INFO] core: post-unseal setup complete
2021-08-02T14:07:10.604Z [INFO] core: root token generated
2021-08-02T14:07:10.604Z [INFO] core: pre-seal teardown starting
2021-08-02T14:07:10.604Z [INFO] rollback: stopping rollback manager
2021-08-02T14:07:10.604Z [INFO] core: pre-seal teardown complete
2021-08-02T14:07:10.604Z [INFO] core.cluster-listener.tcp: starting listener: listener_address=127.0.0.1:8201
2021-08-02T14:07:10.604Z [INFO] core.cluster-listener: serving cluster requests: cluster_listen_address=127.0.0.1:8201
2021-08-02T14:07:10.604Z [INFO] core: post-unseal setup starting
2021-08-02T14:07:10.605Z [INFO] core: loaded wrapping token key
2021-08-02T14:07:10.605Z [INFO] core: successfully setup plugin catalog: plugin-directory=""
2021-08-02T14:07:10.605Z [INFO] core: successfully mounted backend: type=system path=sys/
2021-08-02T14:07:10.605Z [INFO] core: successfully mounted backend: type=identity path=identity/
2021-08-02T14:07:10.605Z [INFO] core: successfully mounted backend: type=cubbyhole path=cubbyhole/
2021-08-02T14:07:10.606Z [INFO] core: successfully enabled credential backend: type=token path=token/
2021-08-02T14:07:10.606Z [INFO] core: restoring leases
2021-08-02T14:07:10.607Z [INFO] identity: entities restored
2021-08-02T14:07:10.607Z [INFO] identity: groups restored
2021-08-02T14:07:10.607Z [INFO] core: post-unseal setup complete
2021-08-02T14:07:10.607Z [INFO] core: vault is unsealed
2021-08-02T14:07:10.609Z [INFO] core: successful mount: namespace="" path=secret/ type=kv
2021-08-02T14:07:10.610Z [INFO] expiration: lease restore complete
2021-08-02T14:07:10.610Z [INFO] secrets.kv.kv_f71fab5a: collecting keys to upgrade
2021-08-02T14:07:10.610Z [INFO] secrets.kv.kv_f71fab5a: done collecting keys: num_keys=1
2021-08-02T14:07:10.610Z [INFO] secrets.kv.kv_f71fab5a: upgrading keys finished
2021-08-02T14:07:10.611Z [INFO] rollback: starting rollback manager
WARNING! dev mode is enabled! In this mode, Vault runs entirely in-memory
and starts unsealed with a single unseal key. The root token is already
authenticated to the CLI, so you can immediately begin using Vault.
You may need to set the following environment variable:
$ export VAULT_ADDR='http://127.0.0.1:8200'
The unseal key and root token are displayed below in case you want to
seal/unseal the Vault or re-authenticate.
Unseal Key: +1P8t1jNPI8mBPCV57v+emB4E3DttH3t1xkz+oXsQUs=
Root Token: s.BT8kE324DT9EJYQqG8noC8J1
Development mode should NOT be used in production installations!
3. 실행된 서버의 상태를 확인
$ vault status
Key Value
--- -----
Seal Type shamir
Initialized true
Sealed false
Total Shares 1
Threshold 1
Version 1.3.0
Cluster Name vault-cluster-a6999d5c
Cluster ID 291371dc-e6a5-42d3-fca7-b2373ff70194
HA Enabled false
vault 와 secret
vault의 핵심 기능중 하나는 비밀정보를 안전하게 읽고 쓰는것
vault에 기록된 비밀정보는 암호화하여 backend 저장소에 저장
값을 저장소에 전달하기 전에 암호화를 하며, backend 저장소에 저장된 암호화값은 vault 없이는 해독 불가능
write a secret (비밀정보 작성)
key 값의 접두사가 secret/ 로 저장됨
secret/ 는 어떤 secrets engine을 실행시킬지 결정하는 route 역할(경로 결정)
비밀정보를 기록할때는 shell history에 남기때문에 되도록이면 file 을 통해서 전달될수있도록 하는것이 좋음
kv → Vault의 키-값 저장소와 상호작용 (command)
put → KV 저장소의 데이터를 설정하거나 업데이트함
secret/hello → hello 이름을 가지는 secret engine 사용
foo=world → foo 키에 world 값이 있음
$ vault kv put secret/hello foo=world
Key Value
--- -----
created_time 2021-08-02T15:40:03.164784248Z
deletion_time n/a
destroyed false
version 1
read a secret (비밀정보 읽기)
1. secret과 함께 여러 가지 메타 데이터가 함께 반환
비밀정보를 획득
vault는 저장소로부터 값을 가져올때 복호화하여 가져옴
kv → Vault의 키-값 저장소와 상호작용 (command)
get → KV 저장소에서 데이터 검색
secret/hello → hello 이름을 가지는 secret engine 사용
$ vault kv get secret/hello
====== Metadata ======
Key Value
--- -----
created_time 2019-11-26T02:39:20.8458832Z
deletion_time n/a
destroyed false
version 1
=== Data ===
Key Value
--- -----
foo world
2. hello 키에 해당하는 값 추출
kv → Vault의 키-값 저장소와 상호작용 (command)
get → KV 저장소에서 데이터 검색
field=key → 입력한 key의 value를 출력, -field 옵션을 사용하면 다른 형식 지정 지시문보다 우선
$ vault kv get -field=foo secret/hello
world
3. JSON output → 결과데이터의 포맷을 json형식으로 출력
kv → Vault의 키-값 저장소와 상호작용 (command)
get → KV 저장소에서 데이터 검색
format=형식 → "table", "json", "yaml", "pretty" 중에 입력한 형식으로 출력 → 기본값은 table로 출력