1 はじめに
CX 事業本部のデリバリー部の平内(SIN)です。
AWS Step Functions(以下、Step Functions)では、ワークフローから 200 を超える AWS のサービス(9,000 を超えるアクション)を直接呼び出すことができます。
その他の AWS のサービスを呼び出す
そして、AWS CDK(以下、CDK) では、そのためのコンストラクタとしてCallAwsServiceが用意されています。
class CallAwsService (construct)
CallAwsServiceでは、コールする API に必要なパーミッショッも併せて生成してくれますが、今回は、その内容について確認してみました。
2 自動的に生成されるポリシー
S3 バケットから、get-objectで、ファイルをダウンロードするとしたら、以下のようなコードになります。
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import { aws_stepfunctions, aws_stepfunctions_tasks } from "aws-cdk-lib";
export class SampleStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const bucketName = "work-2023-02-24";
const keyName = "sample.txt";
const getObject = new aws_stepfunctions_tasks.CallAwsService(
this,
"GetObject",
{
service: "s3",
action: "getObject",
parameters: {
Bucket: bucketName,
Key: keyName,
},
iamResources: [`arn:aws:s3:::${bucketName}/*`],
}
);
new aws_stepfunctions.StateMachine(this, "StateMachine", {
stateMachineName: "myStateMachine",
definition: getObject,
});
}
}
上記を使用して作成された Step Functions を、AWS コンソールで見た様子です。
そして、ロールを確認してみると次のようになっています。
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "s3:getObject",
"Resource": "arn:aws:s3:::work-2023-02-24/*",
"Effect": "Allow"
}
]
}
こちらは、CallAwsServiceの必須パラメータである、 service、action、iamResourcesから生成されています。
3 アクション名が、ポリシーと一致しない場合 (iamAction)
生成されるポリシーは、serviceとactionの組み合わせで決まりますが、その組み合わせで対応できない場合もあります。
例)ListObjectsV2 に必要なポリシーは、s3:ListBucket
参考:ListObjects なんていう S3 のアクションは存在しない
残念ながら、以下のコードで生成される StepFunctions は Access Denied となります。
const listObjectsV2 = new aws_stepfunctions_tasks.CallAwsService(
this,
"ListObjectsV2",
{
service: "s3",
action: "listObjectsV2",
parameters: {
Bucket: bucketName,
},
iamResources: [`arn:aws:s3:::${bucketName}`],
}
);
この原因は、生成されたポリシーが以下のようになっているためです。
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "s3:listObjectsV2",
"Resource": "arn:aws:s3:::work-2023-02-24",
"Effect": "Allow"
}
]
}
対策としては、パラメータとしてのiamActionを追加します。
const listObjectsV2 = new aws_stepfunctions_tasks.CallAwsService(
this,
"ListObjectsV2",
{
service: "s3",
action: "listObjectsV2",
parameters: {
Bucket: bucketName,
},
iamResources: [`arn:aws:s3:::${bucketName}`],
iamAction: "s3:ListBucket", // <= この行を追加
}
);
iamActionが指定されると、生成されるポリシーは、iamActionとiamResourcesの組み合わせとなります。
Access Deniedが解消されていることが確認できます。
4 追加のポリシーが必要な場合(additionalIamStatements)
action、service、iamActionで対応できない場合、additionalIamStatementsを使用します。
例として・・・
rekognition:detectTextを使用すると、画像の中からテキストを検出することができます。
バケットに桜の画像を配置します。
以下のコードで StepFunctions を構成します。
const bucketName = "work-2023-02-24";
const keyName = "sample.jpg";
const detectText = new aws_stepfunctions_tasks.CallAwsService(
this,
"DetectText",
{
service: "rekognition",
action: "detectText",
iamResources: ["*"],
parameters: {
Image: {
S3Object: {
Bucket: bucketName,
Name: keyName,
},
},
},
additionalIamStatements: [
new aws_iam.PolicyStatement({
actions: ["s3:getObject"],
resources: [`arn:aws:s3:::${bucketName}/*`],
}),
],
}
);
実行すると、DetectedText に、Cherry blossomsが検出されていることが確認できます。
rekognition:detectTextでは、S3 バケットにアクセスするための追加のポリシーが必要ですが、これを追加しているのが、additionalIamStatementsです。
先のコードで生成されたポリシーは、以下のようになっています。
action及び、serviceの組み合わせに追加して、additionalIamStatementsに列挙したポリシーも追加されています。
additionalIamStatementsを追加しなかった場合は、S3 へアクセスできなかったことが原因で失敗します。
5 参考: GUI からの操作では、ポリシー追加はされない
AWS コンソールからステートマシンを作成する場合、GUI から簡単に操作できます。
しかし、この場合、AWS サービス API を使用するためのパーミッションは、別途設定する必要があります。
代わりに、xray に関するパーミッションが追加されていることが確認できます。
6 参考: CustomState では、ポリシー追加はされない
パラメータを全て JSON で設定できる、低レベルのコンストラクタであるCustomStateでも、同じように記述できますが、こちらは、ポリシーを自動的に追加することはありません。
class CustomState (construct)
const getObject = new aws_stepfunctions.CustomState(this, "GetObject", {
stateJson: {
Type: "Task",
Resource: "arn:aws:states:::aws-sdk:s3:getObject";,
Parameters: {
Bucket: bucketName,
Key: keyName,
},
},
});
AWS サービス API を使用する場合、現時点で、CustomStateが必要になることはないと思います。
7 最後に
今回は、CallAwsService コンストラクで生成されるパーミションについて確認してみました。
複雑な処理になると、まだまだ Lambda での実装に軍配が上がりそうですが、2,3 の API サービスの組み合わせだけで要件が完了してしまうような場合、CallAwsServiceで簡単に書けることの魅力は捨て難いですよね。
[感謝] 桜の画像は、Pixabayのものを利用させて頂きました。 https://pixabay.com/ja/photos/%e3%83%94%e3%83%b3%e3%82%af-%e6%a1%9c-%e3%83%95%e3%83%a9%e3%83%af%e3%83%bc%e3%82%ba-%e6%94%af%e5%ba%97-324175/