AWS CloudFormation을 사용하여 기존 Amazon S3 버킷에서 Lambda에 대한 Amazon S3 알림 구성을 생성하려면 어떻게 해야 합니까?

최종 업데이트 날짜: 2019년 11월 15일

기존 Amazon Simple Storage Service(Amazon S3) 버킷을 사용하여 AWS CloudFormation을 통해 AWS Lambda 함수에 대한 Amazon S3 알림 구성을 생성하려면 어떻게 해야 합니까?

간략한 설명

Amazon S3 알림 구성을 생성하기 위해 AWS CloudFormation을 사용하여 새 S3 버킷을 생성할 수 있습니다. 그런 다음 NotificationConfiguration 속성을 사용해 해당 버킷에 알림 구성을 추가하십시오. 또는 기존 S3 버킷에 수동으로 알림 구성을 추가하십시오.

다음 단계는 Python 3.6에서 생성된 Lambda 지원 사용자 지정 리소스를 사용하여 AWS CloudFormation으로 기존 S3 버킷에 알림 구성을 추가하는 방법을 보여줍니다. 사용자는 사용자 지정 리소스를 사용하여 Lambda 함수를 트리거하며, 이는 PutBucketNotification API를 트리거하여 S3 버킷에 알림 구성을 추가합니다.

​해결 방법

중요: 다음 단계는 기존 알림 구성이 없는 S3 버킷의 S3 알림 구성에만 적용됩니다. S3 버킷에 기존 또는 수동으로 생성한 알림 구성이 이미 있는 경우 다음 단계를 수행하면 해당 구성이 재정의됩니다.

1.    다음 코드가 포함된 LambdaS3.py라는 이름의 Python 파일을 생성하십시오.

from __future__ import print_function
import json
import boto3
import urllib
from botocore.vendored import requests

SUCCESS = "SUCCESS"
FAILED = "FAILED"

print('Loading function')
s3 = boto3.resource('s3')

def lambda_handler(event, context):
    print("Received event: " + json.dumps(event, indent=2))
    responseData={}
    try:
        if event['RequestType'] == 'Delete':
            print("Request Type:",event['RequestType'])
            Bucket=event['ResourceProperties']['Bucket']
            delete_notification(Bucket)
            print("Sending response to custom resource after Delete")
        elif event['RequestType'] == 'Create' or event['RequestType'] == 'Update':
            print("Request Type:",event['RequestType'])
            LambdaArn=event['ResourceProperties']['LambdaArn']
            Bucket=event['ResourceProperties']['Bucket']
            add_notification(LambdaArn, Bucket)
            responseData={'Bucket':Bucket}
            print("Sending response to custom resource")
        responseStatus = 'SUCCESS'
    except Exception as e:
        print('Failed to process:', e)
        responseStatus = 'FAILURE'
        responseData = {'Failure': 'Something bad happened.'}
    send(event, context, responseStatus, responseData)

def add_notification(LambdaArn, Bucket):
    bucket_notification = s3.BucketNotification(Bucket)
    response = bucket_notification.put(
      NotificationConfiguration={
        'LambdaFunctionConfigurations': [
            {
                'LambdaFunctionArn': LambdaArn,
                'Events': [
                    's3:ObjectCreated:*'
                ]
            }
        ]
      }
    )
    print("Put request completed....")

def delete_notification(Bucket):
    bucket_notification = s3.BucketNotification(Bucket)
    response = bucket_notification.put(
      NotificationConfiguration={}
    )
    print("Delete request completed....")


def send(event, context, responseStatus, responseData, physicalResourceId=None, noEcho=False):
    responseUrl = event['ResponseURL']
    print(responseUrl)
    responseBody = {'Status': responseStatus,
                    'Reason': 'See the details in CloudWatch Log Stream: ' + context.log_stream_name,
                    'PhysicalResourceId': physicalResourceId or context.log_stream_name,
                    'StackId': event['StackId'],
                    'RequestId': event['RequestId'],
                    'LogicalResourceId': event['LogicalResourceId'],
                    'Data': responseData}
    json_responseBody = json.dumps(responseBody)
    print("Response body:\n" + json_responseBody)
    headers = {
        'content-type' : '',
        'content-length' : str(len(json_responseBody))
    }
    try:
        response = requests.put(responseUrl,
                                data=json_responseBody,
                                headers=headers)
        print("Status code: " + response.reason)
    except Exception as e:
        print("send(..) failed executing requests.put(..): " + str(e))

2.    Lambda 함수에 대해 LambdaS3.zip이라는 이름의 zip 파일을 생성하십시오. 다음 예제를 참조하십시오.

-> LambdaS3.zip | |-> LambdaS3.py

중요: LambdaS3.py가 zip 파일의 루트 레벨에 있는지 확인하십시오.

3.    AWS CloudFormation 스택과 동일한 AWS 리전에 있는 S3 버킷에 zip 파일을 업로드하십시오. AWS CLI(AWS 명령줄 인터페이스)를 사용하여 zip 파일을 업로드하려면, LambdaS3.zip 파일이 포함된 폴더에서 다음 명령을 실행합니다.

aws s3 cp ./LambdaS3.zip s3://awsexamplebucket1/LambdaS3.zip

4.    다음 코드를 포함하는 LambdaS3.template이라는 AWS CloudFormation 템플릿을 생성하십시오.

중요: 다음 예제에서 S3NotificationLambdaFunction 리소스는 S3 알림 구성이 추가된 Lambda 함수입니다. CustomResourceLambdaFunctionS3NotificationLambdaFunction에 대한 S3 알림 구성을 추가하는 데 사용된 Lambda 함수입니다.

AWSTemplateFormatVersion: 2010-09-09
Description: >-
  Sample template to illustrate use of existing S3 bucket as event source for
  Lambda function
Parameters:
  NotificationBucket:
    Type: String
    Description: S3 bucket which is used for Lambda event notification
  LambdaCodeBucket:
    Type: String
    Description: S3 bucket in which custom lambda code is stored
  LambdaCodeKey:
    Type: String
    Description: Zip file name in which custom lambda code is stored
    Default: LambdaS3.zip
  Lambdahandler:
    Type: String
    Description: Python file name which is packed inside the zip file
    Default: LambdaS3

Resources:
  S3NotificationLambdaFunction:
    Type: 'AWS::Lambda::Function'
    Properties:
      Code:
        ZipFile: !Join
          - |+

          - - import json
            - 'def lambda_handler(event,context):'
            - '    return ''Welcome... This is a test Lambda Function'''
      Handler: index.lambda_handler
      Role: !GetAtt LambdaIAMRole.Arn
      Runtime: python3.6
      Timeout: 5

  LambdaInvokePermission:
    Type: 'AWS::Lambda::Permission'
    Properties:
      FunctionName: !GetAtt S3NotificationLambdaFunction.Arn
      Action: 'lambda:InvokeFunction'
      Principal: s3.amazonaws.com
      SourceAccount: !Ref 'AWS::AccountId'
      SourceArn: !Sub 'arn:aws:s3:::${NotificationBucket}'

  LambdaIAMRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      Policies:
        - PolicyName: root
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - 's3:*'
                Resource: '*'
              - Effect: Allow
                Action:
                  - 'logs:CreateLogGroup'
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                Resource: 'arn:aws:logs:*:*:*'

  CustomResourceLambdaFunction:
    Type: 'AWS::Lambda::Function'
    Properties:
      Handler: !Sub '${Lambdahandler}.lambda_handler'
      Role: !GetAtt LambdaIAMRole.Arn
      Code:
        S3Bucket: !Ref LambdaCodeBucket
        S3Key: !Ref LambdaCodeKey
      Runtime: python3.6
      Timeout: 50

  LambdaTrigger:
    Type: 'Custom::RouteTableLambda'
    DependsOn: LambdaInvokePermission
    Properties:
      ServiceToken: !GetAtt CustomResourceLambdaFunction.Arn
      LambdaArn: !GetAtt S3NotificationLambdaFunction.Arn
      Bucket: !Ref NotificationBucket

5.    LambdaS3.template 파일을 사용하여 AWS CloudFormation 스택을 시작하려면, AWS CloudFormation 콘솔 또는 다음 AWS CLI 명령을 사용하십시오.

aws cloudformation create-stack --stack-name lambda-s3-notification --template-body file://LambdaS3.template --parameters ParameterKey=NotificationBucket,ParameterValue=existing-bucket-for-lambda-notification ParameterKey=LambdaCodeBucket,ParameterValue=awsexamplebucket1 ParameterKey=Lambdahandler,ParameterValue=LambdaS3 ParameterKey=LambdaCodeKey,ParameterValue=LambdaS3.zip --capabilities CAPABILITY_NAMED_IAM --region us-east-1

중요: AWS CloudFormation 스택을 시작할 때 다음 과정을 거쳐야 합니다.

  • 사용자의 S3 버킷(existing-bucket-for-lambda-notification)
  • zip 파일을 업로드한 S3 버킷 이름(awsexamplebucket1)
  • zip 파일 이름(LambdaS3.zip)
  • Lambda 함수를 생성한 파일 이름(LambdaS3.py)

스택은 Lambda 함수 및 Amazon S3에 대한 Lambda 권한을 생성합니다. 스택이 S3 버킷에 필요한 알림 구성을 추가했으므로 이제 S3 버킷을 Lambda 알림용으로 사용할 수 있습니다.


이 문서가 도움이 되었습니까?

AWS에서 개선해야 할 부분이 있습니까?


도움이 필요하십니까?