보안 & 인증: Key Vault, Managed Identity, RBAC
개요
프로덕션 AI 서비스에서 가장 흔한 보안 실수는 API 키를 코드나 환경변수 파일에 직접 기입하는 것입니다. Azure에서는 다음 세 가지 원칙을 통해 이를 방지합니다.
- Secrets는 Key Vault에: API 키, DB 연결 문자열, 인증서를 코드에서 분리하여 중앙 관리
- 비밀번호 없는 인증 (Managed Identity): Service Principal의
client_secret없이 Azure 서비스 간 신뢰 관계로 인증 - 최소 권한 원칙 (RBAC): 각 서비스/사람이 꼭 필요한 권한만 갖도록 세밀하게 제어
graph TB
Dev["👨💻 개발자\n(Entra ID 계정)"]
GHCI["GitHub Actions\n(Workload Identity)"]
AKSPod["AKS Pod\n(Workload Identity)"]
subgraph "Azure 신뢰 체계"
EntraID["Microsoft Entra ID\n(중앙 ID 관리)"]
MI_App["Managed Identity\n(ai-app-identity)"]
MI_GH["Managed Identity\n(github-actions-identity)"]
end
subgraph "보호 대상 리소스"
KV["Azure Key Vault\n(Secrets / Certs)"]
ACR["Azure Container Registry"]
AKS["AKS Cluster"]
end
Dev -->|RBAC 역할로| KV
Dev -->|RBAC 역할로| AKS
GHCI -->|OIDC 토큰| EntraID
AKSPod -->|OIDC 토큰| EntraID
EntraID -->|액세스 토큰 발급| MI_App
EntraID -->|액세스 토큰 발급| MI_GH
MI_App -->|"Key Vault Secrets User"| KV
MI_GH -->|"AcrPush"| ACR
1. Azure Key Vault
Azure Key Vault는 다음 세 가지 유형의 민감 정보를 안전하게 저장하고 버전 관리합니다.
| 유형 | 용도 | 예시 |
|---|---|---|
| Secrets | API 키, 비밀번호, 연결 문자열 | OPENAI_API_KEY, DB_PASSWORD |
| Keys | 암/복호화용 암호화 키 | 데이터 암호화, 서명 생성 |
| Certificates | TLS/SSL 인증서 | App Gateway에 연결되는 HTTPS 인증서 |
Key Vault 생성 및 Secret 등록
# Key Vault 생성
az keyvault create \
--name my-ai-kv \
--resource-group my-rg \
--location koreacentral \
--enable-rbac-authorization true # RBAC 모드 사용 (Access Policy 방식 지양)
# Secret 등록
az keyvault secret set \
--vault-name my-ai-kv \
--name "openai-api-key" \
--value "sk-..."
az keyvault secret set \
--vault-name my-ai-kv \
--name "db-connection-string" \
--value "postgresql://user:pass@host:5432/db"
AKS에서 Key Vault Secret 사용: CSI Driver
AKS의 Secrets Store CSI Driver는 Key Vault의 Secret을 파드 내 파일 또는 환경변수로 마운트합니다. 파드가 재시작되면 최신 Secret 값으로 자동 갱신됩니다.
# secretproviderclass.yaml
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: ai-app-secrets
namespace: production
spec:
provider: azure
parameters:
usePodIdentity: "false"
clientID: <managed-identity-client-id> # Workload Identity와 연결
keyvaultName: my-ai-kv
tenantId: <tenant-id>
objects: |
array:
- |
objectName: openai-api-key
objectType: secret
- |
objectName: db-connection-string
objectType: secret
secretObjects:
- secretName: ai-app-env-secrets # K8s Secret으로도 동기화
type: Opaque
data:
- objectName: openai-api-key
key: OPENAI_API_KEY
- objectName: db-connection-string
key: DATABASE_URL
# deployment.yaml (일부) - Secret을 환경변수로 주입
spec:
containers:
- name: ai-app
image: myacrregistry.azurecr.io/ai-app:latest
envFrom:
- secretRef:
name: ai-app-env-secrets # CSI Driver가 생성한 K8s Secret
volumeMounts:
- name: secrets-store
mountPath: "/mnt/secrets"
readOnly: true
volumes:
- name: secrets-store
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: ai-app-secrets
2. Managed Identity & Workload Identity
Managed Identity는 Azure가 관리하는 ID로, 서비스 주체(Service Principal)의 client_id + client_secret을 직접 관리할 필요 없이 Azure 리소스 간 신뢰 기반으로 인증합니다.
Managed Identity 종류
| 종류 | 설명 | 사용 사례 |
|---|---|---|
| System-assigned | Azure 리소스(VM, AKS)에 자동 생성·소멸 | 단순 1:1 연결 |
| User-assigned | 사용자가 독립적으로 생성, 여러 리소스에 공유 | AI 앱 권장 (재사용 가능, 생명주기 독립) |
Workload Identity 전체 설정 흐름
# 1. User-assigned Managed Identity 생성
az identity create \
--name ai-app-identity \
--resource-group my-rg
# 클라이언트 ID 확인 (Pod에 주입할 값)
CLIENT_ID=$(az identity show --name ai-app-identity --resource-group my-rg --query clientId -o tsv)
# 2. Key Vault에 역할 부여
az role assignment create \
--assignee $CLIENT_ID \
--role "Key Vault Secrets User" \
--scope /subscriptions/.../vaults/my-ai-kv
# ACR에 이미지 Pull 권한 부여
az role assignment create \
--assignee $CLIENT_ID \
--role "AcrPull" \
--scope /subscriptions/.../registries/myacrregistry
# 3. AKS OIDC Issuer URL 확인
OIDC_URL=$(az aks show --name my-aks --resource-group my-rg --query oidcIssuerProfile.issuerUrl -o tsv)
# 4. Federated Credential 등록 (K8s ServiceAccount와 연결)
az identity federated-credential create \
--name ai-app-fed \
--identity-name ai-app-identity \
--resource-group my-rg \
--issuer $OIDC_URL \
--subject "system:serviceaccount:production:ai-app-sa"
# 5. K8s ServiceAccount 생성 (Managed Identity 클라이언트 ID 주석 추가)
kubectl create serviceaccount ai-app-sa --namespace production
kubectl annotate serviceaccount ai-app-sa \
--namespace production \
azure.workload.identity/client-id=$CLIENT_ID
# deployment.yaml에서 ServiceAccount 지정
spec:
serviceAccountName: ai-app-sa
template:
metadata:
labels:
azure.workload.identity/use: "true" # Workload Identity 활성화
3. Azure RBAC: 역할 기반 접근 제어
Azure RBAC은 리소스에 대한 접근 권한을 누가(Who), 무엇을(What), 어디서(Where) 할 수 있는지 정의합니다. 최소 권한 원칙(Principle of Least Privilege)을 적용해야 합니다.
AI 서비스 배포에서 주요 역할 정의
| 역할 | 부여 대상 | 범위 | 설명 |
|---|---|---|---|
AcrPush |
GitHub Actions MI | ACR | 이미지 빌드 후 푸시 |
AcrPull |
App MI, AKS | ACR | 이미지 배포 시 Pull |
Key Vault Secrets User |
App MI | Key Vault | Secret 읽기 (쓰기 불가) |
Key Vault Secrets Officer |
담당 개발자 | Key Vault | Secret 생성·수정·삭제 |
Contributor |
DevOps 엔지니어 | Resource Group | 인프라 변경 |
Reader |
일반 개발자 | Resource Group | 상태 조회만 |
역할 할당 명령어
# 개발자에게 Key Vault Secret 관리 권한 부여
az role assignment create \
--assignee user@company.com \
--role "Key Vault Secrets Officer" \
--scope /subscriptions/.../vaults/my-ai-kv
# 특정 그룹에게 AKS 읽기 권한 부여
az role assignment create \
--assignee <group-object-id> \
--role "Azure Kubernetes Service Cluster User Role" \
--scope /subscriptions/.../managedClusters/my-aks
4. Microsoft Entra ID (구 Azure AD)
Microsoft Entra ID는 Azure의 중앙 ID 및 인증 서비스입니다. 개발자와 서비스의 모든 인증 흐름이 Entra ID를 통해 이루어집니다.
AKS와 Entra ID 통합 (RBAC)
# AKS에 Entra ID 통합 기반 RBAC 활성화
az aks update \
--resource-group my-rg \
--name my-aks \
--enable-azure-rbac \
--enable-aad
# 특정 Entra ID 그룹에게 AKS 클러스터 관리자 권한 부여
az role assignment create \
--assignee <entra-group-id> \
--role "Azure Kubernetes Service RBAC Cluster Admin" \
--scope /subscriptions/.../managedClusters/my-aks
이후 개발자는 자신의 Entra ID 계정으로 AKS에 로그인합니다.
az aks get-credentials --resource-group my-rg --name my-aks
# → 브라우저 팝업 또는 디바이스 코드로 Entra ID 로그인
kubectl get pods -n production
관련 문서
- AKS 설계 및 운영: Workload Identity가 실제 적용되는 AKS 클러스터
- ACR + CI/CD: GitHub Actions의 Workload Identity Federation
- 네트워크: Key Vault, ACR을 VNet 안에 격리하는 Private Endpoint