Comment puis-je utiliser CloudFormation pour créer une configuration de notification Amazon S3 pour Lambda dans un compartiment S3 existant ?

Lecture de 4 minute(s)
0

Je veux utiliser un compartiment Amazon Simple Storage Service (Amazon S3) existant pour créer une configuration de notification Amazon S3 pour une fonction AWS Lambda. Je veux le faire en utilisant AWS CloudFormation.

Brève description

Pour créer une configuration de notification Amazon S3, utilisez CloudFormation afin de créer un nouveau compartiment S3. Ensuite, ajoutez une configuration de notifications à ce compartiment à l'aide de la propriété NotificationConfiguration. Vous pouvez également ajouter manuellement une configuration de notification à un compartiment S3 existant.

Les étapes suivantes vous montrent comment ajouter une configuration de notification à votre compartiment S3 existant avec CloudFormation. Pour ce faire, utilisez une ressource personnalisée basée sur Lambda créée dans Python 3.9. La ressource personnalisée initie une fonction Lambda, qui déclenche l'API PutBucketNotification pour ajouter une configuration de notification à votre compartiment S3.

Remarque : si vous recevez des erreurs lors de l'exécution de commandes de l'interface de la ligne de commande AWS (AWS CLI), assurez-vous d'utiliser la version la plus récente de l'AWS CLI.

Solution

Important : les étapes suivantes s'appliquent uniquement aux configurations de notification Amazon S3 pour les compartiments S3 qui n'ont aucune configuration de notification existante. Si votre compartiment S3 possède déjà une configuration de notification existante ou créée manuellement, les étapes suivantes remplacent ces configurations. Toutes les notifications sont supprimées une fois que vous avez supprimé votre pile. Si votre solution semble fonctionner, il peut y avoir des configurations sous-optimales liées à votre cas d'utilisation. Il est recommandé de tester votre solution sur un compartiment S3 de test avant de la déployer dans un environnement de production.

1.    Créez un modèle CloudFormation appelé LambdaS3.template qui inclut le code suivant.

Important : dans l'exemple suivant, vous ajoutez la configuration de notification S3 à la ressource S3Notification****LambdaFunction. Vous utilisez la fonction Lambda CustomResourceLambdaFunction pour ajouter la configuration de notification S3 pour S3NotificationLambdaFunction. Vous pouvez modifier le code dans la ressource CustomResourceLambdaFunction pour répondre à vos besoins.

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)

            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.    Pour lancer la pile CloudFormation avec le fichier LambdaS3.template, utilisez la console CloudFormation ou la commande de CLI AWS suivante :

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

Important : lorsque vous lancez la pile CloudFormation, vous devez transmettre votre compartiment S3. Par exemple, existing-bucket-for-lambda-notification

La pile crée une fonction Lambda et des autorisations Lambda pour Amazon S3. Vous pouvez maintenant utiliser le compartiment S3 pour des notifications Lambda, car la pile a ajouté la configuration de notifications requise au compartiment S3.


AWS OFFICIEL
AWS OFFICIELA mis à jour il y a 7 mois