AWS Step Functionsでタスク毎に別アカウントのロールにAssumeRole(スイッチロール)出来るようになりました!

AWS Step Functionsでタスク毎に別アカウントのロールにAssumeRole(スイッチロール)出来るようになりました!これでリソースベースポリシーがサポートされてない別アカウントのリソースもStep Functionsから直接操作出来るように!
2022.11.19

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

お疲れさまです。とーちです。

最近は AWS re:Invent 2022 の開催が近いせいかすごい数のアップデートが AWS から発表されてますね。
そんなアップデートの中でも個人的にオッと思ったアップデートである AWS Step Functions のクロスアカウントアクセスに関するアップデートをご紹介したいと思います。

かんたんまとめ

  • ステートマシン内のタスク単位で別アカウントのロールに AssumeRole できるようになった
  • リソースベースポリシーをサポートしていない別アカウントのリソースでもステートマシンから呼び出せるようになった

今までのステートマシンでのクロスアカウントアクセスのやり方(リソースベースポリシー方式)

便宜上、この記事では今までの Step Functions でのクロスアカウントアクセスの方法をリソースベースポリシー方式と呼ぶことにします。

前提として以下のような構成があるとします。

今まで、アカウント A のステートマシンからアカウント B の Lambda を呼び出すには以下の方法しかありませんでした。

  1. アカウント B の Lambda のリソースベースポリシーを変更し、アカウント A のリソース(ステートマシンやステートマシンに付与する IAM ロール等)からの Lambda 呼び出しを許可する
  2. アカウント A のステートマシンに付与する IAM ロールにアカウント B の Lambda を呼び出せる権限を付与する
  3. ステートマシンの定義の中でアカウント B の Lambda を呼び出すタスクを定義する

上記の IAM 権限周りも含めて絵にすると以下のような感じです。

上記の通り、呼び出し先アカウントのサービスがリソースベースポリシーをサポートしていることが前提となっています。リソースベースポリシーは全ての AWS サービスでサポートされているわけではないので、例えば別アカウントにある DynamoDB をステートマシンから直接操作することは出来ないようになっていました。

今回のアップデートにより可能となったクロスアカウントアクセスのやり方(スイッチロール方式)

便宜上、この記事ではアップデートにより追加された Step Functions のクロスアカウントアクセスの方法をスイッチロール方式と呼ぶことにします。

今回のアップデートによりステートマシン内のタスク単位で別 IAM ロールへの AssumeRole(スイッチロール)が出来るようになりました。 そのため、以下のようなやり方でも別アカウントのサービスを呼び出せるようになりました。

  1. アカウント B にアカウント B の Lambda を呼び出す権限を持つ IAM ロール(以後 LambdaInvokeRole)を作成する
  2. LambdaInvokeRole の信頼ポリシーにアカウント A のステートマシンのロール(以後 StateMRole)Arn を追加する
  3. StateMRole に LambdaInvokeRole に"sts:AssumeRole"出来るポリシーを追加する
  4. ステートマシンの定義の中でアカウント B の Lambda を呼び出すタスクを定義する。この際、新しく追加されたCredentialsというフィールドを使って、LambdaInvokeRole の Arn を指定する

こちらも同様に絵にするとこんな感じになります。

やってみた

実際にステートマシンからスイッチロール方式でクロスアカウントアクセスを試してみました。 作成する構成は以下の通りです。

ステートマシンのフローはこんな感じにしました。テスト用なので意味のある処理ではないんですが、別アカウントで Lambda を動かした後、DynamoDB テーブルを作成するというフローになっています。 リソースベースポリシーを使えないサービスをステートマシンから動かしてみたくて DynamoDB を入れてみました。

ステートマシンの ASL(Amazon States Language)

ステートマシンの ASL は以下のようになります。

{
  "Comment": "A Hello World example demonstrating various state types of the Amazon States Language",
  "StartAt": "Lambda Invoke",
  "States": {
    "Lambda Invoke": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "OutputPath": "$.Payload",
      "Parameters": {
        "Payload.$": "$",
        "FunctionName": "arn:aws:lambda:ap-northeast-1:<アカウントBのID>:function:hello-world"
      },
      "Credentials": {
        "RoleArn": "arn:aws:iam::<アカウントBのID>:role/LambdaInvokeRole"
      },
      "Next": "CreateTable"
    },
    "CreateTable": {
      "Type": "Task",
      "End": true,
      "Parameters": {
        "AttributeDefinitions": [
          {
            "AttributeName": "Name",
            "AttributeType": "S"
          }
        ],
        "KeySchema": [
          {
            "AttributeName": "Name",
            "KeyType": "HASH"
          }
        ],
        "TableName": "MyData",
        "BillingMode": "PAY_PER_REQUEST"
      },
      "Resource": "arn:aws:states:::aws-sdk:dynamodb:createTable",
      "Credentials": {
        "RoleArn": "arn:aws:iam::<アカウントBのID>:role/DynamoRole"
      }
    }
  }
}

ポイントとしては 13 行目と 38 行目の Credentials という箇所です。このフィールドが今回のアップデートで追加されていまして、タスク毎にそのタスクを実行する権限をもった IAM ロールを指定出来るようになっています。

また、各 IAM ロールの設定は以下の通りとなります。ポイントとなる箇所だけ抜粋してみました。

ステートマシンにつける IAM ロール(StateMRole) 関連

ステートマシンにつける IAM ロールに付与したポリシーは以下の通りです。別アカウントのロールに AssumeRole する権限のみがついています。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": [
                "arn:aws:iam::<アカウントBのID>:role/LambdaInvokeRole",
                "arn:aws:iam::<アカウントBのID>:role/DynamoRole"
            ]
        }
    ]
}

Lambda 実行のための IAM ロール(LambdaInvokeRole) 関連

LambdaInvokeRole は ステートマシンにつけた IAM ロールから AssumeRole した上で使用します。IAM ポリシーとしてはアカウント B 上の Lambda を Invoke する権限のみがついています。

{
    "Version": "2012-10-17",
    "Id": "default",
    "Statement": [
        {
            "Sid": "myid01",
            "Effect": "Allow",
            "Action": "lambda:InvokeFunction",
            "Resource": "arn:aws:lambda:ap-northeast-1:<アカウントBのID>:function:hello-world"
        }
    ]
}

また、信頼ポリシーは以下の通りとなっています。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::<アカウントAのID>:role/service-role/StepFunctions-HelloWorld-role-5bddc095"
            },
            "Action": "sts:AssumeRole",
            "Condition": {
                "StringEquals": {
                    "sts:ExternalId": "arn:aws:states:ap-northeast-1:<アカウントAのID>:stateMachine:HelloWorld"
                }
            }
        }
    ]
}

ここのポイントとしては、Principal としてステートマシンに付与したロールを信頼していることと、追加で、Condition により更に特定のステートマシンからしか AssumeRole 出来ないようになっていることです。
この Condition の記載はステートマシンから別アカウントのサービスを呼び出すという点においては必須ではないのですが、「混乱した代理問題」を回避するために入れることを推奨されています。
「混乱した代理問題」については弊社下記ブログをご参照ください。

DynamoDB テーブル作成のための IAM ロール(DynamoRole) 関連

DynamoRole は ステートマシンにつけた IAM ロールから AssumeRole した上で使用します。IAM ポリシーとしてはアカウント B 上で DynamoDB テーブルを作成できる権限のみがついています。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "dynamodb:CreateTable",
            "Resource": "arn:aws:dynamodb:*:<アカウントBのID>:table/MyData"
        }
    ]
}

DynamoRole の信頼ポリシーは LambdaInvokeRole の信頼ポリシーとまったく同じなので割愛します

実際に動かしてみる

上記の設定で、アカウント A 上のステートマシンを動かしてみました。

ちゃんと動きましたね。別アカウント上で DynamoDB テーブルが作成されたことと Lambda が正常に終了していることも確認できました。
各タスクの結果も以下のように表示されています。別アカウント上の DynamoDB テーブルを作りましたが TableArn もちゃんと出力として返ってきていることが分かります。

どちらのクロスアカウントアクセス方法を使うのがいいのか

ステートマシンから起動する別アカウントのサービスがリソースベースポリシーをサポートしていないものである場合は、スイッチロール方式でいいと思います。
それ以外の場合はどちらが優れているというものでもないので、ケースバイケースかと思います。やりやすい方法でやるのが良いでしょう。

さいごに

AWS Step Functions のクロスアカウントアクセスに関するアップデートのご紹介でした。
Step Functions はどんどん便利になっていて頼もしいですね。今後も使用する場面は増えてきそうな予感なので、 アップデートを見逃さないようにしたいところです。

以上、とーちでした。

参考

AWS Step Functions のクロスアカウント アクセス機能のご紹介 | AWS コンピューティング ブログ

チュートリアル: クロスアカウント AWS リソースへのアクセス - AWS Step Functions