【AWS】クロスアカウントアクセスでCloudWatchにアクセスしてみた
この記事は アイソルート Advent Calendar 2022 20日目の記事です。
こんにちは。クラウドソリューショングループのshimizuyです。
「AWSアカウント間でCloudWatchのリソースを参照したい」という要望からクロスアカウントアクセスを設定する機会があり、その際に結構つまづいてしまったので備忘録もかねて具体的な手順を記事に残すことにしました。
目次
- クロスアカウントアクセスとは
- 構成について
- 事前準備
- スイッチ先でIAMロールを作成する
- スイッチ元でIAMポリシーを作成する
- スイッチ元のEC2にIAMポリシーを追加する
- EC2にクロスアカウントアクセス用の設定を追加する
- おわりに
クロスアカウントアクセスとは
クロスアカウントアクセスとは、簡単に言うと「複数のAWSアカウントをまたいだアクセス手段」を指します。
例えば、開発・本番などで環境を分けている場合に
「アカウントAからアカウントBのCloudWatch情報を取得したい!」
「アカウントAからアカウントBにあるS3バケットにアクセスしたい!」
といったケースで利用される手段になります。
今回はクロスアカウントアクセスでアカウントAのEC2からアカウントBのIAMロールにスイッチしてCloudWatchのログイベントを取得する方法について解説します。
構成について
今回のユースケースにおける構成は以下の通りです。
なお前提条件として、アカウントAのSSM Agent、AWS CLIが利用可能なEC2インスタンスと、アカウントBのCloudWatchにはすでに取得対象となるログイベントが作成・生成済みの想定で話を進めます。
また、アカウントIDはそれぞれ[アカウントA: 111111111111]、[アカウントB: 999999999999]とします。
作業の簡単な流れとしては、
- アカウントA(スイッチ元)のEC2で利用するIAMロールをアカウントB(スイッチ先)で作成
- アカウントB上のIAMロールを引き受けるためのIAMポリシーをアカウントAで作成
- アカウントA上のEC2にアタッチしたIAMロールに2で作成したポリシーを追加する
- アカウントAのEC2でクロスアカウント用の設定をする
- EC2上でスイッチロールしてアカウントBのCloudWatchのイベントログを取得
となります。
それではさっそく構築に入っていきましょう!
事前準備
スイッチ先でIAMロールを作成する際、スイッチ元のアカウントIDを入力する必要があるため、事前にスイッチ元のアカウントAのIDを控えておく必要があります。
1. ドロップダウンメニューを開く
AWSコンソールにログイン後、画面上部にあるアカウント名をクリックし、ドロップダウンメニューを開きます。
2. アカウントIDを取得する
赤枠右側のコピーマークを選択し、スイッチ元(アカウントA)のアカウントIDを控えることができたらスイッチ先(アカウントB)の操作に進みます。
スイッチ先でIAMロールを作成する
まずはアカウントB(スイッチ先)で、アカウントA(スイッチ元)に受け渡すIAMロールを作成します。
1. アカウントBでIAMを開き[ロールを作成]をクリック
2. 信頼対象を指定する
信頼されたエンティティタイプを[カスタム信頼ポリシー]と選択し、下記の通りJSONを記述したら、画面下部の[次へ]をクリックする。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<アカウントA(スイッチ元)のAWSアカウントID>:root" }, "Action": "sts:AssumeRole", "Condition": {} } ] }
3. アクセス権限ポリシーを指定する
ここで必要な権限(ポリシー)をロールにアタッチしていきます。
今回の場合は[CloudWatchLogsReadOnlyAccess]と[CloudWatchReadOnlyAccess]をアタッチします。
4. ロール名を入力する
今回は「cross-account」という名前にしました。
名前や説明欄、必要に応じてタグを入力し、画面下部の[ロールを作成]をクリックするとロールが作成されます。
スイッチ元でIAMポリシーを作成する
次に、先ほどアカウントB(スイッチ先)で作成したIAMロールアカウントを引き受けることができるIAMポリシーをアカウントA(スイッチ元)に作成します。
1. アカウントAでIAMを開き[ポリシーを作成]をクリック
2. JSONタブを開きポリシーを設定する
JSONタブを選択し、下記の通りJSONを記述したら画面下部の[次のステップ:タグ]をクリックします。
{ "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Action": "sts:AssumeRole", "Resource": "arn:aws:iam::<アカウントB(スイッチ先)のAWSアカウントID>:role/cross-account" } }
3. タグを追加する(任意)
今回はタグを追加しませんでしたが、必要に応じて追加してください。
確認が終わったら画面下部の[次のステップ:確認]をクリックします。
4. ポリシー名を入力する
今回は「cross-account-monitor」という名前にしました。
名前や必要に応じて説明欄を入力し、画面下部の[ポリシーの作成]をクリックするとポリシーが作成されます。
スイッチ元のEC2にIAMポリシーを追加する
今回はアカウントA(スイッチ元)のEC2でスイッチロールをした上でアカウントB(スイッチ先)のCloudWatch Logsへアクセスするため、EC2にアタッチされたIAMロールに先ほど作成したIAMポリシーを追加します。
1. アカウントAでEC2にアタッチされたIAMロールを開く
今回はEC2にアタッチしたIAMロールを「monitor-iam-ec2」と仮定して選択します。
2. [ポリシーをアタッチ]をクリックする
[許可を追加]をクリックし、ドロップダウンメニューから[ポリシーをアタッチ]をクリックします。
3. 作成したポリシーをアタッチする
先ほど作成したポリシーの「cross-account-monitor」を選択したら[アクション]をクリックし、ドロップダウンメニューから[アタッチ]をクリックします。
これによってアカウントAのEC2内部でアカウントBの「cross-account」ロールにスイッチロールすることが可能になります。
EC2にクロスアカウントアクセス用の設定を追加する
1. プロファイルの設定
EC2にSSM接続し下記コマンドでスイッチロールに必要なプロファイルを設定します。
$ sudo vim ~/.aws/config [profile <プロファイル名>] role_arn = arn:aws:iam::<アカウントB(スイッチ先)のAWSアカウントID>:role/<アカウントB(スイッチ先)に作成したIAMロール名> credential_source=Ec2InstanceMetadata
スイッチロール前のプロファイルの確認については下記コマンドで可能です。
$ aws sts get-caller-identity
スイッチロール後のプロファイルの確認については下記コマンドで可能です。
$ aws sts get-caller-identity --profile <プロファイル名>
2. CloudWatch Logsへのアクセス確認
アカウントB(スイッチ先)内のロググループにアクセスしてみます。
$ aws logs get-log-events --log-group-name <ロググループ名> --log-stream-name <ログストリーム名> --profile <プロファイル名>
正しくアクセスできれば下記のような形式で表示されます。(あくまでも例です)
{ "events": [ { "timestamp": 1608*********, "message": "ERROR: test1", "ingestionTime": ******* }, { "timestamp": 1608*********, "message": "PASS: test1", "ingestionTime": ******* } ], "nextForwardToken": "f/1234567890***********************************************", "nextBackwardToken": "b/1234567890***********************************************" }
おわりに
個人的な感想としてはクロスアカウントアクセスは複雑なだけになかなかのくせ者ですね…。
しかし使いこなせればそれだけAWSの活用の幅が広がることも間違いないと思いますので、機会があれば積極的にチャレンジしてみるのもいいかもしれません!