Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Way to access S3 Bucket's name from cloudformation/boto3?

My team wants to create an S3 bucket in a cloudformation template without assigning it a bucket name (to let cloudformation name it itself).

When putting a file into the S3 bucket from my lambda function, is there a way for me to get the S3 bucket's name without having to manually look at the AWS console and check what name was created?

like image 970
Louis Phan Avatar asked Oct 24 '17 00:10

Louis Phan


People also ask

How do I find my stack name in CloudFormation?

A stack name can contain only alphanumeric characters (case-sensitive) and hyphens. It must start with an alphabetic character and can't be longer than 128 characters. In the Parameters section, specify parameters that are defined in the stack template. You can use or change any parameters with default values.

How do I access S3 bucket files?

In the Amazon S3 console, choose your S3 bucket, choose the file that you want to open or download, choose Actions, and then choose Open or Download. If you are downloading an object, specify where you want to save it. The procedure for saving the object depends on the browser and operating system that you are using.


2 Answers

Using the Serverless Application Model (SAM) you can include environment variables with the function properties

AWSTemplateFormatVersion: '2010-09-09'
Description: "Demo"
Transform: 'AWS::Serverless-2016-10-31'
Resources:
  MyLambdaFunction:
    Type: 'AWS::Serverless::Function'
    Properties:
      Runtime: nodejs10.x
      Handler: index.handler
      CodeUri: ./src
      Policies:
      - Version: '2012-10-17'
        Statement:
        - Action:
          - s3:PutObject
          Effect: 'Allow'
          Resource: !Sub ${MyS3Bucket.Arn}/*
      Environment:
        Variables:
          BUCKET_NAME: !Ref MyS3Bucket
  MyS3Bucket:
    Type: 'AWS::S3::Bucket'

Then your function can access the environment variables using process.env.BUCKET_NAME in node.js. In python I think you'd use os.environ['BUCKET_NAME']

const aws = require('aws-sdk');
const s3 = new aws.S3();

exports.handler = async (event) => {
    const params = {
        Body: 'The Body',
        Bucket: process.env.BUCKET_NAME,
        Key: 'abc123',
    }

    return s3.putObject(params).promise();
}

I would assume this works for any CloudFormation templates which aren't using the SAM transform too.

like image 62
Andy2K11 Avatar answered Sep 28 '22 09:09

Andy2K11


You can use Fn::GetAtt to get the values from your newly created S3 bucket. You can check it here. S3 Ref & Get Attribute Documentation

The problem is how to pass the value to lambda function. Here is the step that might be works.

  • Use the function Get Attribute above to get the s3 bucket name that cloudformation created.
  • Insert the value into a file, you can use the UserData, or use Metadata if you are using cloud-init already.
  • Store the file into existed s3 bucket (or any other storage that lambda can access), you can using the cloud formation template bucket, that always been created when you launch a cloudformation template (usually named cf-template...).
  • Add a code to your lambda to access the s3 and get the file. Now you get the data of the s3 bucket that your cloudformation has been created and can use it on lambda.

Hope this help.

like image 33
sin Avatar answered Sep 28 '22 07:09

sin