Create Lambda Layer Through Cloud Formation - How to make sure your request credentials have permission to GetObject for bucket?

0

I am able to deploy a lambda function via CloudFormation, but I wish to deploy it while including a Lambda layer for the requests library.

My CloudFormation template contains the following resources: LambdaFunction (gets created successfully) LambdaIAMRole (gets created successfully) LambdaIAMPolicy (gets created successfully) LambdaScheduledRule (gets created successfully) LambdaResourcePolicy (for the LambdaScheduledRule, gets created successfully) LambdaLayer (CREATE_FAILED)

Status Reason: Your access has been denied by S3, please make sure your request credentials have permission to GetObject for [bucket] xxxx-nprd-xxxx-xxx-xxxxx-us-east-2/python.zip. S3 Error Code: AccessDenied. S3 Error Message: Access Denied (Service: AWSLambdaInternal; Status Code: 403; Error Code: AccessDeniedException; Request ID: e1d25641-e4cc-47d7-abb4-f0d1b9fb4240; Proxy: null)

Here is the code I used to create some of the above resources:

    "LambdaFunction" : {
      "Type": "AWS::Lambda::Function",
      "Properties": {
          "Code": {
              "S3Bucket": {"Ref" : "CodeSourceBucket" },
              "S3Key": "lambdafunction.zip"
          },
          "Environment":{
            "Variables" :{
              "BUCKET": {"Ref": "xxxx-nprd-xxxx-xxx-xxxxx-us-east-2"},
              "BUCKET_PREFIX": {"Ref": "xxx"},
              "WEBSITE_URL": {"Ref": "xxx"}
              }
            },
            "EphemeralStorage" : {
              "Size" : 512
            },
            "Handler": "lambda_handler",
            "Role": {"Fn::GetAtt" : [ "LambdaIAMRole", "Arn" ]},
            "Runtime": "python3.9",
            "FunctionName": { "Fn::Sub": "xxx"},
            "Description": "xxx",
            "Timeout": "90",
            "MemorySize": 512
        }                
  },
  "LambdaIAMRole" : {
    "Type": "AWS::IAM::Role",
    "Properties": {
       "RoleName": { "Fn::Sub": "xxx-role"},
       "AssumeRolePolicyDocument": {
           "Version": "2012-10-17",
           "Statement": [
               {
                   "Effect": "Allow",
                   "Principal": {
                       "Service": [
                           "lambda.amazonaws.com"
                       ]
                   },
                   "Action": [
                       "sts:AssumeRole"
                   ]
               }
           ]
       },
       "Path": "/"
      }
  },
  "IAMPolicy": {
    "Type": "AWS::IAM::Policy",
    "Properties": {
       "PolicyName": { "Fn::Sub": "xxxxxx"},
       "PolicyDocument" : {
           "Statement": [               
            {
              "Effect": "Allow",
              "Action": 
              [
                  "s3:GetObject"
              ],
              "Resource": [                        
                {"xxxx-nprd-xxxx-xxx-xxxxx-us-east-2"},                       
                {"xxxx-nprd-xxxx-xxx-xxxxx-us-east-2/*"}
               ]
            },                   
           {
              "Effect": "Allow",
              "Action": 
              [
                  "s3:get*",
                  "s3:put*"
              ],
              "Resource": [                        
                {"xxxx-nprd-xxxx-xxx-xxxxx-us-east-2"},                       
                {"xxxx-nprd-xxxx-xxx-xxxxx-us-east-2/*"}
               ]
            },
            {
                 "Effect": "Allow",
                 "Action": [
                     "logs:CreateLogGroup",
                     "logs:CreateLogStream",
                     "logs:PutLogEvents"
                 ],
                 "Resource": "*"
              },
              {
                "Effect": "Allow",
                "Action": [
                    "glue:StartJobRun",
                    "glue:GetJobRun"
                ],
                "Resource": "*"
              },      
              {
                "Effect": "Allow",
                "Action": "lambda:GetLayerVersion",
                "Resource": "arn:aws:lambda:us-east-x:xxxxxxxxxxxx:request_layer-2-28:1" 
              }
           ]
       },
       "Roles" : [ {"Ref":"IAMRole"} ]
    }
  },

  "LambdaLayer": {
    "Type" : "AWS::Lambda::LayerVersion",
    "Properties" : {
        "CompatibleArchitectures" : [ "x86_64" ],
        "CompatibleRuntimes" : [ "python3.7", "python3.8", "python3.9" ],
        "Content" : { 
          "S3Bucket": "xxxx-nprd-xxxx-xxx-xxxxx-us-east-2",
          "S3Key": "python.zip"
        },
        "Description" : "Requests library"
      }
  }

I was able to manually create my lambda layer for the requests library through the AWS console after creating my lambda function, but I don't know which permissions to include in the template to allow the lambda function to access the Lambda Layer of the python.zip in the S3 bucket (the python.zip contains the requests library).

My stack keeps failing to be created because the LambdaLayer resource is failing.

I don't see a "lambda layer" policy that I can attach to the role I am using for this lambda function. I also do not see a lambda layer resource policy.

I tried to add { "Effect": "Allow", "Action": "lambda:GetLayerVersion", "Resource": "arn:aws:lambda:us-east-x:xxxxxxxxxxxx:layer:request_layer-2-28:1" }

to the IAM policy, but it didn't work. Am I supposed to add "Layers" property to the LambdaFunction resource?

I also tried to add { "Effect": "Allow", "Action": [ "s3:GetObject" ],

to the policy but it did't work. Please help.

asked 20 days ago33 views
1 Answer
0

Hello,

From the error, it seems like you may not have sufficient permissions to access the object, ‘python.zip’ from the S3 bucket (masked as ‘xxxx-nprd-xxxx-xxx-xxxxx-us-east-2’) while trying to create Lambda layer resource in Cloudformation.

As you may already be aware, there could be multiple possible reasons for encountering the 403 Access Denied error, it may be due to missing IAM permissions or the request may also be getting denied from S3’s end. There is a detailed article [1] on troubleshooting and fixing the S3 Access Denied errors.

That being said, as the first step, I believe you should verify the permissions in the IAM user/entity which is being used to create/update the Cloudformation stack. This is because, while creating the Lambda layer resource, the Lambda execution role specified in the template is not used to fetch the object from S3, and hence you would need to verify the permissions of the IAM user/entity creating the Lambda layer from outside the template (i.e. possibly from IAM console).

Additionally, ‘GetLayerVersion’ API is specified to use a Lambda function with a layer. For functions in your AWS account, you can add this permission from your user policy on the layer version. Please check the following documentation [2] for more information depending on your use case to better understand the usage of GetLayerVersion.

Therefore, to fix the Access Denied errors, I believe you would first need to ensure that the the IAM entity responsible for creating the Lambda layer resource has the ‘s3:GetObject’ permissions or if that is fine, I would suggest you to check the listed points mentioned in article [1] for troubleshooting the error from S3’s end.

Thank you!

REFERENCES:

[1] https://aws.amazon.com/premiumsupport/knowledge-center/s3-troubleshoot-403/

[2] https://docs.aws.amazon.com/lambda/latest/dg/invocation-layers.html#invocation-layers-permissions

SUPPORT ENGINEER
Ayush_T
answered 18 days ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions