92605
現在、AWSアクセス用のC#アプリの制作をしていますが、Roleの切り替えで行き詰っています。  
AWSの公式情報や言語違いも含めて色々なサイトを調べたのですが、MFAと併用しているものが見受けられず、失敗する原因を把握できていません。  
根本の理解が不足しており恐縮ですが、実施方法についてご存じの方がいらっしゃいましたらご教示お願いします。

### 現状

#### 出来ている事

  * AWSアカウントを複数所持しており、内一つがRoleを利用している。
  * AWSのアクセスには全てのアカウントでMFAを利用している。
  * 使用したいRoleにはExternalIdは設定されていない。
  * Roleを利用しないアカウントでの認証は成功しており、S3のアクセスが確認できている。
  * CLIを利用したサービスでは、Roleを指定して実行が出来ている。

#### 出来ていない事,できない原因として想定している内容

  * 調べた結果、AssumeRoleRequestの関数を利用すると考えているが、どのタイミングで使用すれば正しいか分からない。
  * 記載場所が違う（MFA認証前など）
  * メッセージの内容を見る限り、MFA認証したユーザーをルートユーザーとしてRoleを切り替え出来ていないのではないか
  * CLIで利用しているように --profile test のような形で、S3の関数を実行中に毎回指定してやる必要があるかもしれない

* * *

以下がコード等の情報になります。一部コードを省略(:)して、機密情報は書き換えています。

AWSの情報

AWS Account

```

    RootUserID = 9876-5432-1098
    RootUserName = testuser@xxxx.com
    
    RoleUserID = 0123-4567-8901
    RoleUserName = Test_Role_User
    
```

信頼されたエンティティ

```

    {
      "version":2012-10-17
      "Statement" : [
        {
          "Effect" : "Allow"
          "Principal" : {
             "AWS": "arn:aws:iam::987654321098:root"
           },
          "Action":"sts:AssumeRole",
          "Condition":{}
        }
      ]
    }
    
```

ローカルファイル ※CLIで利用できている。

```

    <.aws\credentials>
    [default]
    aws_access_key_id=ABCDEGHOJKLM
    aws_secret_access_key=11AA22bb33CC44dd
    region=ap-northeast-1
    
    <.aws\config>
    [default]
    region = ap-northeast-1
    output = json
    
    [profile test]
    role_arn = arn:aws:iam::012345678901:role/Test_Role_User
    source_profile=default
    region = ap-northeast-1
    
```

コード C#

```

    //AWSSDK.Core version3.3.0.0 Runtimeversionv4.0.30319
    //AWSSDK.S3 version3.3.0.0 Runtimeversionv4.0.30319
    //AWSSDK.SequrityToken version3.3.0.0 Runtimeversionv4.0.30319
    //.netframework4.6.2
    :
    using Amazon;
    using Amazon.Runtime.CredentialManagement;
    using Amazon.Runtime;
    using Amazon.S3;
    using Amazon.S3.Model;
    using Amazon.S3.Transfar;
    using Amazon.S3.IO
    
    namespace AWSTool
    {
     public class AWSAccess{
      
       public static async Task AWSAuth()
       {
         var credOption = new CredentialProfileOption();
         var credentailsFile = new SharedCredentialsFile();
         credOption.AccessKey = "ABCDEGHOJKLM";
         credOptionSecretKey = "11AA22bb33CC44dd";
         var profile = new CredentialProfile("default",credOption);
         progile.Region = RegionEndpoint.GetBySystemName("ap-northeast-1");
         credentialsFile.RegisterProfile(profile);
         if(credentialsFile.TryGetProfile("default",out profile) == false)
            Console.WriteLine("プロファイル名が見つかりません")
         
         AWSCredentials awsCredentials = null;
         if(AWSCredentialsFactory.TryGetAWSCredentials(profile,credentialsFile,out awsCredentials) == 
     false)
            Console.WriteLine("認証情報生成に失敗しました")
    
    　　　string Token = "XXXXXX" //別のライブラリで生成されるTokenコード
          var stsClient = new AmazonSecurityTokenServiceClient();
          var getSessionRequest = new GetSessionTokenRequest();
          getSessionRequest.DurationSecounds = 3600;
          getSessionRequest.SerialNumber = "arn:aws:iam::987654321098:mfa/testuser@xxxx.com"
          getSessionRequest.TokenCode = "XXXXXX"
          GetSessionTokenResponse getSessionTolenResponse = stsClient.GetSessionToken(getSessionTokenRequest);
          
          string tempAccessKeyId = getSessionTokenResponse.Credentails.AccessKeyId;
          string tempSessionAccessKey = GetSessionTokenResponse.Credentails.SecretAccessKey;
          string tempSessionToken = getSessionTokenResponse.Credentails.SessionToken;
          SessionAWSCredentials tempCredentials = new SessionAWSCredentials(tempAccessKeyId,tempSessionAccessKey,tempSessionToken)
          
          //AsumeRoleをMFA認証後に実施　ここから
            AssumeRoleRequest assumeRoleRequest = new AssumeRoleRequest()
            {
               DurationSecounds = 1600,
               RoleArn = "arn:aws:iam::012345678901:role/Test_Role_User",
               RoleSessionName = "TestSession"
            }
            var RoleResponse = await stsClient.AssumeRoleAsync(AssumeRoleRequest);
            //↑ここで失敗して以下メッセージ
    　　　　//User:arn:aws:iam::987654321098:user/testuser@xxxx.com is not authorized to perform: sts:AssumeRole on resource arn:aws:iam::012345678901::role/Test_Role_User
            
          //ここまで
          
          var AWSS3client = new AmazonS3Client(tempCredentials);
          AWSS3GetBucketList(AWSS3client); //別の関数でS3のバケット一覧を取得
    
       }
     :
     }
    }
    
```
CC BY-SA 4.0
2022-12-01T10:31:34.080
92524
2022-12-06T15:42:42.817
2022-12-01T12:27:15.693
3060
55718
question
c# aws-sdk
C# で AWS SDK を利用して Role を切り替える方法
まず、以下の違いを整理するのがいいのでは無いかと思います。  
・AWS アカウントのrootアカウント  
・各 AWS アカウント内の IAM ユーザ  
・各 AWS アカウントの IAM ロール

その上で、「誰が」「どのロールに」スイッチロール (Assume Role) しようとしているかですね。

AWS アカウント「9876-5432-1098」の root アカウントで、  
AWS アカウント「012345678901」の IAM
ロール「Test_Role_User」にスイッチロールしようと意図されていると理解しましたが、正しいでしょうか？

それを前提として。

> User:arn:aws:iam::987654321098:user/testuser@xxxx.com is not authorized to
> perform: sts:AssumeRole on resource
> arn:aws:iam::012345678901::role/Test_Role_User

というエラーメッセージからすると呼び出し元として認証は成功しているが、AssumeRoleする権限が無いと読めます。

呼び出し元が「user」となっているため、まず操作しようとしているのは root アカウントではなく、「testuser@xxxx.com」という IAM
ユーザで操作しているようです。「testuser@xxxx.com」という IAM
ユーザを作成されているのでは無いでしょうか？また、指定されているアクセスキー、シークレットアクセスキーはその IAM ユーザのものでは無いでしょうか？

root アカウントは全権限を持っていますが、IAM
ユーザは明示的に設定した権限しか持っていません。そのため、権限が無いというエラーになっていると思われます。

root アカウントにアクセスキー、シークレットアクセスキーを割り当てることは推奨されていないため、root アカウントで API
呼び出しするのではなく、IAM ユーザで操作する前提に変えるのがいいと思います。そうするのであれば、IAM ユーザに IAM ポリシーで Assume
Role する権限を付与すれば問題は解決できると思われます。以下のドキュメントにポリシーは説明されています。  
<https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_roles_use_permissions-
to-switch.html>

あと、MFA についても設定状況などを整理した方がいいと思います。root アカウントに MFA を設定しているのか、IAM ユーザに MFA
を設定しているのか、その両方なのか。root アカウントや IAM ユーザに MFA が割り当てられていても、通常 MFA
のワンタイムコードの指定が必要なのは、AWS コンソールにログインする場合だけで、アクセスキー、シークレットアクセスキーで操作する際は MFA
は求められません。例外は以下のドキュメントにあるように、IAM ユーザに対して、IAM ポリシーで権限を付与する際に condition で MFA
の利用が必須と指定した場合とかです。  
<https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_credentials_mfa_configure-
api-require.html#MFAProtectedAPI-user-mfa>

恐らくそのような IAM ポリシーには設定されていないと思うので、アクセスキー、シークレットアクセスキーでの API 呼び出しに MFA
は不要です。（もしかしたら、そのような IAM ポリシーを設定されていて適切に MFA
のワンタイムコードを渡せておらず、権限不足のエラーになっているという可能性もありますが、きっとそうでは無いかと。）

MFA のワンタイムコードは定期的に変わりますので、C#
コードの中に入れるのは現実的ではありませんし、引数などにして変えられるようにしたとしても、自動処理をするためにコードにしているのにもかかわらず、MFA
を使うというのも適していません。実行環境をセキュアにする、EC2 ロールなどを利用するなどの他の方法で全体としてセキュアにするのがいいと思います。

あと、コードの中にアクセスキー、シークレットキーを記載することは避けられた方がいいです。ソースコードレポジトリなど何かの際にキーを流出させてしまう事が少なくありません。そもそもは設定ファイルのプロファイル読み込みが適切に行えていれば、キーをコードで指定する必要もないはずです。
CC BY-SA 4.0
2022-12-06T15:42:42.817
92605
2022-12-06T15:42:42.817
5959
92524
answer