Azure 가상 머신에 Public IP를 열지 않고도, 중앙에서 관리되는 SSH 키로만 안전하게 접속해야 하는 요구가 증가하고 있다. 이 글은 Azure Bastion과 Azure Key Vault Secret을 결합하여, 브라우저 기반 포털에서 SSH 프라이빗 키 파일 없이 접속하는 방법을 정리한다.
1. 문제 정의
일반적인 SSH 접속 구조에서는 다음과 같은 문제가 발생한다.
- 각 운영자 PC에 SSH 프라이빗 키 파일이 분산 저장된다.
- 운영자 퇴사·PC 분실 시 키 유출 리스크가 높다.
- 보안 정책상 VM에 Public IP 할당이 금지된 환경에서는 직접 SSH 접속이 불가능하다.
- Bastion을 사용하는 경우에도, 로컬 파일 기반 프라이빗 키를 계속 관리해야 하는 번거로움이 존재한다.
목표
- VM에 Public IP 없이도 SSH 접속 가능
- 프라이빗 키는 Key Vault Secret로만 관리
- Bastion 접속 시 “SSH Private Key from Azure Key Vault” 옵션만 사용
- 운영자 PC에는 프라이빗 키 파일을 남기지 않음
Azure 공식 문서에서도 Bastion 보안 강화를 위해 SSH 키를 Key Vault Secret으로 저장하고, 해당 Secret을 통해 접속하는 방식을 권장한다.
2. 아키텍처 및 흐름 개요
2.1 논리 아키텍처
텍스트 기준 구성도:
- 사용자는 Azure Portal에 로그인
- VM → Connect → Bastion 선택
- 인증 방식으로 SSH Private Key from Azure Key Vault 선택
- Bastion은 Key Vault에서 Secret(프라이빗 키)을 읽어 SSH 세션을 생성
- 세션은 Bastion ↔ 대상 VM(Private IP) 사이에서만 이루어지며, VM은 외부에 노출되지 않음
구성 요소:
- Azure Bastion
- 대상 VM이 포함된 VNet(또는 피어링된 허브 VNet)에 배포
- SSH/RDP 진입점 역할
- Azure Key Vault
- SSH 프라이빗 키를 Secret으로 저장
- Get/List 권한이 있는 사용자만 Bastion에서 Secret을 선택 가능
- Linux VM
- Public IP 없음
- SSH Public Key 기반 인증만 허용 (Password 비활성화 권장)
- 운영자 계정
- Azure RBAC 및 Key Vault 데이터 평면 권한(Secret Get/List)을 가진 사용자 또는 그룹
3. 사전 준비사항
3.1 필수 리소스
- Azure Subscription
- Bastion을 배포할 VNet 및 AzureBastionSubnet
- Private Subnet에 위치한 Linux VM (SSH Public Key 구성 완료)
- SSH 키 페어 (이미 존재하거나, 새로 생성)
- Azure Key Vault (RBAC 또는 Access Policy 기반 권한 모델)
3.2 권한 요구사항
- Azure Bastion 관리 권한
- Bastion 리소스에 대한 Contributor 이상(또는 Bastion 전용 사용자 정의 역할)
- Key Vault 데이터 평면 권한
- SSH 프라이빗 키 Secret을 조회하려는 사용자/그룹에 대해 Secret에 대한 Get, List 권한 필요
- RBAC 사용 시: 예) Key Vault Secrets Officer, Key Vault Administrator 등
3.3 기술 제약
- Bastion SKU
- Basic/Standard 이상에서 “SSH Private Key from Azure Key Vault” 옵션 제공
- Standard 이상에서만 Connection Settings(포트, 프로토콜) 세부 설정 가능
- SSH 프라이빗 키 Secret 저장 시:
- 멀티 라인 Secret 특성상, 포털에서 붙여넣기하면 줄바꿈이 손상되어 인증 실패 발생 가능
- CLI 또는 PowerShell을 사용해 파일 단위로 저장해야 함
4. 개념 정리: Bastion + Key Vault 기반 SSH 인증
4.1 Bastion 연결 옵션
Linux VM Bastion 연결 시 Azure Portal에서는 다음과 같은 인증 옵션을 제공한다.
- Password
- SSH Private Key
- SSH Private Key from Local File
- SSH Private Key from Azure Key Vault
이 중 **“SSH Private Key from Azure Key Vault”**를 선택하면, Bastion은 사용자의 브라우저나 로컬 파일이 아닌 Key Vault Secret을 통해 SSH 키를 읽어 세션을 생성한다.
4.2 Key Vault에 SSH 키를 Secret으로 저장하는 이유
- SSH 키를 Key 타입이 아닌 Secret 타입으로 저장해야 프라이빗 키 원문을 다시 조회할 수 있다.
- Secret으로 저장하면:
- Key Vault RBAC/Access Policy로 접근 제어
- Secret 버전 관리 및 만료일 설정 가능
- 동일 Secret을 여러 VM 접속에 재사용 가능 (조직 정책에 따라 분리 또는 공유)
5. SSH 키 생성 및 Key Vault Secret 저장 (CLI 기반)
아래 예시는 Linux/MacOS Shell 기준이며, Windows PowerShell도 유사한 흐름으로 구성할 수 있다.
5.1 SSH 키 생성
이미 키 페어가 있다면 이 단계는 생략 가능하다.
# 새 SSH 키 생성 (예: ed25519)
ssh-keygen -t ed25519 -C "bastion-key" -f ~/.ssh/bastion-ed25519
# 프라이빗 키 : ~/.ssh/bastion-ed25519
# 퍼블릭 키 : ~/.ssh/bastion-ed25519.pub
퍼블릭 키(.pub)는 VM 생성 시 또는 “Reset SSH public key” 기능으로 VM에 등록한다.
5.2 Key Vault 생성
# 변수 정의
RG_NAME="rg-bastion-kv-demo"
LOCATION="koreacentral"
KV_NAME="kv-bastion-ssh-demo" # 전역 고유 이름 필요
# 리소스 그룹 생성
az group create \\
--name "$RG_NAME" \\
--location "$LOCATION"
# Key Vault 생성 (RBAC 권한 모델 예시)
az keyvault create \\
--name "$KV_NAME" \\
--resource-group "$RG_NAME" \\
--location "$LOCATION" \\
--enable-rbac-authorization true
5.3 SSH 프라이빗 키를 Secret으로 저장
멀티 라인 Secret은 CLI에서 파일 단위로 등록해야 한다.
# SSH 프라이빗 키를 Secret으로 저장
az keyvault secret set \\
--vault-name "$KV_NAME" \\
--name "vm-bastion-sshkey" \\
--file ~/.ssh/bastion-ed25519
저장 후, 포털에서 Key Vault → Secrets → vm-bastion-sshkey를 확인하면 Secret 값이 존재하는 것을 볼 수 있다.
6. Bastion 구성 및 VM SSH 연결 (Portal 기반 튜토리얼)
6.1 Azure Bastion 배포
- Azure Portal에서 Bastion 리소스 생성
- 대상 VM이 존재하는 VNet 선택
- AzureBastionSubnet(권장 /26 이상) 지정
- Public IP를 할당하고 Bastion 배포 완료
(Bastion 기본 배포 절차는 공식 시작 문서에 정리되어 있으며, 이 글에서는 생략한다.)
6.2 Linux VM 준비
- Linux VM 생성 시 Authentication type을 SSH public key로 설정
- 기존 VM인 경우:
- VM → Reset password → Reset SSH public key 메뉴에서 퍼블릭 키 등록
6.3 Bastion + Key Vault Secret 기반 SSH 접속 (포털 단계)
공식 문서 “Azure Bastion을 사용하여 Linux VM에 대해 SSH 연결 만들기”의 흐름을 기반으로 한다.
- 포털에서 대상 Linux VM 선택
- 상단 메뉴에서 Connect → Bastion 선택
- Bastion 연결 블레이드에서 다음 값 설정
- Protocol: SSH
- Authentication type: SSH Private Key from Azure Key Vault
- Username: VM 생성 시 지정한 계정 (예: azureuser)
- Subscription: Key Vault가 있는 구독
- Azure Key Vault: kv-bastion-ssh-demo
- Azure Key Vault Secret: vm-bastion-sshkey
- 필요 시 Connection Settings에서 포트를 22가 아닌 커스텀 포트로 변경 (Standard SKU 이상)
- Connect 클릭
- 브라우저 팝업이 허용되면 새 탭에서 SSH 터미널 세션이 열린다.
이 시점에서, 운영자 PC에는 프라이빗 키 파일을 직접 사용하지 않고도 VM에 접속할 수 있다. Bastion은 Key Vault에서 Secret을 읽어 SSH 세션을 자체적으로 구성한다.
7. 추가 시나리오: 네이티브 클라이언트 + Key Vault 연계
Azure Bastion은 네이티브 클라이언트 연결 기능을 통해 az network bastion ssh 명령으로 로컬 터미널에서 SSH 접속을 제공한다.
현재 네이티브 클라이언트는 기본적으로 로컬 SSH 키 파일 또는 Entra ID를 사용한다. Key Vault Secret과 직접 연동하는 옵션은 제공하지 않으므로, 다음과 같은 패턴으로 확장할 수 있다.
- az keyvault secret show로 Key Vault Secret 값을 읽어 임시 파일에 저장
- az network bastion ssh에서 -ssh-key 인자로 임시 파일 사용
- 세션 종료 후 임시 파일 삭제
예시 스크립트(컨셉용):
KV_NAME="kv-bastion-ssh-demo"
SECRET_NAME="vm-bastion-sshkey"
TEMP_KEY="/tmp/bastion-kv-key.pem"
# 1) Key Vault Secret에서 프라이빗 키 값 조회
az keyvault secret show \\
--vault-name "$KV_NAME" \\
--name "$SECRET_NAME" \\
--query value -o tsv > "$TEMP_KEY"
chmod 600 "$TEMP_KEY"
# 2) Bastion 네이티브 클라이언트로 SSH 접속
az network bastion ssh \\
--name bastion-prod \\
--resource-group rg-bastion-kv-demo \\
--target-resource-id "/subscriptions/<subId>/resourceGroups/<rg>/providers/Microsoft.Compute/virtualMachines/<vm-name>" \\
--auth-type ssh-key \\
--username azureuser \\
--ssh-key "$TEMP_KEY"
# 3) 임시 파일 삭제
shred -u "$TEMP_KEY"
이 방식은 제품 기능이 아닌 운영 스크립트 패턴이므로, 보안 정책에 따라 추가 검증 후 사용하는 것이 바람직하다.
8. 자주 발생하는 오류 및 해결 방법
8.1 포털에서 Secret 저장 후 로그인 실패
증상
- Bastion 연결 시 Permission denied (publickey) 또는 인증 실패
- Key Vault에 Secret은 존재하나, 동일 키로 로컬에서 접속하면 정상 동작
원인
- 프라이빗 키가 멀티 라인 텍스트인데, 포털에서 Secret 값으로 붙여넣는 과정에서 줄바꿈/공백이 손상됨
- 공식 문서에서도 Key Vault 포털 UI를 통한 SSH 키 저장은 포맷 문제로 인해 Bastion 로그인 실패를 유발할 수 있다고 명시한다.
해결
- 원본 프라이빗 키 파일이 존재하는 경우:
- CLI 또는 PowerShell로 Secret을 다시 저장
az keyvault secret set \\ --vault-name "$KV_NAME" \\ --name "vm-bastion-sshkey" \\ --file ~/.ssh/bastion-ed25519 - 프라이빗 키 파일이 더 이상 없는 경우:
- 새 SSH 키 페어를 생성하고, VM에 새로운 Public Key를 등록한 뒤 Key Vault에 새 Secret 저장
- 공식 문서의 “Update SSH key” 절차를 따른다.
8.2 Key Vault 권한 부족으로 Secret 리스트 미표시
증상
- Bastion 연결 화면에서 Azure Key Vault Secret 드롭다운에 아무 값도 표시되지 않거나, 권한 오류가 발생
원인
- 사용자에게 Key Vault에 대한 Get, List 비밀 권한이 부여되지 않음
해결
- RBAC 사용 시:
- 사용자 또는 그룹에 Key Vault Secrets Officer 또는 Key Vault Administrator 역할 할당
- Access Policy 사용 시:
- Key Vault → Access Policies → Add Access Policy → Secret permissions에서 Get, List 선택 후 대상 Principal 지정
8.3 Bastion SKU 관련 제약
증상
- 포트를 변경할 수 없거나(항상 22), 일부 Connection Settings 비활성화
원인
- Bastion가 Basic SKU로 배포된 경우
- 공식 문서 기준, Connection Settings(커스텀 포트 등)는 Standard SKU 이상에서만 제공되며, Basic SKU는 SSH/22 기본값으로 고정된다.
해결
- Bastion SKU를 Standard로 재배포 또는 새로 배포
- 고정 포트 22를 그대로 사용하는 환경에서는 Basic도 사용 가능하나, 장기적으로는 Standard 이상을 권장
8.4 SSH 키와 VM Public Key 불일치
증상
- Key Vault Secret에서 가져온 프라이빗 키로 Bastion 접속 시 Permission denied (publickey) 발생
- Key Vault Secret 자체는 정상
원인
- VM에 등록된 SSH Public Key가 Key Vault에 저장된 프라이빗 키와 페어가 아님
- VM 재배포·키 재설정 과정에서 키가 교체되었으나 Key Vault Secret을 갱신하지 않은 경우
해결
- VM의 Reset SSH public key 기능을 사용하여 Key Vault Secret과 페어인 Public Key로 재등록
- 또는 Key Vault Secret을 현재 VM에 등록된 Public Key와 일치하는 프라이빗 키로 교체
9. 보안 및 운영 관점 Best Practice
9.1 SSH 키 관리
- SSH 프라이빗 키는 반드시 Key Vault Secret으로만 관리하고, 로컬 저장은 최소화
- Secret에 만료일(Expiration), 태그(Owner, Purpose, Environment) 설정
- 프라이빗 키는 Secret, 퍼블릭 키는 Git/IaC 템플릿에 포함하는 패턴을 사용
9.2 권한 설계
- Bastion 리소스 관리 권한과 SSH 접속 권한을 분리
- 예: Bastion 관리자는 Contributor, 운영자는 본인 VM + Key Vault Secret에 대해서만 Reader + Secret Get/List
- Microsoft Entra ID PIM(Privileged Identity Management)을 활용하여 SSH 접속 관련 권한을 Just-In-Time으로 부여
9.3 네트워크 및 Bastion 보안
- Bastion은 전용 AzureBastionSubnet(/26 이상)에 배치하고, NSG로 최소 포트(443, 22/3389, 특정 Azure 서비스 태그)만 허용
- VM에는 Public IP 미할당, NSG로 Bastion Subnet에서 오는 트래픽만 허용
- 필요 시 Premium SKU의 Private-only Bastion까지 고려하여 인터넷에서의 노출을 제거
9.4 자동화 및 키 로테이션
- Terraform, Bicep, Azure Automation, Functions 등을 활용하여:
- 주기적인 SSH 키 재생성
- Key Vault Secret 업데이트
- VM의 SSH Public Key 재등록 자동화
10. 정리
이 글에서 다룬 Azure Bastion + Key Vault Secret 기반 SSH 접속 패턴은 다음과 같은 목표를 동시에 달성한다.
- VM은 Public IP 없이 Private 서브넷에만 존재
- SSH 프라이빗 키는 로컬 파일이 아닌 Key Vault Secret에서만 관리
- Bastion의 “SSH Private Key from Azure Key Vault” 기능을 활용하여 운영자는 브라우저만으로 SSH 접속
- Key Vault RBAC/Access Policy, Bastion RBAC, 네트워크 보안을 결합한 엔터프라이즈 수준의 접근 제어
Azure Bastion 및 Key Vault 공식 문서에서 제시하는 보안 권장 사항과 Secret 관리 패턴을 그대로 따르는 구성이므로, 규제 산업·금융·공공 환경에서도 활용 가능한 구조이다. 실제 환경에서는 이 패턴을 IaC 코드(Terraform/Bicep) 및 운영 Runbook으로 표준화하여, 신규 프로젝트가 동일한 구조를 재사용할 수 있도록 하는 것이 효과적이다.
이 패턴을 실제 환경에 적용할 계획이라면, 나중에 다시 참고할 수 있도록 북마크하거나 팀·동료와 공유해 두는 것이 좋다.
11. 참고 자료 (Azure 공식 문서 및 기술 문서)
'DevOps > Cloud' 카테고리의 다른 글
| [Azure] Azure Front Door 보안 강화 (Service Tag + AFID 기반 백엔드 보호 전략) (0) | 2025.12.11 |
|---|---|
| [Azure] Azure Virtual Desktop(AVD) 가이드 (0) | 2025.12.02 |
| [Cloud] AWS vs Azure 비교 완벽 가이드 (0) | 2025.11.28 |
| [Azure] AKS(Azure Kubernetes Service) 살펴보기 (0) | 2025.11.28 |
| [Azure / AKS] AGIC vs Application Gateway for Containers (0) | 2025.11.28 |