スキップしてコンテンツを表示

CDK プロジェクトからインターフェイス AwsSdkCall を使用して AWS SDK 呼び出しを行う方法を教えてください。

所要時間3分
0

AWS Cloud Development Kit (AWS CDK) プロジェクトからインターフェイス AwsSdkCall を使用して AWS SDK 呼び出しを行いたいです。

簡単な説明

AWS Software Development Kit (AWS SDK) 呼び出しは、次のスタックデプロイシナリオで使用できます。

  • スタックを作成および更新するときに構成を動的に取得する場合。
  • AWS CloudFormation が戻り値でサポートしていないリソースの属性を取得する場合。
  • AWS CloudFormation がサポートしていない小さなパッチまたは構成変更を行う場合。

作成、削除、または更新などのさまざまな CloudFormation スタック操作イベントで AWS SDK 呼び出しをトリガーできます。AWS SDK 呼び出しを行うために、デプロイパイプラインのアクセスとツールをセットアップする必要はありません。AWS SDK ランタイムは AWS CDK によってセットアップされます。カスタムリソースの背後にある AWS Lambda 関数のアクセスをカスタマイズおよび制限できます。

解決策

注: 次の例では TypeScript を使用しています。使用しているプログラミング言語に固有の構文を使用してください。

AwsSdkCall を使用して AWS SDK 呼び出しを行うには、次のパラメータを使用してください。

  1. Service には、呼び出す予定の AWS サービスを使用する。値の大文字と小文字が区別される。
  2. Action には、実行する API またはアクション呼び出しを使用する。これは通常キャメルケースのパターンに従い、値は大文字と小文字が区別される。
  3. Parameters には、API またはアクション呼び出しを行うときに渡すオプションのパラメータを使用する。パラメータを変数として宣言し、API ペイロードの JSON オブジェクトに似たインターフェイスに渡すことができます。詳細については、"AWS SDK for JavaScript" を参照してください。

例 1: 構成を動的に取得する

次の例では、スタック作成中に AWS Systems Manager Parameter Store から Amazon Machine Image ID を取得します。getResponseField 方法で API コールの応答を参照し、ドット記法を使用して SDK 応答構造をナビゲートする方法を示しています。

import * as cdk from "aws-cdk-lib/core";
import { Construct } from "constructs";
import * as cr from "aws-cdk-lib/custom-resources";

export class Example1Stack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const getAmiId = new cr.AwsCustomResource(this, "GetAMIId", {
      onCreate: {
        service: "SSM",
        action: "getParameter",
        parameters: {
          Name: "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64",
        },
        physicalResourceId: cr.PhysicalResourceId.of("get-ami-id"),
        },
        policy: cr.AwsCustomResourcePolicy.fromSdkCalls({
         resources: cr.AwsCustomResourcePolicy.ANY_RESOURCE,
        }),
     });

     new cdk.CfnOutput(this, "ImageId", {
        value: getAmiId.getResponseField("Parameter.Value"),
     });
    }
}

例 2: CloudFormation で使用できないリソース属性を取得する

CloudFormation は、Fn::GetAtt を通じてすべてのリソース属性を公開するわけではありません。CloudFormation が必要な値を返さない場合は、SDK 呼び出しを使用してサービス API から直接取得します。この方法では、CloudFormation の外部に存在するリソースや、スタックエクスポート、SSM パラメータ、または Secrets Manager に保存していない属性も取得できます。

例えば、AWS::Organizations::Organization は戻り値として Id と ManagementAccountId を公開しますが、CloudFormation はほとんどの組織を作成しません。describeOrganization への SDK 呼び出しにより、組織をスタックの一部として含めることなく、メンバーアカウントからこれらの値を取得できます。

import * as cdk from "aws-cdk-lib/core";
import { Construct } from "constructs";
import * as cr from "aws-cdk-lib/custom-resources";

export class Example2Stack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const orgInfo = new cr.AwsCustomResource(this, "DescribeOrg", {
      onCreate: {
        service: "Organizations",
        action: "describeOrganization",
        physicalResourceId: cr.PhysicalResourceId.of("describe-org"),
        outputPaths: ["Organization.Id", "Organization.MasterAccountId"],
      },
      policy: cr.AwsCustomResourcePolicy.fromSdkCalls({
        resources: cr.AwsCustomResourcePolicy.ANY_RESOURCE,
      }),
    });

    new cdk.CfnOutput(this, "OrgId", {
      value: orgInfo.getResponseField("Organization.Id"),
    });

    new cdk.CfnOutput(this, "ManagementAccountId", {
      value: orgInfo.getResponseField("Organization.MasterAccountId"),
    });
  }
}

**注: ** この例では outputPaths を使用して、応答を必要なフィールドのみに制限しています。これにより、4096 バイトの CloudFormation 応答制限に達することを回避できます。

例 3: CloudFormation でサポートされていない構成変更を行う

一部の操作には、対応する CloudFormation リソースまたはプロパティがありません。例えば、CloudFormation は DynamoDB テーブルを作成できますが、テーブルにアイテムを挿入することはできません。これを解決するには、AwsSdkCall を使用してデプロイ時に初期データをシードします。

次の例では onCreate を使用しているため、スタックを最初に作成するときにのみアイテムを挿入します。スタック更新時にもアイテムを更新するには、同じ呼び出しを onUpdate に追加します。

import * as cdk from "aws-cdk-lib/core";
import { Construct } from "constructs";
import * as cr from "aws-cdk-lib/custom-resources";
import * as dynamodb from "aws-cdk-lib/aws-dynamodb";

export class Example3Stack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const table = new dynamodb.Table(this, "ConfigTable", {
      partitionKey: { name: "PK", type: dynamodb.AttributeType.STRING },
    });

    new cr.AwsCustomResource(this, "SeedData", {
      onCreate: {
        service: "DynamoDB",
        action: "putItem",
        parameters: {
          TableName: table.tableName,
          Item: {
            PK: { S: "CONFIG" },
            version: { S: "1.0" },
            enabled: { BOOL: true },
          },
        },
        physicalResourceId: cr.PhysicalResourceId.of("seed-data"),
      },
      policy: cr.AwsCustomResourcePolicy.fromSdkCalls({
        resources: [table.tableArn],
      }),
    });
  }
}

複雑なアクセス許可シナリオの処理

policy プロパティは、カスタムリソースの背後にある Lambda 関数にアクセス許可を付与します。fromSdkCalls() を使用すると、各 API コールが対応する IAM アクセス許可に自動的に変換されます。可能な場合は、ANY_RESOURCE を使用するのではなく、アクセス許可を特定のリソース ARN に限定します (例 3)。

場合によっては、fromSdkCalls() が必要なすべてのアクセス許可を生成しないことがあります。例えば、例 3 の DynamoDB テーブルがカスタマーマネージド KMS キーを使用している場合、fromSdkCalls() は dynamodb:PutItem のみを生成し、KMS アクセス許可をまったく追加しません。DynamoDB が暗号化されたテーブルにアイテムを書き込むには kms:Encrypt、kms:Decrypt、および kms:GenerateDataKey が必要であるため、デプロイは失敗します。fromStatements() を使用して、正確なアクセス許可を指定できます。

例:

import * as cdk from "aws-cdk-lib/core";
import { Construct } from "constructs";
import * as cr from "aws-cdk-lib/custom-resources";
import * as dynamodb from "aws-cdk-lib/aws-dynamodb";
import * as kms from "aws-cdk-lib/aws-kms";
import * as iam from "aws-cdk-lib/aws-iam";

export class Example4Stack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const encryptionKey = new kms.Key(this, "TableKey");

    const table = new dynamodb.Table(this, "ConfigTable", {
      partitionKey: { name: "PK", type: dynamodb.AttributeType.STRING },
      encryption: dynamodb.TableEncryption.CUSTOMER_MANAGED,
      encryptionKey,
    });

    new cr.AwsCustomResource(this, "SeedData", {
      onCreate: {
        service: "DynamoDB",
        action: "putItem",
        parameters: {
          TableName: table.tableName,
          Item: {
            PK: { S: "CONFIG" },
            version: { S: "1.0" },
            enabled: { BOOL: true },
          },
        },
        physicalResourceId: cr.PhysicalResourceId.of("seed-data"),
      },
      policy: cr.AwsCustomResourcePolicy.fromStatements([
        new iam.PolicyStatement({
          actions: ["dynamodb:PutItem"],
          resources: [table.tableArn],
        }),
        new iam.PolicyStatement({
          actions: ["kms:Encrypt", "kms:Decrypt", "kms:GenerateDataKey"],
          resources: [encryptionKey.keyArn],
        }),
      ]),
    });
  }
}
AWS公式更新しました 4ヶ月前
1コメント

This article was reviewed and updated on 2026-06-01.

エキスパート

応答済み 6日前

関連するコンテンツ