Cloud Formation для добавления нескольких триггеров S3 в одну корзину S3 в LambdaConfiguration - PullRequest
3 голосов
/ 17 марта 2020

Мое требование - запустить Lambda_Function_1, если файл input.txt создается в сегменте S3, и вызвать Lambda_Function_2, если файл output.txt создается в том же сегменте S3.

Приведенный ниже cfn не работает, но он работает нормально, если я помещаю только одно событие вместо двух событий в один и тот же LambdaConfigurations.

Может кто-нибудь помочь мне здесь?

Parameters:
  S3BucketBaseName:
    Type: String
    Description: The base name of the Amazon S3 bucket.
    Default: dw-trip


Resources:
  LambdaStart: 
    DependsOn:
      - LambdaStartStopEC2
    Type: "AWS::Lambda::Function"
    Properties:
      FunctionName: "dw-trip-start-ec2"
      Handler: "index.handler"
      Role: !GetAtt LambdaStartStopEC2.Arn
      Runtime: python3.7
      MemorySize: 3008
      Timeout: 900
      Code:
        ZipFile: |
          import boto3
          region = 'us-east-1'
          instances = ['i-05d5fbec4c82956b6']
          ec2 = boto3.client('ec2', region_name=region)
          def lambda_handler(event, context):
              ec2.start_instances(InstanceIds=instances)
              print('started your instances: ' + str(instances))

  ProcessingLambdaPermissionStart:
    Type: AWS::Lambda::Permission
    DependsOn:
      - LambdaStart    
    Properties:
      Action: 'lambda:InvokeFunction'
      FunctionName: !Ref LambdaStart
      Principal: s3.amazonaws.com
      SourceArn:
                Fn::Join: 
                  - ''
                  - - 'arn:aws:s3:::'
                    - !Join ["-",[!Ref "S3BucketBaseName",!Ref "AWS::AccountId"]]
      SourceAccount: !Ref AWS::AccountId

  LambdaStop: 
    DependsOn:
      - ProcessingLambdaPermissionStart
    Type: "AWS::Lambda::Function"
    Properties:
      FunctionName: "dw-trip-stop-ec2"
      Handler: "index.handler"
      Role: !GetAtt LambdaStartStopEC2.Arn
      Runtime: python3.7
      MemorySize: 3008
      Timeout: 900
      Code:
        ZipFile: |
          import boto3
          region = 'us-east-1'
          instances = ['i-05d5fbec4c82956b6']
          ec2 = boto3.client('ec2', region_name=region)
          def lambda_handler(event, context):
              ec2.stop_instances(InstanceIds=instances)
              print('stopping your instances: ' + str(instances))

  ProcessingLambdaPermissionStop:
    Type: AWS::Lambda::Permission
    DependsOn:
      - LambdaStop  
    Properties:
      Action: 'lambda:InvokeFunction'
      FunctionName: !Ref LambdaStop
      Principal: s3.amazonaws.com
      SourceArn:
                Fn::Join: 
                  - ''
                  - - 'arn:aws:s3:::'
                    - !Join ["-",[!Ref "S3BucketBaseName",!Ref "AWS::AccountId"]]
      SourceAccount: !Ref AWS::AccountId

  S3KmsKey:
    Type: AWS::KMS::Key
    DependsOn:
      - ProcessingLambdaPermissionStop
    Properties:
      Description: KMS key for trip S3 bucket.
      Enabled: true
      EnableKeyRotation: true
      KeyPolicy:
        Statement:
          - Sid: Administration
            Effect: Allow
            Principal:
              AWS:
                - Fn::Join:
                    - ''
                    - - 'arn:aws:iam::'
                      - Ref: AWS::AccountId
                      - ':role/DW01-codepipeline-action-us-east-1'              
                - Fn::Join:
                    - ''
                    - - 'arn:aws:iam::'
                      - Ref: AWS::AccountId
                      - ':root'
            Action: 'kms:*'
            Resource: '*'

  S3bucketCreate:
    DependsOn:
      - S3KmsKey
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Join ["-",[!Ref "S3BucketBaseName",!Ref "AWS::AccountId"]]
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              KMSMasterKeyID: !Ref S3KmsKey
              SSEAlgorithm: "aws:kms"
      NotificationConfiguration:
        LambdaConfigurations:
          - Event: s3:ObjectCreated:*
            Function: !GetAtt LambdaStart.Arn
            Filter:
              S3Key:
                Rules:
                - Name: prefix
                  Value: input.txt               
          - Event: s3:ObjectCreated:*
            Function: !GetAtt LambdaStop.Arn
            Filter:
              S3Key:
                Rules:
                - Name: prefix
                  Value: output.txt     

  S3bucketPolicy:
    DependsOn:
      - S3bucketCreate        
    Type: AWS::S3::BucketPolicy
    Properties: 
      Bucket: 
        Ref: 'S3bucketCreate'
      PolicyDocument: 
        Statement: 
          - Sid: AllowEc2AccesstoBucket
            Action: 
              - 's3:GetObject'
              - 's3:PutObject'              
            Effect: Allow
            Principal:
              AWS:
                - Fn::Join:          
                  - ''
                  - - 'arn:aws:iam::'
                    - Ref: AWS::AccountId
                    - ':role/DevDW01-EC2-us-east-1'
            Resource: 
                Fn::Join: 
                  - ''
                  - - 'arn:aws:s3:::'
                    - Ref: 'S3bucketCreate'
                    - '/*'              
  LambdaStartStopEC2:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service: 
              - lambda.amazonaws.com
            Action: sts:AssumeRole
      RoleName: Lambda-StartStop-EC2
      MaxSessionDuration: 43200
      Policies:
        - PolicyName: StartStop-EC2
          PolicyDocument:
            Statement:
            - Action:
              - s3:*
              Effect: Allow
              Resource: '*'
            - Action:
              - ec2:*
              Effect: Allow
              Resource: '*'
        - PolicyName: logs
          PolicyDocument:
            Statement:
            - Action:
              - logs:CreateLogGroup
              - logs:CreateLogStream
              - logs:DescribeLogGroups
              - logs:DescribeLogStreams
              - logs:PutLogEvents
              - logs:GetLogEvents
              - logs:FilterLogEvents
              Effect: Allow
              Resource: '*'

Outputs:
  S3bucketCreateName:
    Value:
      Ref: S3bucketCreate
    Export:
      Name: S3bucketCreateName
  S3bucketCreateArn:
    Value:
      Fn::GetAtt: S3bucketCreate.Arn
    Export:
      Name: S3bucketCreateArn
  S3KmsKeyArn:
    Value:
      Fn::GetAtt: S3KmsKey.Arn
    Export:
      Name: S3KmsKeyArn

1 Ответ

0 голосов
/ 18 марта 2020

Несколько правил фильтрации с prefix и suffix в качестве имени разрешены, если они не перекрываются. См. здесь для различных примеров, объясняющих, как может происходить перекрытие и как их избежать.

В этом случае ошибка Template format error: YAML not well-formed может быть связана с неправильным форматированием YAML. Используйте cfn-lint для проверки шаблонов.

Добавление фрагмента, который явно указывает ожидаемый префикс и суффикс объекта S3.

      NotificationConfiguration:
        LambdaConfigurations:
          - Event: s3:ObjectCreated:*
            Function: !GetAtt LambdaStart.Arn
            Filter:
              S3Key:
                Rules:
                - Name: prefix
                  Value: input
                - Name: suffix
                  Value: txt           
          - Event: s3:ObjectCreated:*
            Function: !GetAtt LambdaStop.Arn
            Filter:
              S3Key:
                Rules:
                - Name: prefix
                  Value: output
                - Name: suffix
                  Value: txt
...