【问题标题】:Set up S3 Bucket level Events using AWS CloudFormation使用 AWS CloudFormation 设置 S3 存储桶级事件
【发布时间】:2020-03-03 11:24:19
【问题描述】:

我正在尝试让 AWS CloudFormation 创建一个模板,该模板允许我将一个事件附加到现有的 S3 存储桶,只要将新文件放入存储桶中的特定目录,该存储桶就会触发 Lambda 函数。我使用以下 YAML 作为 CloudFormation 模板的基础,但无法使其正常工作。

---
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  SETRULE:
    Type: AWS::S3::Bucket
      Properties:
        BucketName: bucket-name
        NotificationConfiguration:
          LambdaConfigurations: 
            - Event: s3:ObjectCreated:Put
              Filter: 
                S3Key:
                  Rules:
                    - Name: prefix
                      Value: directory/in/bucket
              Function: arn:aws:lambda:us-east-1:XXXXXXXXXX:function:lambda-function-trigger
              Input: '{ CONFIGS_INPUT }'

我尝试了很多不同的方法重写这个模板,但都没有成功。

【问题讨论】:

  • 你遇到了什么错误?
  • 您是否在您的 S3 存储桶上添加了 lambda 调用权限?
  • 我得到了一些不同的错误,这取决于我所做的细微改动,最近我在刚刚读取Properties: 的行上遇到了YAML not well-formatted 错误。而lambda函数一般是在AWS的lambda函数服务下定义的。

标签: amazon-web-services amazon-s3 aws-lambda amazon-cloudformation


【解决方案1】:

您可以编写自定义资源来执行此操作,事实上,这就是我最终在工作中针对同一问题所做的工作。在最简单的级别上,定义一个 lambda,它接受一个 put bucket 通知配置,然后使用传递给它的数据调用 put bucket 通知 api。

如果您希望能够跨不同的 cloudformation 模板控制不同的通知,那就有点复杂了。您的自定义资源 lambda 需要从 S3 读取现有通知,然后根据从 CF 传递给它的数据更新这些通知。

【讨论】:

    【解决方案2】:

    由于您提到这些存储桶已经存在,因此这是行不通的。您可以通过这种方式使用 CloudFormation,但只能创建一个新的存储桶,如果该存储桶最初不是通过该模板创建的,则不能修改现有的存储桶。

    如果您不想重新创建您的基础架构,那么只使用一些将 lambda 函数订阅到每个存储桶的脚本可能会更容易。只要你有一个桶列表和 lambda 函数,你就可以开始了。

    这是一个 Python3 中的脚本。假设我们有:

    1. 2 个桶称为 test-bucket-jkg2 和 test-bucket-x1gf
    2. 带有 arn 的 lambda 函数:arn:aws:lambda:us-east-1:605189564693:function:my_func

    有两个步骤可以完成这项工作。首先,您需要添加允许 s3 服务执行该功能的功能策略。其次,您将逐个遍历存储桶,为每个存储桶订阅 lambda 函数。

    import boto3
    
    s3_client = boto3.client("s3") 
    lambda_client = boto3.client('lambda')
    
    buckets = ["test-bucket-jkg2", "test-bucket-x1gf"]
    lambda_function_arn = "arn:aws:lambda:us-east-1:605189564693:function:my_func"
    
    # create a function policy that will permit s3 service to 
    # execute this lambda function
    
    # note that you should specify SourceAccount and SourceArn to limit who (which account/bucket) can
    # execute this function - you will need to loop through the buckets to achieve 
    # this, at least you should specify SourceAccount
    try:
        response = lambda_client.add_permission(
            FunctionName=lambda_function_arn,
            StatementId="allow s3 to execute this function",
            Action='lambda:InvokeFunction',
            Principal='s3.amazonaws.com'
            # SourceAccount="your account",
            # SourceArn="bucket's arn"
        )
        print(response)
    except Exception as e:
        print(e)
    
    # loop through all buckets and subscribe lambda function 
    # to each one of them
    for bucket in buckets:
        print("putting config to bucket: ", bucket)
        try:
            response = s3_client.put_bucket_notification_configuration(
                Bucket=bucket,
                NotificationConfiguration={
                    'LambdaFunctionConfigurations': [
                        {
                            'LambdaFunctionArn': lambda_function_arn,
                            'Events': [
                                's3:ObjectCreated:*'
                            ]
                        }
                    ]
                }
            )
            print(response)
        except Exception as e:
            print(e)
    

    【讨论】:

    • 我能够触发它并将一组集群配置输入传递给触发 lambda 函数也很重要。 lambda 函数将触发一个状态机,该状态机使用该输入来启动 EMR 集群。我最好能够使用 CloudFormation 进行设置,以便 CloudFormation 更新可以发送更改以在下次触发事件时使用。你知道如何做到这一点吗?
    • 我不明白。 CloudFormation 只是 IaaC(环境描述)。 CloudFormation update could send the changes to be used next time the event is triggered? 什么样的变化并发送到哪里?某种甚至会触发CF更新?该事件将以何种方式以及如何修改模板?您是否打算以编程方式构建您的模板?
    猜你喜欢
    • 2017-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-30
    • 2021-05-06
    • 2017-09-21
    • 2019-07-20
    相关资源
    最近更新 更多