Skip to content

Instantly share code, notes, and snippets.

@nodomain
Forked from holyjak/README.md
Created October 25, 2018 15:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nodomain/eac20e79ceb44990f154a92d8f8c8913 to your computer and use it in GitHub Desktop.
Save nodomain/eac20e79ceb44990f154a92d8f8c8913 to your computer and use it in GitHub Desktop.
IAM policy to allow Continuous Integration user to deploy to AWS Elastic Beanstalk

IAM policy to allow Continuous Integration user to deploy to AWS Elastic Beanstalk

IAM policy that we attach to CI users so that our CI server can deploy new versions of our applications to our EB environments without giving them too many permissions. When some permissions are missing, deploys may fail with the useless and misleading ERROR event log

Service:AmazonCloudFormation, Message:TemplateURL must reference a valid S3 object to which you have access.

(Notice that in many cases the error has nothing to do with S3 but can be caused by any missing permissions, for instance autoscaling:SuspendProcesse. Yes, it sucks.)

The policy can certainly be tightened more, it is not the most restrictive policy that works. As Kyle points out, the full EC2 rights are likely the biggest problem.

What if it fails?

If a deployment to Elastic Beanstalk fails with this policy:

  1. Give the user full access and retry to verify that it as a permission problem.
  2. Revert. You might already have fixed the problem - some deployments need elevated permissions, for example when you change anything in .ebextensions, an elasticbeanstalk.UpdateEnvironment will pass but it will consequently try to UpdateStack, which my fail. But once it succeeds for a given Beanstalk environment, it won't be done again (well, untiil you change the config again).
  3. You are out of luck. AWS is very opaque about what it does and it is hard, if not impossible, to find out what operation failed. CloudTrail does not really help.

Related work

Check out also the popular AWS Elastic Beanstalk deploy user restricted IAM policy by magnetikonline and the comments under it. (Among others, it limits access to only a particular EB application. I am sure I could make my policy more restrictive based on its example.)

Changelog

  • 2017-04-21 Added "s3:Get*","s3:List*", "autoscaling:UpdateAutoScalingGroup", "autoscaling:DescribeLaunchConfigurations" to fix a problem with "Rolling with additional batch" deployments (the infamous "Service:AmazonCloudFormation, Message:TemplateURL must reference a valid S3 object to which you have access.")
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"elasticbeanstalk:CreateApplicationVersion",
"elasticbeanstalk:DescribeEnvironments",
"elasticbeanstalk:DeleteApplicationVersion",
"elasticbeanstalk:UpdateEnvironment"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"sns:CreateTopic",
"sns:GetTopicAttributes",
"sns:ListSubscriptionsByTopic",
"sns:Subscribe"
],
"Effect": "Allow",
"Resource": "arn:aws:sns:REGION:ACCOUNT_ID:*"
},
{
"Action": [
"autoscaling:SuspendProcesses",
"autoscaling:DescribeScalingActivities",
"autoscaling:ResumeProcesses",
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:UpdateAutoScalingGroup",
"autoscaling:DescribeLaunchConfigurations"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"cloudformation:GetTemplate",
"cloudformation:DescribeStacks",
"cloudformation:CreateStack",
"cloudformation:CancelUpdateStack",
"cloudformation:ListStackResources",
"cloudformation:DescribeStackResource",
"cloudformation:DescribeStackResources",
"cloudformation:DescribeStackEvents",
"cloudformation:DeleteStack",
"cloudformation:UpdateStack"
],
"Effect": "Allow",
"Resource": "arn:aws:cloudformation:REGION:ACCOUNT_ID:*"
},
{
"Action": [
"ec2:DescribeImages",
"ec2:DescribeKeyPairs",
"ec2:describeVpcs",
"ec2:*"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:ListBucket",
"s3:DeleteObject",
"s3:GetBucketPolicy",
"s3:Get*",
"s3:List*"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::elasticbeanstalk-REGION-ACCOUNT_ID",
"arn:aws:s3:::elasticbeanstalk-REGION-ACCOUNT_ID/*"
]
},
{
"Action": [
"s3:CreateBucket",
"s3:GetObject",
"s3:ListAllMyBuckets"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"elasticloadbalancing:DescribeInstanceHealth",
"elasticloadbalancing:DescribeLoadBalancers",
"elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
"elasticloadbalancing:RegisterInstancesWithLoadBalancer"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"autoscaling:DescribeScheduledActions",
"autoscaling:TerminateInstanceInAutoScalingGroup"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment