lastoneisbearfood
lastoneisbearfood

Reputation: 4125

Permission denied while elastic beanstalk is retrieving S3 file

I have files stored on S3 and wrote .ebextensions config to automatically copy the them to new instances. I'm receiving this error in the Elastic Beanstalk console:

[Instance: INSTANCEID Module: AWSEBAutoScalingGroup ConfigSet: null] Command failed on instance. Return code: 1 Output: [CMD-AppDeploy/AppDeployStage0/EbExtensionPreBuild] command failed with error code 1: Error occurred during build: Failed to retrieve https://s3-us-west-1.amazonaws.com/MyBucket/MyFolder/_MyFile.txt: HTTP Error 403 : AccessDenied

My .ebextension config file has this section:

files:
    "/target/file/path" :
        mode: "000777"
        owner: ec2-user
        group: ec2-user
        source: https://s3-us-west-1.amazonaws.com/_MyBucket_/_MyFolder_/_MyFile.txt

In attempting to make this file copying work, I've also relaxed permissions by giving the elastic beanstalk IAM role the standard read only access policy to all of S3. It's policy is this:

{
  "Effect": "Allow",
  "Action": [
    "s3:Get*",
    "s3:List*"
  ],
  "Resource": "*"
}

Yet the prebuild copying step still fails. Did I give the source url in the correct format? Is there another security entity/policy involved? Help please :)

Upvotes: 16

Views: 21965

Answers (5)

Alastair McCormack
Alastair McCormack

Reputation: 27714

The documentation is very sketchy on the subject (probably an ideal candidate for StackExchange Docs!).

To do this correctly with .ebextensions, you need to allow the Beanstalk instance IAMs user in the bucket policy, setup an AWS::CloudFormation::Authentication: auth config and attach config to remote sources. This is kind of a hybrid of all the other answers, but all failed in one way or another for me.

Assuming your IAM instance role is aws-elasticbeanstalk-ec2-role:

  1. Set your AWS bucket to allow the Beanstalk IAM User. Edit "bucket policy":

    {
        "Version": "2012-10-17",
        "Id": "BeanstalkS3Copy",
        "Statement": [
            {
                "Sid": "",
                "Effect": "Allow",
                "Principal": {
                    "AWS": "<beanstalk_iam_role_arn>"
                },
                "Action": [
                    "s3:ListBucketVersions",
                    "s3:ListBucket",
                    "s3:GetObjectVersion",
                    "s3:GetObject"
                ],
                "Resource": [
                    "arn:aws:s3:::<bucket_name>",
                    "arn:aws:s3:::<bucket_name>/*"
                ]
            }
        ]
    }
    

    where:

    beanstalk_iam_role_arn = the fully qualified instance IAMs role. See "IAM role" associated with a running instance if available or see environment configuration. Example: arn:aws:iam::12345689:role/aws-elasticbeanstalk-ec2-role

    bucket_name = your bucket name

  2. In your .ebextension/myconfig.config, add an S3 authentication block that uses your IAMs instance user:

    Resources:
    AWSEBAutoScalingGroup:
      Metadata:
        AWS::CloudFormation::Authentication:
          S3Auth:
            type: "s3"
            buckets: ["bucket_name"]
            roleName:
              "Fn::GetOptionSetting":
                Namespace: "aws:asg:launchconfiguration"
                OptionName: "IamInstanceProfile" 
                DefaultValue: "aws-elasticbeanstalk-ec2-role"
    

    Set bucket_name appropriately

  3. Define a remote file and attach the S3 Authentication block:

    "/etc/myfile.txt" :
       mode: "000400"
       owner: root
       group: root
       authentication: "S3Auth" # Matches to auth block above.
       source: https://s3-eu-west-1.amazonaws.com/mybucket/myfile.txt
    

    Set your source URL appropriately

Upvotes: 23

mjallday
mjallday

Reputation: 10082

If you have your IAM role for the machine configured to get access to the file you can do the following in .ebextensions

commands:
  01a_copy_file:
    command: aws s3 cp s3://bucket/path/file /destination/

Upvotes: 1

Matt Holtzman
Matt Holtzman

Reputation: 633

Similar to chaseadamsio's answer, you can configure the role given to the EC2 instance with a policy to access S3 resources, then use the pre-installed AWS CLI utilities to move files around.

The way I approached this is to create a role dedicated to the given EB application, then attach a policy similar to:

"Statement": [
    {
        "Sid": "<sid>",
        "Effect": "Allow",
        "Action": [
            "s3:GetObject"
        ],
        "Resource": [
            "arn:aws:s3:::<your_bucket_path>/*"
        ]
    }
]

This gives your instance access, then to get the files, add a 'commands' block to your config such as:

commands: 
  01-get-file:
    command: aws s3 cp s3://<your_bucket_path>/your-file.txt /home/ec2-user
  02-execute-actions: 
    [unpack, run scripts, etc..]

Obviously you can use other AWS CLI utlities as needed. I found this solved a lot of problems I was having with S3 access and makes deployment a lot easier.

Upvotes: 12

chaseadamsio
chaseadamsio

Reputation: 894

An alternative to setting the .ebextensions config would be to set a policy on the aws-elasticbeanstalk-ec2-role within the IAM Manager (or create a new role specifically for your elastic beanstalk environments to sandbox your autoscaled ec2 instances.

To do so, go to the IAM manager within the web console, and click on "Roles" on the left side. You should see your instance name in the list of roles, clicking on that will take you to the administration page for that particular role. Attach a new role policy to the role under "Permissions" with a policy document matching what you want your ec2 to have permissions to do (in this case, you'd give it a policy to access an s3 bucket called _MyBucket and you should no longer need the Resources section in your .ebextensions config.

Upvotes: 4

lastoneisbearfood
lastoneisbearfood

Reputation: 4125

I found a solution to overcome this error. It turns out adding a Resources section to the .ebextensions config file makes it work. The entire file becomes:

files:
  "/target/file/path" :
    mode: "000777"
    owner: ec2-user
    group: ec2-user
    source: https://s3-us-west-1.amazonaws.com/_MyBucket_/_MyFolder_/_MyFile.txt
Resources:
  AWSEBAutoScalingGroup:
    Metadata:
      AWS::CloudFormation::Authentication:
        S3Access:
          type: S3
          roleName: aws-elasticbeanstalk-ec2-role
          buckets: _MyBucket

At this point, I don't know enough to grok why it has to be this way. Hopefully it can help someone who's lost move forward and eventually gain a better understanding. I based my answer on this link https://forums.aws.amazon.com/message.jspa?messageID=541634

Upvotes: 8

Related Questions