AWS Tools for PowerShellでEC2に割り当てたIAMロールからスイッチロールしてみた

2023.05.21

しばたです。

DevelopersIOではAWS CLIを使ったEC2 IAMロールからのスイッチ手順を解説した記事は存在しているのですが、AWS Tools for PowerShellを使った場合の手順に関する記事が無かったので本記事で解説することにしました。

はじめに結論から

AWS Tools for PowerShellではAWS CLIと同様に共有認証情報ファイル (~/.aws/credentialsおよび~/.aws/config) が使用可能で一部の設定をAWS CLIと共用することができます。

スイッチロールに関する設定も共用可能で、AWS Tools for PowerShellにおいてもAWS CLIと同じ設定でEC2 IAMロールからのスイッチロールが可能です。

試してみた

というわけで実際にスイッチロールできるか確認していきます。

検証環境

今回は2つのAWSアカウントを用意し、アカウントA(111111111111)に用意したEC2のIAMロールを起点にアカウントB(222222222222)へスイッチロールします。

アカウントBのIAMロールにはS3へのアクセス権を与えておき、S3のアクセスを試行してスイッチロールの結果を確認していきます。

1. アカウントAの前準備

まずはアカウントAにVPCおよびWindows Server 2022 EC2を1台用意しておきます。

このEC2には予め用意したEC2RoleforSSMという名前のIAMロールをアタッチします。
EC2RoleforSSMはシンプルにSSMで接続するためのAmazonSSMManagedInstanceCoreとアカウントBにスイッチロール可能にするための権限だけ与えています。

2. アカウントBの前準備

アカウントBにはスイッチ先のTest-Switch-Roleと言う名前のIAMロールを用意しておきます。
ロールの定義は以下の通りで、アカウントAのEC2RoleforSSMからのスイッチを許可しAmazonS3ReadOnlyAccessを与えるものとなります。

CloudFormationテンプレート定義

AWSTemplateFormatVersion: 2010-09-09
Parameters:
  SourceRoleArn:
    Description: "Input switch role source ARN."
    Type: String
    Default: "arn:aws:iam::111111111111:role/EC2RoleforSSM"
Resources:
  TestRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: "Test-Switch-Role"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              AWS:
                - Fn::Sub: "${SourceRoleArn}"
            Action:
              - "sts:AssumeRole"
      Path: "/"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"

上記テンプレートを適用した結果はこんな感じです。

また、適当なS3バケットも用意しておきます。
今回はアカウントBのCloudTrail用に作っていたxxxxxxxx-cloudtrailバケットを動作確認に使います。

3. 共有認証情報ファイルの設定

ここからスイッチロールのための作業に入ります。

最初にAWS CLIの場合と同様に~/.aws/configに以下の様なプロファイル設定を追記します。
プロファイル名をswitch_testとしていますが任意の名称で構いません。

~/.aws/config

[profile switch_test]
role_arn = arn:aws:iam::222222222222:role/Test-Switch-Role
credential_source = Ec2InstanceMetadata

このswitch_testプロファイルはEC2インスタンスメタデータをソースにしてアカウントBのTest-Switch-Roleにスイッチします。

今回~/.aws/credentialsは使わないため未設定(未作成)です。
環境に応じて必要となる場合は適宜用意してください。

4. 動作確認 : スイッチ前

次にスイッチ前の状態を確認します。
今回はEC2にインストール済みのAWS Tools for PowerShell (Ver.4.1.323)で動作確認します。

# バージョン確認
PS C:\> Get-AWSPowerShellVersion

AWS Tools for Windows PowerShell
Version 4.1.323
Copyright 2012-2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.

# ・・・後略・・・

Get-STSCallerIdentityコマンドで実行者情報を確認すると以下の様にアカウントAのEC2RoleforSSMであることが分かります。

PS C:\> Get-STSCallerIdentity | Format-List


LoggedAt         : 2023/05/21 5:58:13
Account          : 111111111111
Arn              : arn:aws:sts::111111111111:assumed-role/EC2RoleforSSM/i-0d176f4a5f9738429
UserId           : AROAXXXXXXXXXXXXXXXXX:i-0d176f4a5f9738429
ResponseMetadata : Amazon.Runtime.ResponseMetadata
ContentLength    : 458
HttpStatusCode   : OK

当然ですがこのロールではS3へのアクセス権はありません。

# S3へのアクセスは権限エラーとなる
PS C:\> Get-S3Bucket -BucketName xxxxxxxx-cloudtrail
Get-S3Bucket : Access Denied
発生場所 行:1 文字:1
+ Get-S3Bucket -BucketName xxxxxxxx-cloudtrail
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (Amazon.PowerShe...tS3BucketCmdlet:GetS3BucketCmdlet) [Get-S3Bucket]、InvalidOperationException
    + FullyQualifiedErrorId : Amazon.S3.AmazonS3Exception,Amazon.PowerShell.Cmdlets.S3.GetS3BucketCmdlet

5. 動作確認 : スイッチ後

続けて-ProfileNameパラメーターを指定してアカウントBのロールにスイッチしてみます。
結果は以下の様になりアカウントBのTest-Switch-Roleにスイッチできていることが分かります。

# アカウントBへスイッチ
PS C:\> Get-STSCallerIdentity -ProfileName switch_test | Format-List


LoggedAt         : 2023/05/21 6:02:11
Account          : 222222222222
Arn              : arn:aws:sts::222222222222:assumed-role/Test-Switch-Role/aws-dotnet-sdk-session-638202457306840525
UserId           : AROAXXXXXXXXXXXXXXXXX:aws-dotnet-sdk-session-638202457306840525
ResponseMetadata : Amazon.Runtime.ResponseMetadata
ContentLength    : 505
HttpStatusCode   : OK

この状態であればS3へのアクセスも問題無く可能です。

# S3の情報を問題無く取得
PS C:\> Get-S3Bucket -BucketName xxxxxxxx-cloudtrail -ProfileName switch_test

CreationDate        BucketName
------------        ----------
2022/09/23 12:18:53 xxxxxxxx-cloudtrail

もちろんSet-AWSCredentialコマンドを使いデフォルトプロファイルを切り替えても問題ありません。

# デフォルトプロファイルを変更
PS C:\> Set-AWSCredential -ProfileName switch_test
# 結果確認
PS C:\> Get-STSCallerIdentity | Format-List


LoggedAt         : 2023/05/21 6:07:18
Account          : 222222222222
Arn              : arn:aws:sts::222222222222:assumed-role/Test-Switch-Role/aws-dotnet-sdk-session-638202460215428142
UserId           : AROAXXXXXXXXXXXXXXXXX:aws-dotnet-sdk-session-638202460215428142
ResponseMetadata : Amazon.Runtime.ResponseMetadata
ContentLength    : 505
HttpStatusCode   : OK

以上で動作確認は終了です。

余談 : AWS SDKストアを使う場合

AWS Tools for PowerShellではAWS SDK for .NET由来の独自の認証情報(AWS SDKストア)が使えます。

AWS SDKストアを使う場合Set-AWSCredentialコマンドでプロファイルを追加でき、スイッチロールをする場合は-SourceProfile-RoleArnパラメーターを指定する必要があります。
ただ、残念ながらEC2インスタンスメタデータを表す特別なプロファイル指定は無く以下の様な指定はできません。

# こういうコマンド一発で実現できれば理想なのだが、残念ながら存在しない模様
Set-AWSCredential -StoreAs switch_test_net -SourceProfile "インスタンスメタデータ" -RoleArn arn:aws:iam::222222222222:role/Test-Switch-Role

このためインスタンスメタデータから直接アクセスキーとトークンを取得し、一時的なソースプロファイルを用意する必要があります。

# インスタンスメタデータから直接認証情報を取得
$metadata = Invoke-RestMethod -Uri http://169.254.169.254/latest/meta-data/iam/security-credentials/EC2RoleforSSM

# 一時的なソースプロファイル temp_metadata を作成
Set-AWSCredential -StoreAs temp_metadata -AccessKey $metadata.AccessKeyId -SecretKey $metadata.SecretAccessKey -SessionToken $metadata.Token
# 上記 temp_metadata をソースにしてスイッチロール用プロファイル switch_test_net を作成
Set-AWSCredential -StoreAs switch_test_net -SourceProfile temp_metadata -RoleArn arn:aws:iam::222222222222:role/Test-Switch-Role

結果はこんな感じ。

# AWS SDKストアを使う場合 temp_metadata, switch_test_net と2つのプロファイルを用意するしかない
PS C:\> Get-AWSCredential -ListProfileDetail

ProfileName     StoreTypeName         ProfileLocation
-----------     -------------         ---------------
temp_metadata   NetSDKCredentialsFile
switch_test_net NetSDKCredentialsFile

# 各プロファイルの詳細
PS C:\> Get-AWSCredential -ProfileName temp_metadata | Format-List
Amazon.Runtime.SessionAWSCredentials
PS C:\> Get-AWSCredential -ProfileName switch_test_net | Format-List

SourceCredentials : Amazon.Runtime.SessionAWSCredentials
RoleArn           : arn:aws:iam::222222222222:role/Test-Switch-Role
RoleSessionName   : aws-dotnet-sdk-session-638202495331889348
Options           : Amazon.Runtime.AssumeRoleAWSCredentialsOptions
PreemptExpiryTime : 00:05:00

当たり前ですが一時的なソースプロファイルtemp_metadataは時間が経てば有効期限を迎え無効になります。
都度手動で更新しなければならず非常に面倒なので特段の事情が無い限り共有認証情報ファイルを使うほうが良いでしょう。

最後に

以上となります。

AWS Tools for PowerShellでもAWS CLIと同様の手順で楽にスイッチロールできるので是非お試しください。