이 가이드에서는 프로덕션 환경에서 AgentID용 Microsoft Entra SDK를 안전하게 배포하고 운영하기 위한 포괄적인 보안 구성 및 강화 모범 사례를 제공합니다. SDK 배포가 보안 모범 사례를 따르도록 네트워크 격리, 자격 증명 관리, 토큰 유효성 검사, 런타임 보안 및 모니터링을 비롯한 필수 보안 제어를 다룹니다.
주의
AgentID API용 Microsoft Entra SDK는 공개적으로 액세스할 수 없어야 합니다. 동일한 신뢰 경계(예: 동일한 Pod, 동일한 가상 네트워크) 내의 애플리케이션에서만 연결할 수 있어야 합니다. 기본적으로 허용되는 호스트는 localhost입니다. 이 API를 공개적으로 노출하면 권한 없는 토큰 획득을 사용하도록 설정할 수 있으며 이는 중요한 보안 위험입니다. 또한 동일한 신뢰 경계 내의 모든 애플리케이션은 이 API에 액세스할 수 있습니다. 해당 경계 내 모든 애플리케이션이 신뢰받고 철저히 보안되는지 확인합니다.
SDK를 실행해도 안전한가요?
AgentID용 Microsoft Entra SDK는 보안을 염두에 두고 설계되었지만 안전은 적절한 구성 및 배포 방법에 따라 달라집니다. 보안 배포를 보장하려면 다음 모범 사례를 따르세요.
- 컨테이너화된 환경에서만 실행
- localhost/pod-internal에만 액세스 제한
- Kubernetes 네트워크 정책 사용
- 자격 증명을 안전하게 저장(Key Vault, 비밀)
- 루트가 아닌 사용자로 실행
- 감사 로깅 사용
네트워크 보안
네트워크 격리는 인증 작업을 보호하는 데 중요합니다. AgentID용 Microsoft Entra SDK는 엄격한 액세스 제어 및 포괄적인 트래픽 필터링을 사용하여 신뢰할 수 있는 경계 내에서 실행되어야 합니다. 여기에는 인증 엔드포인트에 대한 무단 액세스를 방지하는 localhost 전용 바인딩, Pod 내부 통신 및 네트워크 정책이 포함됩니다.
SDK 액세스 제한
인증 엔드포인트에 대한 외부 네트워크 액세스를 방지하기 위해 localhost에서만 수신 대기하도록 Kestrel을 구성합니다.
containers:
- name: sidecar
image: mcr.microsoft.com/entra-sdk/auth-sidecar:1.0.0
env:
- name: Kestrel__Endpoints__Http__Url
value: "http://127.0.0.1:5000"
또는 AllowedHosts와 함께 Kestrel의 호스트 필터링을 사용하여 액세스를 제한합니다.
containers:
- name: sidecar
image: mcr.microsoft.com/entra-sdk/auth-sidecar:1.0.0
env:
- name: AllowedHosts
value: "localhost;127.0.0.1"
Pod-Local 통신 사용
트래픽이 동일한 Pod 내에 유지되고 네트워크를 트래버스하지 않도록 localhost를 통해 AgentID용 Microsoft Entra SDK와 통신하도록 애플리케이션을 구성합니다.
containers:
- name: app
env:
- name: SIDECAR_URL
value: "http://localhost:5000" # Pod-local communication only
LoadBalancer 또는 Ingress를 통해 노출하지 마세요(외부의 신뢰할 수 없는 경계에서 무단으로 토큰을 획득할 수 있다는 의미입니다).
# WRONG - exposes Microsoft Entra SDK for AgentID publicly
apiVersion: v1
kind: Service
metadata:
name: sidecar-service
spec:
type: LoadBalancer # Exposes SDK publicly - INSECURE
selector:
app: myapp
ports:
- port: 5000
자격 증명 관리
보안 자격 증명 관리는 SDK 보안의 기본 사항입니다. 가능하면 관리 ID를 사용하여 비밀을 제거하고 인증 자격 증명을 구성할 때 최소 권한 원칙을 따릅니다.
컨테이너에 대한 워크로드 ID 선호
AKS(컨테이너화된 배포)에 Azure AD 워크로드 ID를 사용하여 비밀을 완전히 제거하고 파일 기반 토큰 프로젝션을 사용하여 보안 자격 증명 관리를 보장합니다.
apiVersion: v1
kind: ServiceAccount
metadata:
name: myapp-sa
annotations:
azure.workload.identity/client-id: "<managed-identity-client-id>"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
metadata:
labels:
azure.workload.identity/use: "true"
spec:
serviceAccountName: myapp-sa
containers:
- name: sidecar
image: mcr.microsoft.com/entra-sdk/auth-sidecar:1.0.0
env:
- name: AzureAd__ClientId
value: "<web-api-client-id>"
# Workload Identity credentials - uses file-based token projection
- name: AzureAd__ClientCredentials__0__SourceType
value: "SignedAssertionFilePath"
이점: 워크로드 ID는 자동 자격 증명 관리, Azure RBAC 통합 및 전체 감사 내역을 제공하면서 비밀을 저장하거나 회전할 필요가 없습니다. 토큰은 워크로드 아이덴티티 웹훅에 의해 Pod에 자동으로 할당되고, SDK는 SignedAssertionFilePath 자격 증명 유형을 사용하여 이를 읽습니다. 이 방법은 기존 비밀 기반 인증에 비해 보안 위험 및 운영 오버헤드를 크게 줄입니다.
참고: Azure VM 및 App Services(컨테이너화되지 않은 환경)의 경우 대신 자격 증명 형식으로 시스템 또는 사용자 할당 관리 ID를 SignedAssertionFromManagedIdentity 사용합니다. 자세한 내용은 관리 ID 사용을 참조하세요.
비밀보다 인증서 사용
클라이언트 비밀을 피할 수 없는 경우 인증을 위해 인증서를 사용하는 것이 좋습니다. 인증서는 공개 키 암호화를 사용하고 추출하거나 오용하기가 더 어렵기 때문에 클라이언트 비밀보다 더 강력한 보안을 제공합니다. 중앙 집중식 관리 및 자동 갱신을 위해 Azure Key Vault에 인증서를 저장합니다.
- name: AzureAd__ClientCredentials__0__SourceType
value: "KeyVault"
- name: AzureAd__ClientCredentials__0__KeyVaultUrl
value: "https://your-keyvault.vault.azure.net"
- name: AzureAd__ClientCredentials__0__KeyVaultCertificateName
value: "your-cert-name"
이점: Azure Key Vault는 자동화된 회전, 액세스 정책 및 포괄적인 감사를 통해 중앙 집중식 인증서 관리를 제공하며 인증서가 컨테이너 이미지에 포함되지 않도록 합니다. 자세한 내용은 인증에 인증서 사용을 참조하세요.
비밀을 안전하게 저장
Kubernetes 시크릿은 관리 ID 또는 인증서 사용이 불가능한 경우 클라이언트 시크릿을 저장하는 데 적합한 옵션입니다. 시크릿이 물리적으로 저장될 때 암호화되고 액세스가 엄격하게 제어되는지 확인합니다.
apiVersion: v1
kind: Secret
metadata:
name: app-cert
type: Opaque
data:
certificate.pfx: <base64-encoded-pfx>
certificate.password: <base64-encoded-password>
---
containers:
- name: sidecar
volumeMounts:
- name: cert-volume
mountPath: /certs
readOnly: true
env:
- name: AzureAd__ClientCredentials__0__SourceType
value: "Path"
- name: AzureAd__ClientCredentials__0__CertificateDiskPath
value: "/certs/certificate.pfx"
- name: AzureAd__ClientCredentials__0__CertificatePassword
valueFrom:
secretKeyRef:
name: app-cert
key: certificate.password
volumes:
- name: cert-volume
secret:
secretName: app-cert
items:
- key: certificate.pfx
path: certificate.pfx
defaultMode: 0400 # Read-only for owner
클라이언트 비밀(가능한 경우 방지)
클라이언트 비밀을 사용해야 하는 경우 위험을 최소화하기 위해 추가 보안 조치를 구현합니다. 클라이언트 비밀은 관리 ID 또는 인증서보다 안전하지 않으므로 짧은 만료 기간, 미사용 암호화를 사용한 보안 스토리지, RBAC를 통한 제한된 액세스 및 빈번한 회전 일정을 포함한 추가 보호가 필요합니다. 배포 매니페스트에 표시되는 컨테이너 이미지 또는 환경 변수에 비밀을 저장하지 마세요.
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
type: Opaque
stringData:
client-secret: "<your-client-secret>"
---
containers:
- name: sidecar
env:
- name: AzureAd__ClientCredentials__0__SourceType
value: "ClientSecret"
- name: AzureAd__ClientCredentials__0__ClientSecret
valueFrom:
secretKeyRef:
name: app-secrets
key: client-secret
주의
비밀을 소스 제어에 커밋하지 마세요. 외부 비밀 관리(Azure Key Vault, 봉인된 비밀 등)를 사용합니다.
토큰 보안
토큰 보안을 통해 SDK에서 유효한 적절한 범위의 토큰만 수락 및 처리됩니다. 토큰 유효성 검사, 범위 요구 사항 및 대상 그룹 검사를 구현하여 무단 액세스를 방지하고 토큰 오용을 제한합니다.
범위 유효성 검사를 활성화하기
들어오는 토큰에 대한 특정 범위 필요(공백으로 구분):
- name: AzureAd__Scopes
value: "access_as_user"
적절한 대상 그룹 설정
토큰 유효성 검사에 필요한 대상 그룹을 구성합니다.
- name: AzureAd__Audience
value: "api://your-api-id"
비고
예상 대상 그룹 값은 앱 등록의 requestedAccessTokenVersion에 따라 달라집니다.
-
버전 2:
{ClientId}값을 직접 사용 -
버전 1 또는 null: 앱 ID URI를 사용합니다(일반적으로
api://{ClientId}사용자 지정하지 않은 경우)
사용하기 전에 토큰 유효성 검사
사용자 토큰을 수락하기 전에 항상 호출 /Validate 합니다.
GET /Validate
Authorization: Bearer <user-token>
런타임 보안
런타임 보안 컨트롤은 수정, 권한 상승 및 권한 없는 기능 액세스로부터 SDK 컨테이너를 보호합니다. 최소한의 권한과 읽기 전용 파일 시스템을 사용하여 실행되도록 컨테이너를 구성하여 공격 표면을 줄입니다.
읽기 전용 루트 파일 시스템
컨테이너 파일 시스템의 수정 방지:
securityContext:
readOnlyRootFilesystem: true
Pod 보안 정책
보안 표준 적용:
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: sidecar-psp
spec:
privileged: false
allowPrivilegeEscalation: false
requiredDropCapabilities:
- ALL
runAsUser:
rule: 'MustRunAsNonRoot'
seLinux:
rule: 'MustRunAs'
fsGroup:
rule: 'MustRunAs'
readOnlyRootFilesystem: true
로깅 및 모니터링
효과적인 로깅 및 모니터링을 사용하면 변칙을 검색하고, 문제를 해결하고, 규정 준수를 위한 감사 내역을 유지할 수 있습니다. 환경에 적절한 로깅 수준을 구성하고 상태 프로브를 구현하여 SDK가 예상대로 작동하는지 확인합니다.
적절한 로깅 구성
프로덕션 환경:
- name: Logging__LogLevel__Default
value: "Warning"
- name: Logging__LogLevel__Microsoft.Identity.Web
value: "Information"
개발 환경(자세한 정보):
- name: Logging__LogLevel__Default
value: "Debug"
- name: ASPNETCORE_ENVIRONMENT
value: "Development"
건강 모니터링 사용하기
활동성 및 준비 상태 프로브 구성:
livenessProbe:
httpGet:
path: /health
port: 5000
initialDelaySeconds: 10
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: 5000
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 3
모범 사례 검사 목록
이 포괄적인 검사 목록을 사용하여 SDK 배포가 네트워크, 자격 증명, 토큰, 런타임 및 모니터링 차원에서 권장되는 모든 보안 사례를 따르도록 합니다.
네트워크:
- [ ] SDK는 localhost/127.0.0.1에서만 수신 대기합니다.
- [ ] LoadBalancer 또는 Ingress를 통해 노출되지 않음
- [ ] 네트워크 정책으로 외부 액세스 제한
- [ ] 외부 통신을 위한 HTTPS/TLS
자격 증명:
- [ ] 컨테이너에 워크로드 ID 사용(AKS, Kubernetes, Docker)
SignedAssertionFilePath - [ ]
를 통해 VM/App Services에서 관리 ID 사용 - [ ] 비밀보다 인증서 선호
- [ ] 보안 관리 시스템에 저장된 비밀
- [ ] 주기적인 자격 증명 갱신
토큰:
- [ ] 범위 유효성 검사 사용
- [ ] 대상 유효성 검사 구성됨
- [ ] 사용하기 전에 유효성이 검사된 토큰
런타임:
- [ ] 컨테이너가 루트가 아닌 것으로 실행됨
- [ ] 읽기 전용 루트 파일 시스템
- [ ] 적용된 보안 컨텍스트
- [ ] 리소스 제한 설정
모니터링:
- [ ] 적절한 로깅이 구성됨
- [ ] 상태 검사를 사용하도록 설정됨
- [ ] 감사 로깅 사용
- [ ] 구성된 경고
일반적인 보안 패턴
참조 구현은 여러 보안 컨트롤을 통합 배포 패턴으로 결합하는 방법을 보여 줍니다. 이러한 패턴은 다양한 위협 모델에서 프로덕션 배포를 위한 템플릿 역할을 합니다.
고보안 배포
apiVersion: v1
kind: ServiceAccount
metadata:
name: secure-app-sa
annotations:
azure.workload.identity/client-id: "<managed-identity-id>"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: secure-app
spec:
template:
metadata:
labels:
azure.workload.identity/use: "true"
spec:
serviceAccountName: secure-app-sa
securityContext:
fsGroup: 2000
containers:
- name: sidecar
image: mcr.microsoft.com/entra-sdk/auth-sidecar:1.0.0
ports:
- containerPort: 5000
env:
- name: Kestrel__Endpoints__Http__Url
value: "http://127.0.0.1:5000"
- name: AzureAd__TenantId
valueFrom:
configMapKeyRef:
name: app-config
key: tenant-id
- name: AzureAd__ClientId
value: "<managed-identity-client-id>"
securityContext:
runAsNonRoot: true
runAsUser: 1000
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "250m"
livenessProbe:
httpGet:
path: /health
port: 5000
initialDelaySeconds: 10
periodSeconds: 10
자격 증명을 정기적으로 교체
자격 증명을 교체하면 자격 증명이 유출되거나 손상된 경우 공격자가 공격할 기회가 줄어듭니다. 회전 빈도는 자격 증명 유형 및 조직의 보안 정책에 따라 달라집니다.
- 클라이언트 비밀: 90일마다(권장)
- 인증서: 만료 전, 일반적으로 1-2년마다
- 서명된 SHR(HTTP 요청) 키: 조직의 보안 정책을 따릅니다.
구현 지침: 자동화된 회전 기능으로 Azure Key Vault를 사용하거나 외부 비밀 관리자(예: 봉인된 비밀)를 배포 파이프라인에 통합합니다. 이렇게 하면 수동 개입이 최소화되고 일관된 회전 일정이 보장됩니다.
손상된 자격 증명에 응답
자격 증명이 손상되었다고 의심되는 경우 즉시 다음 단계에 따라 사고를 통제하고 무단 액세스를 방지하십시오.
- Microsoft Entra ID에서 손상된 자격 증명 해지 - 애플리케이션 등록에서 자격 증명을 제거하여 즉시 사용을 차단합니다.
- 새 자격 증명 생성 - Microsoft Entra ID에 새 클라이언트 비밀 또는 인증서를 만들어 손상된 암호를 대체합니다.
- 비밀 관리 시스템 업데이트 - 적절한 액세스 제어를 사용하여 Kubernetes 비밀 또는 Azure Key Vault에 새 자격 증명을 저장합니다.
- SDK 컨테이너 다시 배포 - 새 자격 증명을 사용하도록 배포를 업데이트하여 실행 중인 모든 인스턴스가 변경 내용을 선택하도록 합니다.
- 액세스 로그 검토 - 손상 기간 동안 Azure Monitor 및 Kubernetes 감사 로그에서 권한 없는 토큰 요청 또는 의심스러운 활동의 징후를 확인합니다.
- 인시던트 문서화 - 인시던트의 세부 정보(발견된 경우, 발생한 방법, 액세스한 내용)를 기록하고 조직의 인시던트 대응 절차를 따라 되풀이를 방지합니다.