別々のIAMユーザーが同じロールにスイッチしたら、CloudTrailログで見分けられるのか検証してみた
こんにちは、kaz です。
先日ふと、「複数人が同じロールにスイッチしていたら、CloudTrail 上で誰の操作か分かるんだっけか・・・?」と気になったことから、実際に検証してみました!
はじめに
運用などでは管理用の IAM ロールを 1 つ用意して、チームの複数メンバーがそこへスイッチして作業することもあると思います。
本来ならば各ユーザーごとにロールを作成することが望ましいですが、メンバーの入退場などで管理が煩雑になったりとトレードオフがあると思います。
ただ、同じロール上で実行されることになるため、誰が操作したか分からなくなるのでは・・・?という疑問が浮かびました。
本記事では、下記のような構成のときに CloudTrail のログから誰が操作したかをどこまで判別できるか検証した結果をお伝えしたいと思います。
結論
先に結論をまとめておきます。
※なお、「マネジメントコンソール」と「CLI(SDK等も含む)」では判別方法が異なります
AssumeRoleイベント自体には、元の IAM ユーザーなどのプリンシパル情報がしっかり記録される- スイッチ後の操作イベントには元のユーザー名は直接残らず、「セッション名」が手がかりになる
- マネジメントコンソールからのスイッチロールでは セッション名 = IAM ユーザー名 が自動設定されるため判別可能
- CLI からの
AssumeRoleでは セッション名を自由に設定可能なため、そのままでは確実な判別は難しい
前提条件
今回の検証環境はこちらです。
- AWS アカウント:
111111111111と222222222222の 2 つ - IAM ユーザー:
user-aとuser-bの 2 人 - IAM ロール:
SwitchTestRoleを 1 つ作成 - 2 人とも同じ
SwitchTestRoleにスイッチして操作する

やってみた
マネジメントコンソールの場合
1. IAM ロールの作成
まず、222222222222 アカウントで SwitchTestRole を作成します。
信頼ポリシーでは、個別のユーザーではなくアカウント ID(root)を指定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:root"
},
"Action": "sts:AssumeRole"
}
]
}
これで sts:AssumeRole の許可を持つプリンシパルなら誰でもスイッチできる状態になります。
アクセス許可ポリシーは検証用に PowerUserAccess を付けておきました。

2. コンソールからスイッチロールして操作
user-a でマネジメントコンソールにサインインし、画面右上のメニューから「ロールの切り替え」で SwitchTestRole にスイッチします。

スイッチ後、EC2 キーペアを作成します。同じ操作を user-b でも行っておきます。(CreateKeyPair が記録されます)

3. CloudTrail のログを確認
ここからが本記事のメインです。
CloudTrail のイベント履歴から、CreateKeyPair が記録されたイベントを見てみます。
まず、user-a 側を見てみます。ログの userIdentity はこうなっていました。
不要なところは削ってます。
{
"eventName": "CreateKeyPair",
"userIdentity": {
"type": "AssumedRole",
"principalId": "AROAXXXXXXXXXXX:user-a",
"arn": "arn:aws:sts::222222222222:assumed-role/SwitchTestRole/user-a",
"accountId": "222222222222",
"accessKeyId": "ASIAXXXXXXXXXXX",
"sessionContext": {
"sessionIssuer": {
"type": "Role",
"principalId": "AROAXXXXXXXXXXX",
"arn": "arn:aws:iam::222222222222:role/SwitchTestRole",
"accountId": "222222222222",
"userName": "SwitchTestRole"
}
}
},
"sessionCredentialFromConsole": "true" // コンソールから実行されたこと示す
}
続いては user-b 側を見てみます。
{
"eventName": "CreateKeyPair",
"userIdentity": {
"type": "AssumedRole",
"principalId": "AROAYYYYYYYYYYY:user-b",
"arn": "arn:aws:sts::222222222222:assumed-role/SwitchTestRole/user-b",
"accountId": "222222222222",
"accessKeyId": "ASIAYYYYYYYYYYY",
"sessionContext": {
"sessionIssuer": {
"type": "Role",
"principalId": "AROAYYYYYYYYYYY",
"arn": "arn:aws:iam::222222222222:role/SwitchTestRole",
"accountId": "222222222222",
"userName": "SwitchTestRole"
}
}
},
"sessionCredentialFromConsole": "true" // コンソールから実行されたこと示す
}
ちなみに、CloudTrail の各ログ画面からは「ユーザー名」欄があるため、マネジメントコンソールからの操作の場合は「user-a」と「user-b」どちらのユーザー(正しくはセッション名ですが)が操作したのかがすぐにわかります。

関連するフィールドは下記の通りです。
| フィールド | 分かること |
|---|---|
principalId |
プリンシパル ID + セッション名 |
sessionContext.sessionIssuer |
元の IAM ユーザー情報はなく、ロールの情報のみ |
つまり、CloudTrail ログを確認しても元の IAM ユーザー名を直接示すフィールドはなく、principalId に記載された セッション名だけが手がかり になります。
コンソール経由であれば「セッション名 = ユーザー名」となるため、user-a や user-b の操作だと読み取れます。
CLI 経由の場合
それでは、CLI からの操作を行った場合はどうでしょうか・・・?
実は CLI 経由の場合はセッション名を自由に設定することができるため、元のユーザー名を偽装できるようになってしまいます。
実際にセッション名を設定して確認してみます。
1. CLI から AssumeRole する
では、user-a が user-b を名乗って AssumeRole してみます。
# 現在のプロファイルを確認(user-a でログインしている状態)
aws sts get-caller-identity
{
"UserId": "AIDAxxxxxxxxxxxxxxxxx",
"Account": "111111111111",
"Arn": "arn:aws:iam::111111111111:user/user-a"
}
# role-session-name を user-b に設定して AssumeRole
aws sts assume-role \
--role-arn arn:aws:iam::222222222222:role/SwitchTestRole \
--role-session-name user-b
# AssumeRole 後のプロファイルを確認
aws sts get-caller-identity
{
"UserId": "AROAyyyyyyyyyyyyy:user-b",
"Account": "222222222222",
"Arn": "arn:aws:sts::222222222222:assumed-role/SwitchTestRole/user-b"
}
この時点で、プロファイルを見るだけだとまるで user-b が操作したかのように見えますね。
とりあえず、EC2 キーペアも作成しておきます。
aws ec2 create-key-pair \
--key-name honto-ha-user-a-dayo \
--query 'KeyMaterial'
2. CloudTrail のログを確認
では、CreateKeyPair の CloudTrail のログを確認してみます。
{
"eventName": "CreateKeyPair",
"userIdentity": {
"type": "AssumedRole",
"principalId": "AROAyyyyyyyyyyyyy:user-b",
"arn": "arn:aws:sts::222222222222:assumed-role/SwitchTestRole/user-b",
"accountId": "222222222222",
"accessKeyId": "ASIAzzzzzzzzzzzzz",
"sessionContext": {
"sessionIssuer": {
"type": "Role",
"principalId": "AROAyyyyyyyyyyyyy",
"arn": "arn:aws:iam::222222222222:role/SwitchTestRole",
"accountId": "222222222222",
"userName": "SwitchTestRole"
}
}
}
}
この情報だけでは完全に user-b が行ったイベントに見えてしまいますね・・・。
当然、コンソール上のユーザー名も user-b になってしまっています。

マネジメントコンソールのように上辺だけでは判別できません。
3. 偽装を特定する
では、どうすれば user-a が user-b を名乗った AssumeRole だと判別できるのでしょうか?
ポイントは aws sts assume-role 時に発行される一時クレデンシャルの accessKeyId です。
さきほどの CloudTrail ログを確認すると accessKeyId が ASIAzzzzzzzzzzzzz となっていますが、一旦こちらを記録しておきます。
次に、CloudTrail ログから CLI 経由で AssumeRole した時のイベントを探します。
{
"userIdentity": {
"type": "AWSAccount",
"principalId": "AIDAxxxxxxxxxxxxxxxxx",
"accountId": "111111111111"
},
"eventSource": "sts.amazonaws.com",
"eventName": "AssumeRole",
"requestParameters": {
"roleArn": "arn:aws:iam::222222222222:role/SwitchTestRole",
"roleSessionName": "user-b"
},
"responseElements": {
"credentials": {
"accessKeyId": "ASIAzzzzzzzzzzzzz",
"sessionToken": "~~~~~~~~~~~~~~~",
"expiration": "2026-07-14T13:33:01Z"
},
"assumedRoleUser": {
"assumedRoleId": "AROAyyyyyyyyyyyyy:user-b",
"arn": "arn:aws:sts::222222222222:assumed-role/SwitchTestRole/user-b"
}
}
}
あまり関係のない箇所は省略してますが、responseElements.credentials.accessKeyId を見ると、さきほど記録した ASIAzzzzzzzzzzzzz と一致することがわかります。
また、requestParameters.roleSessionName が user-b となっていることから、AssumeRole 時にセッション名が意図的に設定されていることもわかります。
ここまでわかればあとは大元を特定するだけです。
改めて userIdentity フィールドを確認すると、以下のことがわかります。
| フィールド | 分かること |
|---|---|
type |
AWS アカウント |
arn |
IAM ユーザーの識別子(AIDA から始まるものは IAM ユーザーを指す 参考) |
accountId |
アカウント ID(AssumeRole の実行元) |
とくに principalId と accountId に注目してほしいのですが「1. CLI から AssumeRole する」のときに確認した UserId が principalId と一致しています。
# 現在のプロファイルを確認(user-a でログインしている状態)
aws sts get-caller-identity
{
"UserId": "AIDAxxxxxxxxxxxxxxxxx",
"Account": "111111111111",
"Arn": "arn:aws:iam::111111111111:user/user-a"
}
これで user-a が user-b を名乗って AssumeRole したことが判明しました。
実行されたアクションの数が多いと判別も大変になるので、その場合は Athena を使って CloudTrail ログを JOIN するのがいいと思います。
分かったこと
検証結果を整理するとこうなります。
| 確認対象 | 元ユーザーの記録 | 判別可否 |
|---|---|---|
| コンソール経由 | セッション名 = ユーザー名(自動設定) | ○ |
| CLI 経由 | セッション名は変更可能 | △ ※偽装可能 |
仕組みがわかった上で、これらに対して対策を行う場合(確実に判別したい)は以下の 2 つが有効です。
sts:RoleSessionName で信頼ポリシーでセッション名を強制する
sts:RoleSessionName 条件を使うと、セッション名が自分の IAM ユーザー名と一致しない AssumeRole を拒否できます。
{
"Condition": {
"StringEquals": {
"sts:RoleSessionName": "${aws:username}"
}
}
}
sts:SourceIdentity でソースアイデンティティを強制する
AssumeRole 時に設定するとセッション中は変更不可で、ロールチェーンをまたいでも引き継がれ、全操作イベントの sourceIdentity フィールドに記録されます。
監査要件が厳しい環境ではこちらが有力です。
まとめ
CloudTrail のログを実際に読み解きながら、AssumeRole 後の操作が誰のものか判別できるかを検証してみました。
意外と細かなところまで見る機会がなかったので勉強になりました。
本件の内容がどなたかの役立てば嬉しいです!







