¿Cómo puedo utilizar CloudFormation para crear una configuración de notificaciones de Amazon S3 para Lambda en un bucket de S3 existente?

4 minutos de lectura
0

Quiero usar un bucket de Amazon Simple Storage Service (Amazon S3) existente para crear una configuración de notificaciones de Amazon S3 para una función de AWS Lambda.

Breve descripción

Para crear una configuración de notificaciones de Amazon S3, utilice CloudFormation para crear un nuevo bucket de S3. A continuación, añada una configuración de notificaciones a ese bucket mediante la propiedad NotificationConfiguration. O, añada manualmente una configuración de notificaciones a un bucket de S3 existente.

En los siguientes pasos se muestra cómo añadir una configuración de notificaciones a su bucket de S3 existente con CloudFormation. Para ello, cree un recurso personalizado respaldado por Lambda en Python 3.9. El recurso personalizado inicia una función de Lambda que inicia la API PutBucketNotification para añadir una configuración de notificaciones a su bucket de S3.

Nota: Si recibe errores al ejecutar los comandos de la Interfaz de la línea de comandos de AWS (AWS CLI), asegúrese de usar la versión más reciente.

Resolución

Importante: Los siguientes pasos se aplican únicamente a las configuraciones de notificaciones de Amazon S3 de los buckets de S3 que no tienen configuraciones de notificaciones existentes. Si su bucket de S3 ya tiene una configuración de notificaciones existente o creada manualmente, los siguientes pasos anulan esas configuraciones. Tras eliminar la pila, Amazon S3 suprime todas las notificaciones. Si su solución parece funcionar, es posible que haya configuraciones subóptimas en su caso de uso. Se recomienda probar la solución en un bucket de prueba de S3 antes de implementarla en un entorno de producción.

1.Cree una plantilla de CloudFormation llamada LambdaS3.template que incluya el código siguiente:

Importante: En el ejemplo siguiente, añade la configuración de notificaciones de S3 al recurso S3NotificationLambdaFunction. Utilice la función de Lambda CustomResourceLambdaFunction para añadir la configuración de notificaciones de S3 para S3NotificationLambdaFunction. Para cumplir sus requisitos, puede modificar el código del 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 una pila de CloudFormation con el archivo LambdaS3.template, utilice la consola de CloudFormation o el siguiente comando de 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: Al iniciar su pila de CloudFormation, debe incluir su bucket de S3. Por ejemplo, ejecute existing-bucket-for-lambda-notification.

La pila crea una función de Lambda y permisos de Lambda para Amazon S3. Como la pila agregó la configuración de notificaciones requerida a su bucket de S3, ahora puede usar el bucket de S3 para las notificaciones de Lambda.

OFICIAL DE AWS
OFICIAL DE AWSActualizada hace 10 meses