🔐

[AWS]スイッチロールを色々な方法で試してみた

2022/01/12に公開

スイッチロールとは?

アカウントAのIAMユーザーでアカウントBの権限を利用することができる機能です。
正確には、アカウントBのIAMロールの認可を利用することが出来る機能で、IAMロールを切り替えることから「スイッチロール」と呼ばれています。

ユースケースとしては、複数のAWSアカウントのIDとパスワードを管理することを避けたいときなどに使います。
例えば、5つの案件を並行して作業しており、本番用と検証用で10コのAWSアカウントを使用していたとします。その際にそれぞれのIDとパスワードを管理するのではなく、アカウント管理用のAWSアカウントを1つ作成し、そのAWSアカウントからスイッチロールして他アカウントのリソースを使うようにします。

スイッチロールの説明画像

AWS マネジメントコンソールで設定する方法

https://dev.classmethod.jp/articles/iam-switchrole-for-beginner/#toc-2
こちらのクラスメソッドさんの記事を参考に設定しました。

手順:

  1. スイッチ先のアカウントで引き渡すIAMロールを作成する。
  2. スイッチ元のアカウントでIAMロールを引き受けることが出来るポリシーを作成する。

ポリシー:

{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "sts:AssumeRole",
        "Resource": "arn:aws:iam::<スイッチ先のAWSアカウントID>:role/<1で作成したロール名>"
    }
}

以上を行うことで、スイッチ元のマネジメントコンソール右上のユーザーメニューより、ロールの切り替えが行えるようになりました。
ロールの切り替え画面
アカウント: スイッチ先のアカウントID
ロール: スイッチ先の引き渡すロール名
表示名: 何でも良い(任意で設定すると次にスイッチロールする際に分かりやすくなる)

疑問点1: この状態でスイッチ元のIAMポリシーを削除するとどうなる?

スイッチロールしてスイッチ先のマネジメントコンソールを触れるようになりました。この後、スイッチバックすると、スイッチ元のIAMユーザーに戻ることが出来ました。

クロスアカウント2

スイッチ元ではユーザーメニューから、常にスイッチアカウントの設定が表示されています。
この状態でIAMポリシーを削除するとどうなるでしょうか?

結果、スイッチロールが出来てしまいました。
となると、IAMポリシーの設定は不要ということになります。
恐らく、元記事の方は「信頼関係ポリシー」を作る手順を書きたかったのですが、誤って「アイデンティティベースポリシー(一般的にIAMポリシー)」を作ってしまったものを思われます。
信頼関係ポリシーに関しては、マネジメントコンソールからロールを作成した際に、スイッチ元のアカウントIDを入力したことで自動で作られているため、別で作る必要は無さそうです。

疑問点2: この状態でスイッチ先のIAMロールを削除すると当然スイッチロールが失敗する?

IAMポリシーはどうやら必要なさそうです。
スイッチ先のIAMロールを削除したらスイッチロールが失敗するはず(そうじゃないと困る)ですが、こちらも試してみました。

結果、スイッチロールが失敗しました。

結論、一度スイッチロールを許可したアカウントからのアクセスを拒否したい場合や権限を変えたいときは、スイッチ先のIAMロールを修正すれば良さそうです。

AWS CLIで設定する

AWS CLIを利用する際にも、以下の手順でスイッチ元のIAMユーザーからスイッチ先のアカウントにアクセスできるようになりました。

手順

  1. スイッチ先のアカウントで引き渡すIAMロールを作成する
  2. aws configure にてスイッチ元のIAMユーザーを設定
  3. AssumeRoleを実行
aws sts assume-role \
 --role-arn "arn:aws:iam::200000000000:role/CrossAccountReadOnly" \
 --role-session-name FromSession
 
 // 結果 -> Credentialsが返ってくる
 {
    "Credentials": {
        "AccessKeyId": "ABCDEFGHIJKMNL",
        "SecretAccessKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "SessionToken": "xxxxxxxxxxxxxxxxxxxxxxxx~~~~~~~~~~~~~~~xxxxxxx",
        "Expiration": "2022-01-09T14:42:00Z"
    },
    "AssumedRoleUser": {
        "AssumedRoleId": "ABCDEFGHIJKMNL:FromSession",
        "Arn": "arn:aws:sts::0000000000:assumed-role/CrossAccountReadOnly/FromSession"
    }
}
  1. 認証情報を環境変数にセットする
export AWS_ACCESS_KEY_ID=ABCDEFGHIJKMNL
export AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
export AWS_SESSION_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxx~~~~~~~~~~~~~~~xxxxxxx
  1. スイッチ先のアカウントのリソースが見れるか確認する
aws s3 ls // s3のバケット一覧を表示するコマンド

//結果 -> スイッチ先のバケット一覧が返ってくる
account-to-bucket-1
  1. 環境変数を削除する
unset AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN
  1. 再度スイッチ先のアカウントのリソースが見れるか確認する
aws s3 ls // s3のバケット一覧を表示するコマンド

//結果 -> スイッチ元のバケット一覧が返ってくる
account-from-bucket-1
account-from-bucket-2

二段階認証に関する注意点

スイッチ先のロールを二段階認証を二段階認証必須にしている場合、別のオプションが必要となります。マネジメントコンソール上では、以下のようにチェックを入れると二段階認証を必須にできます。
CLIでのクロスアカウント

二段階認証を必須にする場合は、以下のオプションをassume-role時に追加しましょう。

--serial-number 
--token-code

こちらの記事を参考にしました。
https://dev.classmethod.jp/articles/aws-cli-iam-sts-cross-account/#fn-155260-1

AWS SDKで設定する

以下のPythonプログラムを実行し、スイッチロールできることを確認しました。

import boto3
from boto3 import Session

client = boto3.client('sts')
response = client.assume_role(
    RoleArn="arn:aws:iam::123456789123:role/CrossAccountReadOnly",
    RoleSessionName="crossAccountSession"
)

credentials = response['Credentials']
session = Session(
    aws_access_key_id=credentials['AccessKeyId'],
    aws_secret_access_key=credentials['SecretAccessKey'],
    aws_session_token=credentials['SessionToken'],
    region_name='ap-northeast-1'
)
s3 = session.client('s3')
buckets = s3.list_buckets()
print(buckets)

Discussion