【IAM】クロスクラウド連携でアクセスしてきた相手を特定できるログを確認してみた
タイトル
【IAM】クロスクラウド連携でアクセスしてきた相手を特定できるログを確認してみた
はじめに
データ事業本部の川中子(かわなご)です。
以前の記事で、AWSとGoogle Cloud間のフェデレーションアクセスにおいて、
複数プリンシパルからのアクセスをまとめて許可するような構成を紹介しました。
ただ、そのような構成にした場合にログで追跡できるのか気になりました。
どのプリンシパルがアクセスしてきたのか特定できるのでしょうか。
今回はAWSとGoogle Cloudそれぞれの場合において、
フェデレーションアクセスしてきた相手がログから分かるのかを検証します。
結論
AWS、Google Cloudのどちらの場合でも、ログからアクセス元を確認できました。
- AWS側(CloudTrail):
- Google CloudからアクセスしてきたサービスアカウントのIDがログに記録される
- Google Cloud側(Cloud Logging):
- AWSからアクセスしてきたロールのARNがログに記録される
これにより1つのロールやサービスアカウントに対して、
複数プリンシパルからのフェデレーションアクセスを許可するような形式でも、
どのプリンシパルがアクセスしてきたのかを正確に把握できます。
なお概要については、それぞれ公式のドキュメントでも説明されています。
AWS:
Google Cloud:
検証構成
今回の検証では、以下の2パターンを検証しました。
なお本記事に記載のアカウントIDやクレデンシャル等の値はマスク・変更しています。
Google CloudからAWSにアクセス
1つのIAMロールに対し、複数サービスアカウントからのアクセスを許可する構成です。
Google Cloud側
- サービスアカウント1:
kawanago-crosscloud-test-1 - サービスアカウント2:
kawanago-crosscloud-test-2
AWS側
- IAMロール:
kawanago-crosscloud-test
AWSからGoogle Cloudにアクセス
1つのサービスアカウントに対し、複数IAMロールからのアクセスを許可する構成です。
AWS側
- IAMロール1:
kawanago-crosscloud-test-aws-1 - IAMロール2:
kawanago-crosscloud-test-aws-2
Google Cloud側
- Workload Identity Pool:
kawanago-crosscloud-test - Workload Identity Provider:
kawanago-crosscloud-test-aws - サービスアカウント:
kawanago-cc-test-target
Google CloudからAWSにアクセス
大まかな検証の構成イメージは以下になります。
実際の認証の詳細な流れについては、前回のブログを参照してください。
事前準備
Google Cloud側でサービスアカウントを2つ作成し、一意IDを取得しました。
- サービスアカウント1の一意ID:
100000000000000000001 - サービスアカウント2の一意ID:
100000000000000000002
AWS側では以下の信頼ポリシーでIAMロールを作成しました。
accounts.google.com:oaudとaccounts.google.com:subを条件に指定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "accounts.google.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"accounts.google.com:oaud": "kawanago-crosscloud-test",
"accounts.google.com:sub": [
"100000000000000000001",
"100000000000000000002"
]
}
}
}
]
}
サービスアカウントからAWSにアクセス
サービスアカウント1のIDトークンを取得し、AWSロールを引き受けます。
信頼ポリシーのaudience値にkawanago-crosscloud-testを設定したので、
Google Cloud側のトークン取得時にも同じ値を設定します。
TOKEN=$(gcloud auth print-identity-token \
--impersonate-service-account="kawanago-crosscloud-test-1@my-gcp-project.iam.gserviceaccount.com" \
--audiences="kawanago-crosscloud-test" 2>/dev/null)
aws sts assume-role-with-web-identity \
--role-arn arn:aws:iam::111111111111:role/kawanago-crosscloud-test \
--role-session-name gcp-sa1-session \
--web-identity-token "$TOKEN" \
--duration-seconds 900
レスポンスのSubjectFromWebIdentityTokenを確認します。
サービスアカウント1の一意IDが記録されています。
{
...,
"SubjectFromWebIdentityToken": "100000000000000000001",
"AssumedRoleUser": {
"Arn": "arn:aws:sts::111111111111:assumed-role/kawanago-crosscloud-test/gcp-sa1-session"
},
"Provider": "accounts.google.com",
"Audience": "100000000000000000001"
}
サービスアカウント2で同様に実行すると、別の一意IDが記録されました。
CloudTrailでログを確認
CloudTrailでAssumeRoleWithWebIdentityイベントを検索してみると、
ユーザー名列にアクセス元のサービスアカウントのIDが表示されていました。

参照されたリソースの方では、アシュームされたロールが確認できます。

これで問題なくCloudTrailから、アクセス元の情報を確認できました。
1つのIAMロールに許可をまとめても追跡はできそうです。
AWSからGoogle Cloudにアクセス
大まかな検証の構成イメージは以下になります。
こちらも認証の詳細な流れについては、前回のブログを参照してください。
事前準備
まずはAWS側でIAMロールを2つ作成しています。
今回の検証用に特別に必要な権限はありません。
- IAMロール1:
kawanago-crosscloud-test-aws-1 - IAMロール2:
kawanago-crosscloud-test-aws-2
次にGoogle Cloud側でWorkload Identity関連の資材を作成して、
サービスアカウントとIAMロールの紐づけを行なっています。
- Workload Identity Pool / Provider
- 検証用AWSアカウントからのアクセスを許可
- サービスアカウント:
kawanago-cc-test-target - サービスアカウントに各AWSロールからのアクセスを許可
- 認証情報の構成ファイルをダウンロード
認証情報の構成ファイルは、検証のためにAWSのCloudShellにアップロードしました。
AWSロールからGoogle Cloudにアクセス
AWS CloudShell上で以下のpyファイルを実行し、アクセスを確認します。
import json
import os
import boto3
from google.auth import aws
from google.auth.transport.requests import Request
sts = boto3.client('sts')
creds = sts.assume_role(
RoleArn='arn:aws:iam::111111111111:role/kawanago-crosscloud-test-aws-1',
RoleSessionName='aws-role1-test'
)['Credentials']
os.environ['AWS_ACCESS_KEY_ID'] = creds['AccessKeyId']
os.environ['AWS_SECRET_ACCESS_KEY'] = creds['SecretAccessKey']
os.environ['AWS_SESSION_TOKEN'] = creds['SessionToken']
with open('credential-config.json') as f:
config = json.load(f)
credentials = aws.Credentials.from_info(config)
scoped_credentials = credentials.with_scopes(
['https://www.googleapis.com/auth/cloud-platform']
)
scoped_credentials.refresh(Request())
print(f"Access token: {scoped_credentials.token[:20]}...")
上記のスクリプトにより、正常にアクセストークンを取得できました。
kawanago-crosscloud-test-aws-2でも同様の方法で確認できました。
Cloud Loggingでログを確認
Cloud Loggingの画面でトークン交換のログを検索すると、
こちらも問題なくログが出力されていることが確認できました。
protoPayload.methodName="google.identity.sts.v1.SecurityTokenService.ExchangeToken"

イベントの詳細を開いてみると、authenticationInfo.principalSubject内に、
アクセス元ロールのARNやセッション名が記載されていることが確認できます。
{
"protoPayload": {
"@type": "type.googleapis.com/google.cloud.audit.AuditLog",
"status": {},
"authenticationInfo": {
"principalSubject": "arn:aws:sts::111111111111:assumed-role/kawanago-crosscloud-test-aws-1/aws-role1-test"
},
...
},
...
}
こちらも問題なくCloud Loggingから、アクセス元の情報を確認できました。
1つのサービスアカウントに許可をまとめても追跡できそうです。
なおCloud Loggingで上記のログを確認するには、
IAMの監査ログ設定でデータアクセス監査ログを有効にしておく必要があります。
さいごに
AWSとGoogle Cloudの間でWorkload Identity連携を使った場合でも、
アクセス元を特定できるログが出力されることが分かりました。
-
Google CloudからAWSにアクセスする場合
- CloudTrailの
userIdentity.userNameにサービスアカウントの一意IDが記録される - 同じIAMロールを複数のサービスアカウントで共有しても、それぞれを区別してログが残る
- CloudTrailの
-
AWSからGoogle Cloudにアクセスする場合
- Cloud Loggingの
protoPayload.authenticationInfo.principalSubjectにIAMロールのARNが記録される - 同じサービスアカウントを複数のAWSロールで共有しても、それぞれを区別してログが残る
- Cloud Loggingの
どちらの方向においても、アクセス元のプリンシパルを特定することができました。
外部クラウドからのアクセスを許可するリソースが全て同じ場合に限りますが、
最小限のリソースで、複数プリンシパルからのアクセスを許可できることが分かりました。
少しでも参考になれば幸いです。
最後まで記事を閲覧いただきありがとうございました。







