【问题标题】:How to get access to the bucket created via cloudformation in my lambda?如何在我的 lambda 中访问通过 cloudformation 创建的存储桶?
【发布时间】:2020-08-21 04:23:33
【问题描述】:

我正在通过 cloudformation 模板创建一个 lambda 和一个 S3。对于存储桶,我传入了存储桶名称的参数。我想在我的 python 代码中为 lambda 函数访问这个存储桶。我该怎么做?

cloudformation 模板

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Sample SAM Template 

Globals:
  Function:
    Timeout: 3

Parameters:
  bucketName:
     Default: somename
Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      AccessControl: PublicRead
      BucketName: !Sub '${bucketName}-${AWS::AccountID}'

  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.8
    Environment:
      Variables:
        s3bucketName: !GetAtt S3Bucket
      

lambda_handler 函数

import boto3
import os
from requests_aws4auth import AWS4Auth

session = boto3.Session()
credentials = session.get_credentials()
aws4auth = AWS4Auth(credentials.access_key,credentials.secret_key,region, service, session_token=credentials.token)
                    
s3 = boto3.resource('s3')

//get access to the S3 bucket created??

【问题讨论】:

  • 最常见的选项是通过环境变量将存储桶名称提供给 Lambda 函数。将Environment 添加到您的AWS::Serverless::Function
  • @jarmod - 更新了我的答案。这应该有效吗?
  • 看起来很合理。我通常会将其命名为 S3_BUCKET_NAME。
  • @jarmod - 谢谢,我只想问最后一个问题。 - 我需要确保在 lambda 之前创建 s3。我的 python 代码出现错误 -> keyError 'S3_BUCKET_NAME',我在代码中使用 os.environ['S3_BUCKET_NAME'] 来访问它。 – ozil 1 分钟前 编辑
  • 如果您的 Lambda 函数中发生 Python 错误,则说明环境变量设置不正确。使用控制台查看您的 CloudFormation 堆栈实际创建了哪些环境变量。

标签: python amazon-web-services aws-lambda


【解决方案1】:
s3 = boto3.resource('s3')

obj = s3.Object(bucket, key)
objAsString = obj.get()['Body'].read().decode('utf-8')

您还缺少从 lambda 访问 s3 存储桶的策略。

HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.8
      Environment:
      Variables:
        S3_BUCKET_NAME: !Ref S3Bucket
      Policies:
        - Statement:
          - Effect:
            Action:
              - 's3:GetObject'
              - 's3:ListBucket'
              - 's3:ListBucketMultipartUploads'
              - 's3:PutObject'
            Resource:
              - !Sub 'arn:aws:s3:::${S3Bucket}'

我将在单独的 cloudformation s3.yaml 中创建存储桶并执行一次。

....
Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      AccessControl: PublicRead
      BucketName: !Sub '${bucketName}-${AWS::AccountID}'

Outputs:
  BucketName:
   Value: !Ref S3Bucket
   Description: 'Bucket name'
   Export:
     Name: s3-bucket-name

之后,我可以使用 lambda 将这个 s3-bucket-name 导入其他 cloudformation。

Variables:
   S3_BUCKET_NAME: !ImportValue s3-bucket-name

【讨论】:

  • 我更新了我的答案,在环境变量下添加了存储桶名称。一旦我让 s3 访问 lambda ,就像你说的那样。这个设置会起作用吗?
  • 是的,存储桶名称可以作为环境变量访问。我会使用!Ref 而不是!GetAttr ...S3_BUCKET_NAME: !Ref S3Bucket,更新了我的答案中的示例。
  • 最后一个 - 我需要确保 s3 在 lambda 之前创建。我的 python 代码出现错误 -> keyError 'S3_BUCKET_NAME',我在代码中使用 os.environ['S3_BUCKET_NAME'] 来访问它。
  • 是的,您需要先创建它。要么使用单独的 cloudformation 创建它,要么使用 DependsOn,因此 lambda 取决于先创建存储桶。
猜你喜欢
  • 2016-12-09
  • 2015-04-30
  • 1970-01-01
  • 1970-01-01
  • 2016-12-31
  • 2020-10-17
  • 1970-01-01
  • 2020-12-02
  • 2021-09-17
相关资源
最近更新 更多