AWS CDK v2.85.0 で AWS Step Functions ステートマシンを ASL JSON から作成可能になりました

2023.06.22

こんにちは、CX事業本部 Delivery部の若槻です。

AWS CDK v2.85.0 で、AWS Step Functions ステートマシンを ASL(Amazon States Language )JSON から作成可能になりました。

今までは aws_stepfunctions および aws_stepfunctions_tasks モジュールを使用して Chain を作成する必要がありましたが、今後は ASL JSON という選択肢も増えることになります。ASL JSON はマネジメントコンソールや AWS CloudFormation から作成する際に直接操作するものであったため、こちらの方が馴染みのある方も多いのではないでしょうか。

試してみた

CDK ライブラリのアップデート

CDK ライブラリを最新バージョンにアップグレードします。

npm install aws-cdk aws-cdk-lib

アップグレードできました。

package.json

{
  "devDependencies": {
-    "aws-cdk": "^2.84.0",
+    "aws-cdk": "^2.85.0",
  },
  "dependencies": {
-    "aws-cdk-lib": "^2.84.0",
+    "aws-cdk-lib": "^2.85.0",
  }
}

ASL JSON からステートマシンを作成

ASL JSON の文字列を直接指定した場合と、ファイルで指定した場合でステートマシンを作成してみます。今回のアップデートで追加された DefinitionBody クラスの fromFile および fromString メソッドをそれぞれ使用します。

lib/cdk-sample-stack.ts

import { aws_stepfunctions as sfn, Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';

export class CdkSampleStack extends Stack {
  constructor(scope: Construct, id: string, props: StackProps) {
    super(scope, id, props);

    const definitonBody = {
      StartAt: 'Pass',
      States: { Pass: { Type: 'Pass', End: true } },
    };

    // ASL JSON 文字列から作成
    new sfn.StateMachine(this, 'StateMachineFromString', {
      stateMachineName: 'StateMachineFromString',
      definitionBody: sfn.DefinitionBody.fromString(
        JSON.stringify(definitonBody)
      ),
    });

    // ASL JSON ファイルから作成
    new sfn.StateMachine(this, 'StateMachineFromFile', {
      stateMachineName: 'StateMachineFromFile',
      definitionBody: sfn.DefinitionBody.fromFile('./asl.json', {}),
    });
  }
}

fromFile() で読み込む ASL JSON ファイルです。

asl.json

{
  "StartAt": "Pass",
  "States": { "Pass": { "Type": "Pass", "End": true } }
}

CDK デプロイを実行します。

文字列から作成したステートマシンが作成されました。

また、ファイルから作成したステートマシンが作成されました。

API アクションを実行するステートマシンを作成する場合、明示的に権限の付与が必要

ここで、AWS サービスを API アクションで実行するステートマシンを AWS SJON から作成した場合に、権限がどうなるのか気になりました。

次のように、Lambda 関数を実行するステートマシンを ASL JSON から作成してみます。

lib/cdk-sample-stack.ts

import {
  aws_lambda_nodejs,
  aws_stepfunctions as sfn,
  Stack,
  StackProps,
} from 'aws-cdk-lib';
import { Construct } from 'constructs';

export class CdkSampleStack extends Stack {
  constructor(scope: Construct, id: string, props: StackProps) {
    super(scope, id, props);

    // Lambda 関数
    const sampleFunc = new aws_lambda_nodejs.NodejsFunction(
      this,
      'sampleFunc',
      {
        functionName: 'myFunction',
      }
    );

    // Lambda 関数を実行する ASL JSON
    const definitonBody = {
      StartAt: 'Lambda Invoke',
      States: {
        'Lambda Invoke': {
          Type: 'Task',
          Resource: 'arn:aws:states:::lambda:invoke',
          Parameters: {
            FunctionName: sampleFunc.functionName,
          },
          End: true,
        },
      },
    };

    // ASL JSON 文字列からステートマシンを作成
    new sfn.StateMachine(this, 'StateMachineFromString', {
      stateMachineName: 'StateMachineFromString',
      definitionBody: sfn.DefinitionBody.fromString(
        JSON.stringify(definitonBody)
      ),
    });
  }
}

作成されたリソース一覧を見ると、ステートマシンの実行ロールが作成されています。

しかしロールの権限内容を確認すると、ポリシーが何も付与されていません。

よって、ステートマシンを実行すると Lambda 関数の実行権限が無いためエラーになります。

そこで Lambda 関数の実行権限をステートマシンに明示的に付与します。

lib/cdk-sample-stack.ts

    // ASL JSON 文字列からステートマシンを作成
    const StateMachineFromString = new sfn.StateMachine(
      this,
      'StateMachineFromString',
      {
        stateMachineName: 'StateMachineFromString',
        definitionBody: sfn.DefinitionBody.fromString(
          JSON.stringify(definitonBody)
        ),
      }
    );

    sampleFunc.grantInvoke(StateMachineFromString);

実行ロールに適切なポリシーが付与されます。

ステートマシンを実行すると Lambda 関数が実行されるようになります。

ASL JSON から作成した場合は、今までのモジュールによる構築時とは異なり、実行ロールの権限がよしなに付与されないので、注意が必要そうです。

おわりに

AWS CDK v2.85.0 で AWS Step Functions ステートマシンを ASL JSON から作成可能になったので試してみました。

aws_stepfunctions および aws_stepfunctions_tasks モジュールによるワークフローの構築はかなり癖があるので、今回のアップデートによる ASL JSON による構築のサポートにより、AWS CDK による AWS Step Functions のワークフロー構築の敷居が下がったのではないでしょうか。

以上