web-dev-qa-db-ja.com

AWS CDK - 既存のS3バケットにイベント通知を追加する方法

私は変更しようとしています この AWS-Provent CDKの例代わりに既存のバケットを使用してください。追加 ドキュメント 既存のリソースのインポートがサポートされていることを示します。これまでは、CDKを使用して既存のバケットにイベント通知を追加できません。

これが私の例の私の修正版です:

_class S3TriggerStack(core.Stack):

    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # create lambda function
        function = _lambda.Function(self, "lambda_function",
                                    runtime=_lambda.Runtime.PYTHON_3_7,
                                    handler="lambda-handler.main",
                                    code=_lambda.Code.asset("./lambda"))

        # **MODIFIED TO GET EXISTING BUCKET**
        #s3 = _s3.Bucket(self, "s3bucket")
        s3 = _s3.Bucket.from_bucket_arn(self, 's3_bucket',
            bucket_arn='arn:<my_region>:::<my_bucket>')

        # create s3 notification for lambda function
        notification = aws_s3_notifications.LambdaDestination(function)

        # assign notification for the s3 event type (ex: OBJECT_CREATED)
        s3.add_event_notification(_s3.EventType.OBJECT_CREATED, notification)
_

これにより、_add_event_notification_を試してみると、次のエラーが発生します。

_AttributeError: '_IBucketProxy' object has no attribute 'add_event_notification'
_

_from_bucket_arn_関数はIBucketを返し、_add_event_notification_関数はBucketクラスのメソッドですが、他の方法を見つけることはできません。これ。たぶんサポートされていません。どんな助けにも感謝されるでしょう。

11
cyber-samurai

上記の素晴らしい答えのおかげで、S3 - > Lambda通知のための構成については、以下を参照してください。同様に使用できます

    const fn = new SingletonFunction(this, "Function", {
    ...
    });

    const bucket = Bucket.fromBucketName(this, "Bucket", "...");

    const s3notification = new S3NotificationLambda(this, "S3Notification", {
      bucket: bucket,
      lambda: function,
      events: ['s3:ObjectCreated:*'],
      prefix: "some_prefix/"
    })

構文(.tsファイルとしてプロジェクトにドロップイン)

import * as cr from "@aws-cdk/custom-resources";
import * as logs from "@aws-cdk/aws-logs";
import * as s3 from "@aws-cdk/aws-s3";
import * as sqs from "@aws-cdk/aws-sqs";
import * as iam from "@aws-cdk/aws-iam";
import { Construct } from "@aws-cdk/core";
import * as lambda from "@aws-cdk/aws-lambda";

export interface S3NotificationLambdaProps {
  bucket: s3.IBucket;
  lambda: lambda.IFunction;
  events: string[];
  prefix: string;
}

export class S3NotificationLambda extends Construct {
  constructor(scope: Construct, id: string, props: S3NotificationLambdaProps) {
    super(scope, id);

    const notificationResource = new cr.AwsCustomResource(
      scope,
      id + "CustomResource",
      {
        onCreate: {
          service: "S3",
          action: "putBucketNotificationConfiguration",
          parameters: {
            // This bucket must be in the same region you are deploying to
            Bucket: props.bucket.bucketName,
            NotificationConfiguration: {
              LambdaFunctionConfigurations: [
                {
                  Events: props.events,
                  LambdaFunctionArn: props.lambda.functionArn,
                  Filter: {
                    Key: {
                      FilterRules: [{ Name: "prefix", Value: props.prefix }],
                    },
                  },
                },
              ],
            },
          },
          physicalResourceId: <cr.PhysicalResourceId>(
            (id + Date.now().toString())
          ),
        },
        onDelete: {
          service: "S3",
          action: "putBucketNotificationConfiguration",
          parameters: {
            // This bucket must be in the same region you are deploying to
            Bucket: props.bucket.bucketName,
            // deleting a notification configuration involves setting it to empty.
            NotificationConfiguration: {},
          },
          physicalResourceId: <cr.PhysicalResourceId>(
            (id + Date.now().toString())
          ),
        },
        policy: cr.AwsCustomResourcePolicy.fromStatements([
          new iam.PolicyStatement({
            // The actual function is PutBucketNotificationConfiguration.
            // The "Action" for IAM policies is PutBucketNotification.
            // https://docs.aws.Amazon.com/AmazonS3/latest/dev/list_amazons3.html#amazons3-actions-as-permissions
            actions: ["S3:PutBucketNotification", "S3:GetBucketNotification"],
            // allow this custom resource to modify this bucket
            resources: [props.bucket.bucketArn],
          }),
        ]),
      }
    );

    props.lambda.addPermission("AllowS3Invocation", {
      action: "lambda:InvokeFunction",
      principal: new iam.ServicePrincipal("s3.amazonaws.com"),
      sourceArn: props.bucket.bucketArn,
    });

    // don't create the notification custom-resource until after both the bucket and queue
    // are fully created and policies applied.
    notificationResource.node.addDependency(props.bucket);
    notificationResource.node.addDependency(props.lambda);
  }
}

1
ubi

@biの答えに基づいて

シングルトン機能が必要ではなく機能+いくつかのクリーンアップが必要な場合

このように呼び出します:

const s3NotificationLambdaProps = < S3NotificationLambdaProps > {
    bucket: bucket,
    lambda: lambda,
    events: ['s3:ObjectCreated:*'],
    prefix: '', // or put some prefix
};

const s3NotificationLambda = new S3NotificationLambda(this, `${envNameUpperCase}S3ToLambdaNotification`, s3NotificationLambdaProps);
 _

そして構築物は次のようになります:

import * as cr from "@aws-cdk/custom-resources";
import * as s3 from "@aws-cdk/aws-s3";
import * as iam from "@aws-cdk/aws-iam";
import { Construct } from "@aws-cdk/core";
import * as lambda from "@aws-cdk/aws-lambda";

export interface S3NotificationLambdaProps {
    bucket: s3.IBucket;
    lambda: lambda.Function;
    events: string[];
    prefix: string;
}

export class S3NotificationLambda extends Construct {
    constructor(scope: Construct, id: string, props: S3NotificationLambdaProps) {
        super(scope, id);

        const notificationResource = new cr.AwsCustomResource(
            scope,
            id + "CustomResource", {
                onCreate: {
                    service: "S3",
                    action: "putBucketNotificationConfiguration",
                    parameters: {
                        // This bucket must be in the same region you are deploying to
                        Bucket: props.bucket.bucketName,
                        NotificationConfiguration: {
                            LambdaFunctionConfigurations: [{
                                Events: props.events,
                                LambdaFunctionArn: props.lambda.functionArn,
                                Filter: {
                                    Key: {
                                        FilterRules: [{
                                            Name: "prefix",
                                            Value: props.prefix
                                        }],
                                    },
                                },
                            }, ],
                        },
                    },
                    physicalResourceId: < cr.PhysicalResourceId > (
                        (id + Date.now().toString())
                    ),
                },
                onDelete: {
                    service: "S3",
                    action: "putBucketNotificationConfiguration",
                    parameters: {
                        // This bucket must be in the same region you are deploying to
                        Bucket: props.bucket.bucketName,
                        // deleting a notification configuration involves setting it to empty.
                        NotificationConfiguration: {},
                    },
                    physicalResourceId: < cr.PhysicalResourceId > (
                        (id + Date.now().toString())
                    ),
                },
                policy: cr.AwsCustomResourcePolicy.fromStatements([
                    new iam.PolicyStatement({
                        // The actual function is PutBucketNotificationConfiguration.
                        // The "Action" for IAM policies is PutBucketNotification.
                        // https://docs.aws.Amazon.com/AmazonS3/latest/dev/list_amazons3.html#amazons3-actions-as-permissions
                        actions: ["S3:PutBucketNotification", "S3:GetBucketNotification"],
                        // allow this custom resource to modify this bucket
                        resources: [props.bucket.bucketArn],
                    }),
                ]),
            }
        );

        props.lambda.addPermission("AllowS3Invocation", {
            action: "lambda:InvokeFunction",
            principal: new iam.ServicePrincipal("s3.amazonaws.com"),
            sourceArn: props.bucket.bucketArn,
        });

        // don't create the notification custom-resource until after both the bucket and lambda
        // are fully created and policies applied.
        notificationResource.node.addDependency(props.bucket);
        notificationResource.node.addDependency(props.lambda);
    }
}
 _
1
Vitalii