shou2017.com
JP / EN

CDK(TypeScript)でAwsCustomResourceを使う方法

Sun Mar 9, 2025
Sun Mar 9, 2025
AWS

CDKでAwsCustomResourceを使っていて、わりとハマってしまったので、メモしておきます。

CDKのAwsCustomResourceとは

公式の説明は以下の通りです。

Defines a custom resource that is materialized using specific AWS API calls. These calls are created using a singleton Lambda function. class AwsCustomResource (construct)

要は、AWSのAPIを呼び出して、リソースを作成するためのカスタムリソースというこです。

わかりやすく言うとCloudFormationやCDKは出来上がったCloudFormationからリソースを作成するのに対して、AwsCustomResourceはAWSのAPIを直接呼び出してリソースを作成するということです。 このやり方は、AWSのAPIから直接リソースを作成するTerraformと一緒ですね。

どういった場合に使うか

CDKはAWS純正のサービスですので、ほとんどのリソースはCDKで作成できますし、constructsがない場合でも低レベルのCDKを使えばリソースを作成できます。 なので、基本はAwsCustomResourceを使うことはないと思いますし、できれば避けたいところです。

しかし、以下のような場合に使うことがあります。

既存のリソースを新たにCDKで管理する場合です。

例えば、最初はAWSコンソールからポチポチ作成していたリソースをCDKで管理したい場合です。cognitoとかそのケースがありありかもしれません。 新規でもリージョンも移行しないしAWSアカウントもそのままなら、わざわざ移行の手間をかける必要はないので既存のリソースをそのまま使うということもありますね。

こんな感じで書いちゃえば済む話なので。

// 既存のUserPoolを取得
const iUserPool: IUserPool = UserPool.fromUserPoolId(
this,
"UserPool",
"既存のUserPoolId",
);
this.userPool = iUserPool as UserPool;

これで既存のUserPoolをCDKで管理できるようになりますが、これでデプロイするとデフォルトのUserPoolの設定になってしまいます。

例えば、これに追加のlambdaトリガーを追加したい場合、純粋にCDKのclassを使用するとエラーになります。これはあくまでも新規のリソースを作成するためのもので、既存のリソースを管理するためのものではないからです。私もこのエラーに当たりました。もうリソースはあるよって感じのエラーを吐かれました(たしか…)。

そこで、この場合は既存のリソースを管理したあとに追加の設定をするにはAwsCustomResourceかlambdaでAWSのAPIを使うかのどっちかですね。

まぁ、AwsCustomResourceのほうが簡単なので、ここではAwsCustomResourceを使っていきます。

AwsCustomResourceを使う

AwsCustomResourceはCDKではなくAWSのAPIを使うのでSDKを見て、そのまま追加する機能を書いてやればいいです。

AWS SDK for JavaScript

例えば、以下のようにUserPoolの設定を変更する場合は以下のように書けます。例えば、管理者のみがユーザーを作成できるようにする場合です。

ServiceとActionはAWSのSDKを見て、それに合わせて書いていきます。あとはポリシーの設定と、physicalResourceIdを設定してやればOKです。

new AwsCustomResource(this, "UpdateUserPool", {
  onUpdate: {
    service: "CognitoIdentityServiceProvider", // 対象のサービス
    action: "UpdateUserPoolCommand", // 対象のAPI
    parameters: {
      UserPoolId: "既存のUserPoolId",
      DeletionProtection: "ACTIVE",
      // 管理者のみがユーザーを作成できるようにする
      AdminCreateUserConfig: {
        AllowAdminCreateUserOnly: true,
      },
    },
    physicalResourceId: PhysicalResourceId.of(Date.now().toString()),
  },
  policy: AwsCustomResourcePolicy.fromSdkCalls({
    resources: AwsCustomResourcePolicy.ANY_RESOURCE,
  }),
});

AwsCustomResourceはこのやり方をざっくり知っていれば、あとはAWSのSDKを見て、どのAPIを使うかを調べて、それに合わせて書いていけばSDKとか普段から書いている人であれば特に問題ないと思います。

ですが、気をつけて欲しいのがAwsCustomResourceを書いているときは、TypeScriptの型が効いてないということを忘れないでください。まぁ、コードみればわかるよと思うと思いますが、それでも気をつけてください。

私は思いっきりハマって数時間溶かしてしまいました。なんで、設定が反映されていないし、デプロイでもエラーがでないんだと思ったらparametersの中のAdminCreateUserConfigadminCreateUserConfigと書いていました。CDKのバグじゃないのかと思って、リポジトリを見ていてたら結局はタイプミスというオチ、、、

AwsCustomResourceはCDKの型の恩恵を受けられないので、なにかしらのミスをしてもエラーが出ないので、気をつけてください。

See Also