Como posso usar o CloudFormation para criar uma configuração de notificação do Amazon S3 para o Lambda em um bucket do S3 existente?

4 minuto de leitura
0

Quero usar um bucket existente do Amazon Simple Storage Service (Amazon S3) para criar uma configuração de notificação do Amazon S3 para uma função do AWS Lambda.

Breve descrição

Para criar uma configuração de notificação do Amazon S3, use o CloudFormation para criar um novo bucket do S3. Em seguida, adicione uma configuração de notificação a esse bucket usando a propriedade NotificationConfiguration. Ou adicione manualmente uma configuração de notificação a um bucket S3 existente.

As etapas a seguir mostram como adicionar uma configuração de notificação ao seu bucket S3 existente com o CloudFormation. Para fazer isso, crie um recurso personalizado baseado em Lambda no Python 3.9. O recurso personalizado inicia uma função do Lambda que inicia a API PutBucketNotification para adicionar uma configuração de notificação ao seu bucket do S3.

Observação: se você receber erros ao executar comandos da AWS Command Line Interface (AWS CLI), verifique se está usando a versão mais recente.

Resolução

Importante: As etapas a seguir se aplicam somente às configurações de notificação do Amazon S3 para buckets do S3 que não têm configurações de notificação existentes. Se o seu bucket do S3 já tiver uma configuração de notificação existente ou criada manualmente, as etapas a seguir substituirão essas configurações. Depois de excluir sua pilha, o Amazon S3 remove todas as notificações. Se sua solução parecer funcionar, talvez haja configurações abaixo do ideal em seu caso de uso. É uma prática recomendada testar sua solução em um bucket de teste do S3 antes de implantá-la em um ambiente de produção.

1.    Crie um modelo do CloudFormation chamado LambdaS3.template que inclua o seguinte código:

Importante: No exemplo a seguir, você adiciona a configuração de notificação do S3 ao recurso S3NotificationLambdaFunction. Você usa a função do Lambda CustomResourceLambdaFunction para adicionar a configuração de notificação do S3 para S3NotificationLambdaFunction. Para atender aos seus requisitos, é possível modificar o código no recurso CustomResourceLambdaFunction.

AWSTemplateFormatVersion: 2010-09-09
Description: >-
  Sample template to illustrate use of existing S3 bucket as an event source for a Lambda function
Parameters:
  NotificationBucket:
    Type: String
    Description: S3 bucket that's used for the Lambda event notification

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.9
      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:GetBucketNotification'
                  - 's3:PutBucketNotification'
                Resource: !Sub 'arn:aws:s3:::${NotificationBucket}'
              - Effect: Allow
                Action:
                  - 'logs:CreateLogGroup'
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                Resource: 'arn:aws:logs:*:*:*'

  CustomResourceLambdaFunction:
    Type: 'AWS::Lambda::Function'
    Properties:
      Handler: index.lambda_handler
      Role: !GetAtt LambdaIAMRole.Arn
      Code:
        ZipFile: |

            from __future__ import print_function
            import json
            import boto3
            import cfnresponse

            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 = 'FAILED'
                    responseData = {'Failure': 'Something bad happened.'}
                cfnresponse.send(event, context, responseStatus, responseData, "CustomResourcePhysicalID")

            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....")
      Runtime: python3.9
      Timeout: 50

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

2.    Para iniciar uma pilha do CloudFormation com o arquivo LambdaS3.template, use o console do CloudFormation ou o seguinte comando da 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 --capabilities CAPABILITY_NAMED_IAM --region us-east-1

Importante: Ao iniciar sua pilha do CloudFormation, você precisa passar seu bucket do S3. Por exemplo, execute existing-bucket-for-lambda-notification.

A pilha cria uma função do Lambda e permissões do Lambda para o Amazon S3. Como a pilha adicionou a configuração de notificação necessária ao seu bucket do S3, agora você pode usar seu bucket do S3 para notificações do Lambda.

AWS OFICIAL
AWS OFICIALAtualizada há 10 meses