본문 바로가기

리눅스

HashiCorp Vault를 이용한 SSH 인증서 기반 인증 설정

반응형

HashiCorp Vault를 이용한 SSH 인증서 기반 인증 설정(Certificate Authority)

테스트 환경

호스트 이름 IP 주소 역할 비고
node1 192.168.0.101 Vault 서버  
node2 192.168.0.102 SSH 서버  
node3 192.168.0.103 SSH 클라이언트  

아키텍처

다이어그램

Mermaid(https://mermaid.live)

더보기

---

sequenceDiagram
    participant C as Node3<br/>클라이언트
    participant V as Node1<br/>Vault 서버
    participant S as Node2<br/>SSH 서버

    Note over C,S: Phase 1: 초기 설정
    V->>S: CA 공개키 배포
    V->>S: 호스트 인증서 발급
    
    Note over C,S: Phase 2: 사용자 인증
    C->>V: SSH 공개키 전송
    V->>C: 서명된 인증서 발급
    
    Note over C,S: Phase 3: SSH 접속
    C->>S: SSH 연결 요청 (인증서 포함)
    S->>S: 인증서 유효성 검증
    S->>S: Vault CA 서명 확인
    S->>S: Principal 매칭 확인
    S->>C: 접속 허용

---

node1 : 역할 생성

node2

  • vtest 계정 생성
  • SSH 설정
  • CA 공개키 설정
  • Principal 파일 생성

node3

  • SSH 키 생성
  • 인증서 발급
  • SSH config 설정

1. Vault 서버 설정(node1)

Vault에 SSH 엔진 활성화

환경 변수 설정

export VAULT_ADDR="http://127.0.0.1:8200"
export VAULT_TOKEN="hvs.your-root-token"

SSH 엔진 활성화

vault secrets enable ssh

SSH CA 초기화

CA 키 생성

vault write ssh/config/ca generate_signing_key=true

vtest 사용자용 역할 생성

vtest 사용자를 위한 역할 파일 생성

cat > vtest_role.json << 'EOF'
{
  "key_type": "ca",
  "allow_user_certificates": true,
  "allowed_users": "vtest",
  "ttl": "1h",
  "max_ttl": "24h",
  "default_user": "vtest"
}
EOF

역할 생성

vault write ssh/roles/vtest @vtest_role.json

확인

vault read ssh/roles/vtest

정책 생성

vtest를 위한 정책 파일 생성

cat > vtest_policy.hcl << 'EOF'
path "ssh/sign/vtest" {
  capabilities = ["create", "update"]
}
EOF

정책 생성

vault policy write vtest-sign vtest_policy.hcl

vtest용 토큰 생성

vtest 사용자가 사용할 토큰 생성

vault token create -policy="vtest-sign" -ttl=24h

2. SSH 서버 설정(node2)

SSH 서버에 vtest 계정 생성

node2에서 실행

sudo useradd -m -d /home/vtest -s /bin/bash vtest

SSH 설정 파일 수정

백업 생성

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup.$(date +%Y%m%d)

설정 파일 수정

sudo tee /etc/ssh/sshd_config > /dev/null << 'EOF'
Port 22
Protocol 2

# 보안 설정
PermitRootLogin no
MaxAuthTries 3

# 인증 설정
PubkeyAuthentication yes
PasswordAuthentication no
ChallengeResponseAuthentication no

# 인증서 설정
TrustedUserCAKeys /etc/ssh/trusted-user-ca.pem
AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u

# 기타
UsePAM yes
X11Forwarding yes
PrintMotd no
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server
EOF

필요한 디렉토리 생성

sudo mkdir -p /etc/ssh/auth_principals

Vault CA 공개키 가져오기

Vault CLI 설치(필요시)

더보기

---

VAULT_VERSION=$(curl -fsSL https://api.github.com/repos/hashicorp/vault/releases/latest | jq -r .tag_name | sed 's/^v//')
curl -fsSL https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_amd64.zip \
  -o vault_${VAULT_VERSION}_linux_amd64.zip
unzip vault_${VAULT_VERSION}_linux_amd64.zip
sudo mv vault /usr/local/bin/
sudo rm -f LICENSE.txt vault_${VAULT_VERSION}_linux_amd64.zip

---

환경 변수 설정

export VAULT_ADDR="http://127.0.0.1:8200"
export VAULT_TOKEN="hvs.your-root-token"

CA 공개키 다운로드

vault read -field=public_key ssh/config/ca | sudo tee /etc/ssh/trusted-user-ca.pem

권한 설정

sudo chmod 644 /etc/ssh/trusted-user-ca.pem

vtest용 Principal 파일 생성

echo "vtest" | sudo tee /etc/ssh/auth_principals/vtest

SSH 서비스 재시작

설정 검증

sudo sshd -t

재시작

sudo systemctl restart ssh

상태 확인

sudo systemctl status ssh
728x90

클라이언트에서 SSH 키 생성(node3)

Vault CLI 설치 및 설정

Vault 설치

더보기

---

VAULT_VERSION=$(curl -fsSL https://api.github.com/repos/hashicorp/vault/releases/latest | jq -r .tag_name | sed 's/^v//')
curl -fsSL https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_amd64.zip \
  -o vault_${VAULT_VERSION}_linux_amd64.zip
unzip vault_${VAULT_VERSION}_linux_amd64.zip
sudo mv vault /usr/local/bin/
sudo rm -f LICENSE.txt vault_${VAULT_VERSION}_linux_amd64.zip

---

환경 변수 설정

export VAULT_ADDR="http://127.0.0.1:8200"
export VAULT_TOKEN="hvs.your-root-token"

테스트

vault status

SSH 키 생성

디렉토리 생성

mkdir -p ~/.ssh
chmod 700 ~/.ssh

SSH 키 쌍 생성

ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_vtest -N ""

확인

ls -la ~/.ssh/id_vtest*

인증서 발급 스크립트 생성

cat > get_cert.sh << 'EOF'
#!/bin/bash
echo "=== SSH 인증서 발급 시작 ==="

# Vault 설정
export VAULT_ADDR="http://61.100.4.237:8200"
export VAULT_TOKEN="위에서_생성한_vtest용_token"

# 인증서 발급 요청
vault write -format=json ssh/sign/vtest \
    public_key=@$HOME/.ssh/id_vtest.pub \
    username=vtest \
    ttl=1h > /tmp/cert_response.json

# 응답 확인
if [ $? -eq 0 ]; then
    # 인증서 추출
    jq -r .data.signed_key /tmp/cert_response.json > $HOME/.ssh/id_vtest-cert.pub
    
    # 권한 설정
    chmod 644 $HOME/.ssh/id_vtest-cert.pub
    
    echo "✅ 인증서 발급 성공!"
    echo "인증서 파일: $HOME/.ssh/id_vtest-cert.pub"
    
    # 인증서 정보 확인
    echo -e "\n=== 인증서 정보 ==="
    ssh-keygen -L -f $HOME/.ssh/id_vtest-cert.pub | grep -E "(Valid:|Principals:|Key ID)"
else
    echo "❌ 인증서 발급 실패"
    exit 1
fi
EOF
  • VAULT_TOKEN 수정
chmod +x get_cert.sh

인증서 발급 실행

인증서 발급

./get_cert.sh

4. SSH 접속 테스트

SSH config 파일 생성

cat > ~/.ssh/config << 'EOF'
Host ssh-server
    HostName 192.168.0.102
    User vtest
    IdentityFile ~/.ssh/id_vtest
    CertificateFile ~/.ssh/id_vtest-cert.pub
    StrictHostKeyChecking no
    
Host 192.168.0.102
    User vtest
    IdentityFile ~/.ssh/id_vtest
    CertificateFile ~/.ssh/id_vtest-cert.pub
    StrictHostKeyChecking no
EOF
chmod 600 ~/.ssh/config

테스트

whoami

ssh ssh-server whoami

hostname

ssh ssh-server hostname

date

ssh ssh-server date

상세 정보 확인

ssh -v ssh-server whoami
ssh -vv ssh-server whoami

직접 명시적으로 테스트

ssh -o StrictHostKeyChecking=no \
    -i ~/.ssh/id_vtest \
    -o CertificateFile=~/.ssh/id_vtest-cert.pub \
    vtest@192.168.0.102 "echo 테스트 성공"

6. 자동 갱신 설정(선택사항)

자동 갱신 스크립트

cat > renew_cert.sh << 'EOF'
#!/bin/bash
CERT_FILE="$HOME/.ssh/id_vtest-cert.pub"

# 인증서가 있는지 확인
if [ ! -f "$CERT_FILE" ]; then
    echo "인증서 파일이 없습니다. 새로 발급합니다."
    ./get_cert.sh
    exit 0
fi

# 만료 시간 확인
EXPIRES=$(ssh-keygen -L -f "$CERT_FILE" 2>/dev/null | grep "Valid:" | awk '{print $NF}')
if [ -z "$EXPIRES" ]; then
    echo "인증서 정보를 읽을 수 없습니다. 새로 발급합니다."
    ./get_cert.sh
    exit 0
fi

# 만료 시간을 초 단위로 변환
EXPIRES_EPOCH=$(date -d "$EXPIRES" +%s 2>/dev/null)
NOW_EPOCH=$(date +%s)

if [ -z "$EXPIRES_EPOCH" ] || [ $((EXPIRES_EPOCH - NOW_EPOCH)) -lt 300 ]; then
    echo "인증서가 곧 만료됩니다. 갱신합니다."
    ./get_cert.sh
else
    echo "인증서 유효 (만료: $EXPIRES)"
fi
EOF
chmod +x renew_cert.sh

매시간 자동 갱신

crontab에 등록

(crontab -l 2>/dev/null; echo "0 * * * * $HOME/renew_cert.sh >> $HOME/cert_renew.log 2>&1") | crontab -

테스트 실행

./renew_cert.sh

 

참고URL

- 변군이글루 블로그 : 우분투 24.04에서 Vault CLI를 설치하는 방법

 

728x90
반응형