AWS IAM policy for Serverless Framework deploy
I recently built a CD pipeline to deploy a Serverless Framework project to AWS (Lambda). To do that, you need your CD pipeline’s AWS user to have specific permissions.
The official docs list a sample policy but it also mentions:
If you are create a custom IAM Role with this policy, you will need to add a Trust relationship to the AWS Account with ID 377024778620 (arn:aws:iam::377024778620:root) in order for the Serverless Framework to Assume the Role with the provided policy.
If you don’t want to add that trust relationship, and just have all the perms you need, you need to figure out all those perms. This policy is what I ended up with:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"apigateway:DELETE",
"apigateway:GET",
"apigateway:PATCH",
"apigateway:POST",
"apigateway:PUT",
"cloudformation:CreateChangeSet",
"cloudformation:CreateStack",
"cloudformation:DeleteChangeSet",
"cloudformation:DeleteStack",
"cloudformation:DescribeChangeSet",
"cloudformation:DescribeStackEvents",
"cloudformation:DescribeStackResource",
"cloudformation:DescribeStacks",
"cloudformation:ExecuteChangeSet",
"cloudformation:ListChangeSets",
"cloudformation:ListStackResources",
"cloudformation:UpdateStack",
"cloudformation:ValidateTemplate",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSubnets",
"ec2:DescribeVpcs",
"events:DescribeRule",
"events:PutRule",
"events:PutTargets",
"events:RemoveTargets",
"iam:AttachRolePolicy",
"iam:CreateRole",
"iam:DeleteRole",
"iam:DeleteRolePolicy",
"iam:DetachRolePolicy",
"iam:GetRole",
"iam:GetRolePolicy",
"iam:ListAttachedRolePolicies",
"iam:ListRolePolicies",
"iam:PassRole",
"iam:PutRolePolicy",
"iam:UpdateAssumeRolePolicy",
"lambda:AddPermission",
"lambda:CreateAlias",
"lambda:CreateFunction",
"lambda:DeleteFunction",
"lambda:DeleteProvisionedConcurrencyConfig",
"lambda:GetAccountSettings",
"lambda:GetAlias",
"lambda:GetEventSourceMapping",
"lambda:GetFunction",
"lambda:GetFunctionConfiguration",
"lambda:GetLayerVersion",
"lambda:GetLayerVersionPolicy",
"lambda:GetPolicy"
"lambda:GetProvisionedConcurrencyConfig",
"lambda:InvokeFunction",
"lambda:ListAliases",
"lambda:ListEventSourceMappings",
"lambda:ListFunctions",
"lambda:ListLayerVersions",
"lambda:ListLayers",
"lambda:ListProvisionedConcurrencyConfigs",
"lambda:ListTags",
"lambda:ListVersionsByFunction",
"lambda:PublishVersion",
"lambda:PutProvisionedConcurrencyConfig",
"lambda:RemovePermission",
"lambda:UpdateAlias",
"lambda:UpdateFunctionCode",
"lambda:UpdateFunctionConfiguration",
"logs:*",
"s3:CreateBucket",
"s3:DeleteBucket",
"s3:DeleteBucketPolicy",
"s3:DeleteBucketWebsite",
"s3:DeleteObject",
"s3:DeleteObjectVersion",
"s3:GetBucketLocation",
"s3:GetObject*",
"s3:ListBucket",
"s3:PutBucketPolicy",
"s3:PutEncryptionConfiguration",
"s3:PutObject",
"ssm:GetParameter",
"ssm:PutParameter",
"sts:GetCallerIdentity",
],
"Resource": "*"
}
]
}
It’s not quite as fine-grained as it could be, because
- I got a bit heavy handed with granting some perms, like
logs:*
- I trusted that all the perms in the sample policy are needed
- I haven’t restricted the perms to a given resource (not even sure this is possible or maintainable)
Anyway, I need to store this somewhere and this is the place for it. Hope it helps you and/or saves you time.