jwadsack
jwadsack

Reputation: 5888

IAM bucket policy to allow cross-account Lambda function to write to S3

I'm having a tough time figuring out how to make this work. Our client runs a Lambda function to generate data to write to our bucket. Lambda assumes a role and because of that (I think) all our attempts to allow the client's entire account access to the bucket still result in an AccessDenied error.

In looking at our logs I see the AccessDenied is returned for the STS assumed-role. However, S3 console won't allow me to add a policy for a wildcard Principal, and the assumed role's session ID changes each session.

My guess from the sparse documentation is that we need to provide a trust relationship to the lambda.amazonaws.com service. But I can't find any documentation anywhere on how to limit that to just access from a specific Lambda function or account.

I would like to have something like this but with further constraints on the Principal so that it's not accessible by any account or Lambda function.

{
    "Version": "2012-10-17",
    "Id": "Policy11111111111111",
    "Statement": [
        {
            "Sid": "Stmt11111111111111",
            "Effect": "Allow",
            "Principal": {
                "Service": [
                    "lambda.amazonaws.com"
                ]
            },
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::bucket-name-here/*",
                "arn:aws:s3:::bucket-name-here"
            ]
        }
    ]
}

UPDATE

This policy doesn't even work. It still returns an AccessDenied. The user listed in the logs is in the form of arn:aws:sts::111111222222:assumed-role/role-name/awslambda_333_201512111822444444.

So at the point I'm at a loss as to how to even allow a Lambda function to write to an S3 bucket.

Upvotes: 2

Views: 11009

Answers (2)

Nakul Bhandare
Nakul Bhandare

Reputation: 1

To Allow Cross account lambda function to get access of s3 bucket
following policy we need to add to s3 bucket policy externally
{
            "Sid": "AWSLambda",
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.amazonaws.com",
                "AWS": "arn:aws:iam::<AccountID>:root"
            },
            "Action": "s3:GetObject",
            "Resource": "<AWS_S3_Bucket_ARN>/*"
        }

Following Template will help you to allow cross account Lambda function to access s3 bucket

Parameters:
  LamdaAccountId:
    Description: AccountId to which allow access
    Type: String
Resources:
  myBucket:
    Type: 'AWS::S3::Bucket'
    Properties: {}
    Metadata:
      'AWS::CloudFormation::Designer':
        id: e5eb9fcf-5fe2-468c-ad54-b9b41ba1926a
  myPolicy:
    Type: 'AWS::S3::BucketPolicy'
    Properties:
      Bucket: !Ref myBucket
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Sid: Stmt1580304800238
            Action: 's3:*'
            Effect: Allow
            Resource:
              - !Sub 'arn:aws:s3:::${myBucket}/*'
            Principal:
              Service: lambda.amazonaws.com
              AWS:
                - !Sub '${LamdaAccountId}'

Upvotes: 0

jwadsack
jwadsack

Reputation: 5888

We resolved this eventually with help from the IAM team.

IAM roles do not inherit any permission from the account so they need permissions assigned explicitly to the assumed role for the Lambda script.

In our case the Lambda script was also trying to grant the destination bucket owner full control of the copied file. The role assumed by the Lambda function was missing permissions for s3:PutObjectAcl. After we added the permission the lambda function began working correctly.

The destination policy that we have working now is something like this:

{
  "Version": "2012-10-17",
  "Id": "Policy11111111111111",
  "Statement": [
    {
        "Sid": "Stmt11111111111111",
        "Effect": "Allow",
        "Principal": "*",
        "Action": "s3:ListBucket*",
        "Resource": "arn:aws:s3:::bucket-name",
        "Condition": {
            "StringLike": {
                "aws:userid": "ACCOUNT-ID:awslambda_*"
            }
        }
    },
    {
        "Sid": "Stmt11111111111111",
        "Effect": "Allow",
        "Principal": "*",
        "Action": "s3:*",
        "Resource": "arn:aws:s3:::bucket-name/*",
        "Condition": {
            "StringLike": {
                "aws:userid": "ACCOUNT-ID:awslambda_*"
            }
        }
    },
    {
        "Sid": "Stmt11111111111111",
        "Effect": "Allow",
        "Principal": {
            "AWS": "arn:aws:iam::0000000000000:root"
        },
        "Action": "s3:*",
        "Resource": "arn:aws:s3:::bucket-name"
    },
    {
        "Sid": "Stmt11111111111111",
        "Effect": "Allow",
        "Principal": {
            "AWS": "arn:aws:iam::0000000000000:root"
        },
        "Action": "s3:*",
        "Resource": "arn:aws:s3:::bucket-name/*"
    }
  ]
}

Upvotes: 3

Related Questions