Azure 리소스를 위한 AWS Outbound Identity Federation 사용
Source: Dev.to
AWS 아웃바운드 아이덴티티 연동을 사용하여 Azure 리소스에 접근하기
AWS와 Azure를 동시에 운영하고 있다면, 두 클라우드 간에 아이덴티티 연동을 설정해 두 시스템을 원활히 연결하고 싶을 때가 많습니다.
이 글에서는 AWS Outbound Identity Federation(AWS OIDC 연동)을 활용해 Azure 리소스에 접근하는 방법을 단계별로 살펴보겠습니다.
목차
시나리오 개요
- AWS Lambda 혹은 EC2 인스턴스에서 실행되는 애플리케이션이 Azure Storage Account 혹은 Azure Key Vault와 같은 Azure 서비스에 접근해야 합니다.
- 기존에 각각의 클라우드에 별도 IAM/AD 계정을 만들고 관리하는 대신, AWS에서 발급한 임시 보안 토큰을 이용해 Azure AD에 인증하도록 구성합니다.
핵심 아이디어
AWS는 OIDC 프로바이더 역할을 수행하고, Azure AD는 해당 OIDC 토큰을 신뢰하도록 설정한다.
필수 전제 조건
| 항목 | 요구 사항 |
|---|---|
| AWS 계정 | IAM 권한: iam:CreateOpenIDConnectProvider, iam:CreateRole, iam:PutRolePolicy 등 |
| Azure AD 테넌트 | Enterprise applications에 커스텀 애플리케이션을 추가할 수 있는 권한 |
| CLI/SDK | aws cli (v2 이상)와 az cli (v2.0 이상) 설치 |
| 리소스 | 테스트용 Azure Storage Account 혹은 Key Vault (이미 생성돼 있어야 함) |
AWS에서 OIDC IdP 생성
- OIDC 메타데이터 URL을 확인합니다. AWS에서는 자체적으로 메타데이터 엔드포인트를 제공하지 않으므로, AWS STS가 발행하는 토큰을 OIDC 형식으로 변환해 주는 AWS Cognito 혹은 AWS IAM OIDC Provider를 사용합니다. 여기서는 Cognito User Pool를 이용합니다.
# 1) Cognito User Pool 생성 (이미 존재한다면 스킵)
aws cognito-idp create-user-pool \
--pool-name AwsOutboundFederationPool \
--auto-verified-attributes email
# 2) User Pool에 OIDC IdP 설정
aws cognito-idp create-identity-provider \
--user-pool-id <POOL_ID> \
--provider-name OIDCProvider \
--provider-type OIDC \
--provider-details client_id=<CLIENT_ID>,client_secret=<CLIENT_SECRET>,attributes_request_method=GET,oidc_issuer=https://cognito-idp.<region>.amazonaws.com/<POOL_ID>
- IAM OIDC Provider를 등록합니다.
aws iam create-open-id-connect-provider \
--url https://cognito-idp.<region>.amazonaws.com/<POOL_ID> \
--client-id-list <CLIENT_ID> \
--thumbprint-list <THUMBPRINT>
팁:
thumbprint-list는 IdP의 SSL 인증서 SHA‑1 지문이며,openssl명령어로 확인할 수 있습니다.
Azure AD에 신뢰 관계 설정
- Azure Portal > Azure Active Directory > Enterprise applications 로 이동합니다.
- 새 애플리케이션 > Non-gallery application 선택 후, 이름을
AWS OIDC Federation로 지정합니다. - Single sign-on 탭에서 SAML 대신 OIDC를 선택합니다.
- Issuer URL에 앞서 만든 AWS OIDC Provider URL(
https://cognito-idp.<region>.amazonaws.com/<POOL_ID>)을 입력하고, Client ID와 Client Secret을 동일하게 입력합니다. - User assignment required? 옵션을 No 로 설정해 두면, 토큰에 포함된
sub클레임만으로 인증이 가능합니다.
중요: Azure AD는 기본적으로 OIDC 토큰의
aud(audience) 값을 검증합니다. 따라서 AWS IAM 역할 정책에서aud를 Azure AD 애플리케이션의 Application (client) ID 로 지정해야 합니다.
IAM 역할 및 정책 구성
1️⃣ 역할 생성
aws iam create-role \
--role-name AzureFederatedRole \
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/cognito-idp.<region>.amazonaws.com/<POOL_ID>"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"cognito-idp.<region>.amazonaws.com/<POOL_ID>:aud": "<AZURE_AD_CLIENT_ID>"
}
}
}
]
}'
2️⃣ 정책 부여 (예: Azure Storage Blob 읽기)
aws iam put-role-policy \
--role-name AzureFederatedRole \
--policy-name AzureBlobReadPolicy \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": "*"
}
]
}'
주의: 실제 Azure 리소스에 접근하려면 Azure 측에서 Managed Identity 혹은 Service Principal에 대한 권한 부여가 필요합니다. 여기서는 AWS에서 발급받은 임시 토큰을 Azure AD가 신뢰하도록 설정하는 것이 핵심이므로, Azure RBAC 설정은 별도로 진행합니다.
실제 호출 예시
아래 예시는 AWS Lambda (Python) 함수에서 Azure Key Vault에 저장된 비밀을 조회하는 흐름을 보여줍니다.
import json
import boto3
import requests
def lambda_handler(event, context):
# 1) AWS STS 로 OIDC 토큰 획득
client = boto3.client('sts')
resp = client.assume_role_with_web_identity(
RoleArn='arn:aws:iam::<AWS_ACCOUNT_ID>:role/AzureFederatedRole',
RoleSessionName='AzureAccessSession',
WebIdentityToken=event['token'] # Lambda 트리거에서 전달된 OIDC 토큰
)
access_token = resp['Credentials']['SessionToken']
# 2) Azure AD 토큰 엔드포인트에 교환 요청
token_endpoint = "https://login.microsoftonline.com/<TENANT_ID>/oauth2/v2.0/token"
data = {
'client_id': '<AZURE_AD_CLIENT_ID>',
'client_secret': '<AZURE_AD_CLIENT_SECRET>',
'grant_type': 'urn:ietf:params:oauth:grant-type:token-exchange',
'subject_token': access_token,
'subject_token_type': 'urn:ietf:params:oauth:token-type:access_token',
'scope': 'https://vault.azure.net/.default'
}
r = requests.post(token_endpoint, data=data)
azure_token = r.json()['access_token']
# 3) Azure Key Vault 호출
vault_name = "<YOUR_VAULT_NAME>"
secret_name = "MySecret"
kv_url = f"https://{vault_name}.vault.azure.net/secrets/{secret_name}?api-version=7.2"
headers = {"Authorization": f"Bearer {azure_token}"}
secret_resp = requests.get(kv_url, headers=headers)
return {
'statusCode': 200,
'body': json.dumps(secret_resp.json())
}
핵심 흐름
1️⃣ AWS IAM 역할을 통해 WebIdentityToken을 획득 → 2️⃣ 해당 토큰을 Azure AD에 Token Exchange(RFC 8693) 방식으로 전달 → 3️⃣ Azure AD가 발행한 액세스 토큰으로 Azure 리소스 호출
정리 및 베스트 프랙티스
| 항목 | 권장 사항 |
|---|---|
| 토큰 수명 | 최소 권한 원칙에 따라 sts:AssumeRoleWithWebIdentity 의 DurationSeconds 를 900 초(15 분) 이하로 제한 |
| 감사 로그 | AWS CloudTrail 과 Azure AD Sign‑in logs 를 연동해 교차 감사를 수행 |
| 비밀 관리 | AWS Secrets Manager 에서 Azure AD client secret 을 저장하고, Lambda 에서는 boto3 로 동적으로 읽어 사용 |
| 오류 처리 | 토큰 교환 단계에서 invalid_grant 오류가 발생하면, AWS 토큰이 만료됐을 가능성이 높음 → 재발급 로직 구현 |
| 네트워크 | Lambda 혹은 EC2 가 Azure 엔드포인트에 접근할 수 있도록 VPC 엔드포인트 혹은 VPN 설정 검토 |
마무리
AWS Outbound Identity Federation을 활용하면 별도의 사용자 계정 관리 없이 AWS와 Azure 사이에 안전한 신뢰 관계를 구축할 수 있습니다.
위 단계들을 따라 설정하면, 기존에 구축된 AWS 워크로드가 Azure 리소스에 무중단으로 접근할 수 있게 되며, 보안·운영 효율성 모두 크게 향상됩니다.
추가 자료
AWS Identity Federation Limitations
Google Cloud의 workload identity pool AWS provider와 달리 Azure 관리형 ID는 사전 서명된 URL을 사용한 IAM 인증을 지원하지 않습니다. Azure 관리형 ID는 외부 OpenID Connect (OIDC) 공급자만 지원하므로, AWS에서 실행되는 워크로드가 OIDC 토큰을 변환할 수 있는 다른 서비스를 사용하지 않고는 Azure 환경으로 연동될 수 없습니다(예: AWS EKS 또는 Cognito).
지금까지 Puma Security의 Nymeria cross‑cloud workload identity 프로젝트는 AWS Lambda 함수와 EKS 팟을 Azure 및 Google Cloud 스토리지 리소스로 연동하는 예시를 제공했습니다. 2025 re:Invent에서 발표된 IAM Outbound Identity Federation와 함께, AWS EC2 인스턴스가 Azure 스토리지 리소스로 연동할 수 있는 지원을 추가했습니다.
아래 다이어그램은 AWS Outbound Identity Federation을 사용해 Azure Blob 스토리지 컨테이너에 접근하는 AWS EC2 인스턴스의 아키텍처를 보여줍니다. EC2 인스턴스는 sts:GetWebIdentityToken API를 통해 AWS IAM으로부터 서명된 OIDC 토큰을 요청합니다. 이 AWS 서명 OIDC 토큰을 사용해 Azure 테넌트의 사용자 지정 관리형 ID에 로그인한 뒤, EC2 인스턴스는 Azure 액세스 토큰을 획득하고 스토리지 컨테이너와 Blob 객체에 접근할 수 있습니다.
AWS 아웃바운드 아이덴티티 연합 설정
기능을 사용하려면 먼저 AWS 계정에서 Outbound Identity Federation을 활성화해야 합니다. 이는 AWS Management Console을 통해서든 Terraform 프로바이더(v6.26.0 이후)에서 새로운 aws_iam_outbound_web_identity_federation 리소스를 사용해서든 할 수 있습니다:
# Enables account‑level web identity federation
resource "aws_iam_outbound_web_identity_federation" "this" {}
구성을 적용하면 AWS IAM 콘솔에 아웃바운드 아이덴티티 연합이 활성화되었으며 계정에 고유한 Token Issuer URL이 생성된 것을 확인할 수 있습니다. 이 URL은 나중에 Azure 관리형 아이덴티티의 신뢰 관계를 설정할 때 필요합니다.
AWS 아웃바운드 ID 연합 권한
기능을 사용하려면 EC2 인스턴스를 위한 IAM 역할(및 인스턴스 프로파일)을 생성하십시오. 역할에는 sts:GetWebIdentityToken 권한이 포함되어야 합니다.
Terraform – IAM 정책 문서
data "aws_iam_policy_document" "cross_cloud" {
statement {
sid = "AllowTokenVending"
effect = "Allow"
actions = [
"sts:GetWebIdentityToken",
]
resources = [
"*",
]
}
}
resource "aws_iam_policy" "cross_cloud" {
name = "nymeria-cross-cloud-token-${random_string.unique_id.result}"
path = "/"
description = "IAM policy for Nymeria VM"
policy = data.aws_iam_policy_document.cross_cloud.json
tags = {
Product = "Nymeria"
}
}
EC2 인스턴스에서 토큰 요청
인스턴스에 연결(SSM Session Manager 또는 SSH 사용)하고 다음 AWS CLI 명령을 실행하십시오:
aws sts get-web-identity-token \
--audience api://AzureADTokenExchange \
--signing-algorithm RS256 \
--duration-seconds 300
명령은 아래와 유사한 JSON을 반환합니다. WebIdentityToken 필드에는 서명된 OIDC 토큰이 포함되고, Expiration 필드에는 토큰 만료 시간이 표시됩니다.
{
"WebIdentityToken": "",
"Expiration": "2025-12-20T12:34:56Z"
}
이제 이 토큰을 Azure AD와 교환하여 Azure 액세스 토큰을 얻고 원하는 Azure Blob 스토리지 리소스에 접근할 수 있습니다.
{
"IdentityToken": "eyJraWQiOiJSU0FfMCIsInR5cCI6IkpXVCIsImFsZyI6IlJTMjU2In0...",
"Expiration": "2025-12-19T04:06:07.577000+00:00"
}
Source: …
Azure 관리형 ID 구성
이제 AWS 아웃바운드 ID 토큰을 요청하는 방법을 알았으니, Azure 관리형 ID가 AWS 아웃바운드 ID 공급자를 신뢰하도록 구성할 수 있습니다. 여기서는 AWS ID 토큰에서 필요한 클레임을 추출하고, 해당 클레임을 사용해 Azure 관리형 ID의 연합 자격 증명을 설정합니다.
AWS 아웃바운드 ID 토큰 클레임
먼저 jq를 사용해 AWS ID 토큰을 디코딩합니다. Azure 관리형 ID의 신뢰 관계를 구성하려면 토큰의 iss(발행자)와 sub(주체) 클레임이 필요합니다.
JWT=$(aws sts get-web-identity-token \
--audience api://AzureADTokenExchange \
--signing-algorithm RS256 \
--duration-seconds 300 | jq -r '.WebIdentityToken')
참고: Azure 관리형 ID 연합은 https://sts.amazonaws.com/ 클레임에 포함된 고급 클레임 필터를 지원하지 않습니다. Azure 관리형 ID 신뢰를 구성할 때는 iss, aud, sub 클레임만 필요합니다.
{
"aud": "api://AzureADTokenExchange",
"sub": "arn:aws:iam::123456789012:role/nymeria-cross-cloud-9zo9h8c5",
"https://sts.amazonaws.com/": {
"ec2_instance_source_vpc": "vpc-1234567890123456",
"ec2_role_delivery": "2.0",
"org_id": "o-abcd1234",
"aws_account": "123456789012",
"ou_path": [
"o-abcd1234/r-abc/ou-abc-def/"
],
"original_session_exp": "2025-12-19T10:21:06Z",
"source_region": "us-east-2",
"ec2_source_instance_arn": "arn:aws:ec2:us-east-2:123456789012:instance/i-12345678901234567",
"principal_id": "arn:aws:iam::123456789012:role/nymeria-cross-cloud-9zo9h8c5",
"principal_tags": {
"Product": "Nymeria"
},
"ec2_instance_source_private_ipv4": "10.142.128.107"
},
"iss": "https://53e20c38-5c03-41f7-8baa-a67e81974de0.tokens.sts.global.api.aws",
"exp": 1766118898,
"iat": 1766118598,
"jti": "1640bab7-b35b-4410-b4ee-04d219abbf33"
}
Source: …
Azure 관리형 ID 신뢰 구성
Azure 테넌트에 대한 신뢰를 설정하려면, 교차 클라우드 스토리지 계정에서 데이터를 읽을 수 있는 권한을 가진 리소스 그룹에 사용자 할당 관리형 ID를 생성하십시오.
Terraform – 관리형 ID 및 역할 할당
resource "azurerm_user_assigned_identity" "cross_cloud" {
name = "cross-cloud-vm-${random_string.unique_id.result}"
location = var.location
resource_group_name = azurerm_resource_group.federated_identity.name
}
resource "azurerm_role_assignment" "cross_cloud_blob_reader" {
principal_id = azurerm_user_assigned_identity.cross_cloud.principal_id
scope = azurerm_storage_account.cross_cloud.id
role_definition_name = "Storage Blob Data Reader"
}
Terraform – 연합 자격 증명
사용자 할당 관리형 ID의 연합 자격 증명을 구성하여 AWS 아웃바운드 ID 공급자를 신뢰하도록 설정합니다.
resource "azurerm_federated_identity_credential" "aws" {
name = "nymeria-aws"
resource_group_name = var.azure_resource_group_name
parent_id = var.azure_managed_identity_id
issuer = var.aws_account_issuer
audience = ["api://AzureADTokenExchange"]
subject = var.aws_iam_role_arn
}
var.aws_account_issuer→https://53e20c38-5c03-41f7-8baa-a67e81974de0.tokens.sts.global.api.awsvar.aws_iam_role_arn→arn:aws:iam::123456789012:role/nymeria-cross-cloud-9zo9h8c5
AWS EC2에서 Azure Blob 스토리지에 액세스하기
페더레이션 및 신뢰 관계가 구성되면, EC2 인스턴스가 이제 Azure Blob 스토리지 컨테이너에 액세스할 수 있습니다.
-
새 AWS 아웃바운드 ID 토큰을 요청하고 이를
JWT라는 환경 변수에 저장합니다.JWT=$(aws sts get-web-identity-token \ --audience api://AzureADTokenExchange \ --signing-algorithm RS256 \ --duration-seconds 300 | jq -r '.WebIdentityToken') -
필요한 Azure 변수들을 내보냅니다:
export AZURE_TENANT_ID="your-azure-tenant-id" export AZURE_MANAGED_IDENTITY_CLIENT_ID="your-managed-identity-client-id" export AZURE_STORAGE_ACCOUNT="your-storage-account-name"
AWS 아웃바운드 ID 토큰으로 Azure 인증
az login \
--service-principal \
--tenant $AZURE_TENANT_ID \
--username $AZURE_MANAGED_IDENTITY_CLIENT_ID \
--federated-token $JWT
이 명령은 성공적인 인증을 확인하는 JSON 블록을 반환합니다.
Azure 스토리지 컨테이너의 Blob 목록 조회
az storage blob list \
--auth-mode login \
--account-name $AZURE_STORAGE_ACCOUNT \
--container-name assets \
| jq '.[].name'
출력은 Blob 이름들을 나열하며, 스토리지 계정에 대한 접근이 정상적으로 작동함을 확인합니다.
Conclusion
AWS IAM Outbound Identity Federation은 AWS에서 실행되는 워크로드가 짧은 수명과 서명된 OIDC 토큰을 사용하여 외부 클라우드 리소스에 안전하게 접근할 수 있는 새로운 방법을 제공합니다. 이 기능을 통해 Puma Security Nymeria 크로스‑클라우드 워크로드 아이덴티티 프로젝트는 이제 AWS EC2 인스턴스에서 Azure와 Google Cloud 스토리지 리소스로 연동을 지원합니다.
참고 문헌
- Wiz 블로그: 2025년 보안 팀을 위한 주요 AWS re:Invent 발표 (Scott Piper)
- AWS 뉴스 블로그: AWS IAM 아웃바운드 ID 연동을 사용하여 외부 서비스에 대한 액세스 간소화
- Terraform: aws_iam_outbound_web_identity_federation 리소스
- Nymeria 워크숍 GitHub 저장소: https://github.com/pumasecurity/nymeria
저자 소개
Eric Johnson – LinkedIn profile
Eric의 경험에는 클라우드 보안 아키텍처 및 설계, 클라우드‑네이티브 및 쿠버네티스 평가, 인프라스트럭처‑as‑code 자동화, 애플리케이션 보안 자동화, 웹 및 모바일 애플리케이션 침투 테스트, 보안 개발 라이프사이클 컨설팅, 그리고 보안 코드‑review 평가가 포함됩니다.

