Come faccio a utilizzare CloudFormation per creare una configurazione di notifica Amazon S3 per Lambda su un bucket S3 esistente?

4 minuti di lettura
0

Desidero utilizzare un bucket Amazon Simple Storage Service (Amazon S3) esistente per creare una configurazione di notifica Amazon S3 per una funzione AWS Lambda.

Breve descrizione

Per creare una configurazione di notifica Amazon S3, usa CloudFormation per creare un nuovo bucket S3. Quindi, aggiungi una configurazione di notifica a quel bucket utilizzando la proprietà NotificationConfiguration. Oppure, aggiungi manualmente una configurazione di notifica a un bucket S3 esistente.

I passaggi seguenti mostrano come aggiungere una configurazione di notifica al tuo bucket S3 esistente con CloudFormation. Per fare ciò, crea una risorsa personalizzata supportata da Lambda in Python 3.9. La risorsa personalizzata avvia una funzione Lambda che avvia l'API PutBucketNotification per aggiungere una configurazione di notifica al bucket S3.

Nota: Se visualizzi errori durante l'esecuzione dei comandi dell'interfaccia della linea di comando AWS (AWS CLI), assicurati di utilizzare la versione più recente di AWS CLI.

Risoluzione

Importante: i passaggi seguenti si applicano solo alle configurazioni di notifica Amazon S3 per i bucket S3 che non dispongono di configurazioni di notifica esistenti. Se il tuo bucket S3 ha già una configurazione di notifica esistente o creata manualmente, i seguenti passaggi sostituiranno tali configurazioni. Dopo aver eliminato lo stack, Amazon S3 rimuoverà tutte le notifiche. Se la soluzione sembra funzionare, è possibile che vi siano configurazioni non ottimali per il tuo caso d'uso. È consigliabile testare la soluzione su un bucket S3 di prova prima di implementarla in un ambiente di produzione.

1.    Crea un modello CloudFormation chiamato Lambdas3.template che include il seguente codice:

Importante: nell'esempio seguente, aggiungi la configurazione di notifica S3 alla risorsa S3NotificationLambdaFunction. Utilizza la funzione Lambda CustomResourceLambdaFunction per aggiungere la configurazione di notifica S3 per S3NotificationLambdaFunction. Per soddisfare i tuoi requisiti, puoi modificare il codice nella risorsa 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.    Per avviare uno stack CloudFormation con il file LambdaS3.template, utilizza la console CloudFormation o il seguente comando 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: quando avvii il tuo stack CloudFormation, devi inserire il bucket S3. Ad esempio, esegui existing-bucket-for-lambda-notification.

Lo stack crea una funzione Lambda e autorizzazioni Lambda per Amazon S3. Poiché lo stack ha aggiunto la configurazione di notifica richiesta al tuo bucket S3, ora puoi usare il tuo bucket S3 per le notifiche Lambda.

AWS UFFICIALE
AWS UFFICIALEAggiornata 9 mesi fa