Last active
June 5, 2019 17:20
-
-
Save bsamuel-ui/df0eff41160243ca23a2bad58ac7b08f to your computer and use it in GitHub Desktop.
Cloudformation template to deploy permissions for deploying a serverless project.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
AWSTemplateFormatVersion: 2010-09-09 | |
Description: > | |
Constructs a managed IAM policy to deploy a serverless project. | |
This template assumes the stack is being deployed in the current region and account. | |
You can then attach this policy to other IAM objects, such as users or roles. | |
Based on the work done in: https://github.com/serverless/serverless/issues/1439 | |
Parameters: | |
UserName: | |
Description: >- | |
The name of the IAM User to construct. | |
Type: String | |
# From https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateUser.html | |
AllowedPattern: '[A-Za-z0-9+=,.@-]+' #' | |
Service: | |
Description: >- | |
A name for this serverless service. | |
Type: String | |
Stage: | |
Description: >- | |
The stage for this project. | |
Type: String | |
MayInvoke: | |
Description: >- | |
Allow the constructed user to invoke lambdas. | |
Type: String | |
AllowedValues: [allow, deny] | |
Default: deny | |
MayDeployFunction: | |
Description: >- | |
Allow the user to deploy a single function. This is ignored if you don't create a CfnRole. | |
Type: String | |
AllowedValues: [allow, deny] | |
Default: allow | |
CreateCfnRole: | |
Description: >- | |
Create a role to assign to the `provider.cfnRole` variable, rather than rely on the user's permissions. | |
Type: String | |
AllowedValues: [create, skip] | |
Default: skip | |
Conditions: | |
AllowInvoke: !Equals [!Ref MayInvoke, allow] | |
UserFullPermissions: !Or [!Equals [!Ref MayDeployFunction, allow], !Equals [!Ref CreateCfnRole, ignore]] | |
CreateCfnRole: !Equals [!Ref CreateCfnRole, create] | |
Resources: | |
DeployUser: | |
Type: AWS::IAM::User | |
Properties: | |
UserName: !Ref UserName | |
Policies: [] # Prefer managing policies separately. | |
CfnRole: | |
Condition: CreateCfnRole | |
Type: AWS::IAM::Role | |
Properties: | |
Policies: [] | |
AssumeRolePolicyDocument: | |
Version: 2012-10-17 | |
Statement: | |
- Effect: Allow | |
Principal: | |
Service: | |
- !Sub 'cloudformation.${AWS::URLSuffix}' | |
Action: | |
- sts:AssumeRole | |
DeployPolicy: | |
# Cumulative inline policy size cannot exceed 2,048 characters for IAM Users. | |
# Cloudformation will hang waiting for an update exceeding this amount to complete. | |
# https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-limits.html | |
Type: AWS::IAM::ManagedPolicy | |
Properties: | |
Users: | |
- !Ref DeployUser | |
ManagedPolicyName: !Sub '${Service}-${Stage}-DeployPolicy' | |
PolicyDocument: | |
Version: 2012-10-17 | |
Statement: | |
- Sid: ListDeploymentBucket | |
Effect: Allow | |
Action: | |
- s3:GetBucketLocation | |
- s3:ListBucket | |
Resource: | |
# See https://docs.aws.amazon.com/AmazonS3/latest/dev/s3-arn-format.html | |
# Also https://docs.aws.amazon.com/govcloud-us/latest/UserGuide/using-govcloud-arns.html | |
- !Sub 'arn:${AWS::Partition}:s3:::${Service}-${Stage}-serverlessdeploymentbucket-*' | |
- Sid: ReadWriteAccessToDeploymentObjects | |
Effect: Allow | |
Action: | |
- s3:GetObject* | |
- s3:PutObject | |
- s3:DeleteObject | |
Resource: | |
- !Sub 'arn:${AWS::Partition}:s3:::${Service}-${Stage}-serverlessdeploymentbucket-*/*' | |
- Sid: ValidateTemplate | |
Effect: Allow | |
Action: | |
- cloudformation:ValidateTemplate | |
Resource: '*' | |
- Sid: ReadAccessToCloudFormation | |
Effect: Allow | |
Action: | |
- cloudformation:Describe* | |
- cloudformation:List* | |
- cloudformation:Get* | |
- cloudformation:PreviewStackUpdate | |
Resource: | |
# https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-iam-template.html | |
- !Sub 'arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${Service}-${Stage}/*' | |
- Sid: WriteAccessToCloudFormation | |
Effect: Allow | |
Action: | |
- cloudformation:CreateStack | |
- cloudformation:UpdateStack | |
- cloudformation:DeleteStack | |
Resource: | |
- !Sub 'arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${Service}-${Stage}/*' | |
- Sid: GetLambdaRole | |
Effect: Allow | |
Action: | |
- iam:GetRole | |
Resource: | |
- !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${Service}-${Stage}-${AWS::Region}-lambdaRole' | |
DeployViaRole: | |
Condition: CreateCfnRole | |
Type: AWS::IAM::Policy | |
Properties: | |
Users: | |
- !Ref DeployUser | |
PolicyName: !Sub '${Service}-${Stage}-DeployViaRole' | |
PolicyDocument: | |
Version: 2012-10-17 | |
Statement: | |
- Sid: PassRoleToCloudFormation | |
Effect: Allow | |
Action: | |
- iam:PassRole | |
Resource: | |
- !GetAtt CfnRole.Arn | |
UpdateServicePolicy: | |
Type: AWS::IAM::ManagedPolicy | |
Properties: | |
Users: | |
- !If [UserFullPermissions, !Ref DeployUser, !Ref 'AWS::NoValue'] | |
Roles: | |
- !If [CreateCfnRole, !Ref CfnRole, !Ref 'AWS::NoValue'] | |
ManagedPolicyName: !Sub '${Service}-${Stage}-UpdateServicePolicy' | |
PolicyDocument: | |
Version: 2012-10-17 | |
Statement: | |
- Sid: DropDeploymentBucket | |
Effect: Allow | |
Action: | |
- s3:DeleteBucket | |
Resource: | |
- !Sub 'arn:${AWS::Partition}:s3:::${Service}-${Stage}-serverlessdeploymentbucket-*' | |
- Sid: ReadAccessToDeploymentObjects | |
Effect: Allow | |
Action: | |
- s3:GetObject* | |
Resource: | |
- !Sub 'arn:${AWS::Partition}:s3:::${Service}-${Stage}-serverlessdeploymentbucket-*/*' | |
- Sid: Lambdas | |
Effect: Allow | |
Action: | |
- lambda:Get* | |
- lambda:List* | |
- lambda:UpdateFunctionCode | |
- lambda:UpdateFunctionConfiguration | |
- lambda:PublishVersion | |
- lambda:CreateAlias | |
- lambda:DeleteAlias | |
- lambda:UpdateAlias | |
- lambda:AddPermission | |
Resource: | |
- !Sub 'arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${Service}-${Stage}*' | |
- Sid: CloudwatchEvents | |
Effect: Allow | |
Action: | |
- events:Put* | |
- events:Remove* | |
- events:Delete* | |
- events:Describe* | |
Resource: | |
- !Sub 'arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:rule/${Service}-${Stage}*' | |
- Sid: CloudwatchLogs | |
Effect: Allow | |
Action: | |
- logs:CreateLogGroup | |
- logs:CreateLogStream | |
- logs:DeleteLogGroup | |
- logs:DeleteLogStream | |
- logs:DescribeLogStreams | |
- logs:FilterLogEvents | |
Resource: | |
- !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${Service}-${Stage}*:log-stream:*' | |
- Sid: CloudwatchLogGroups | |
Effect: Allow | |
Action: | |
- logs:DescribeLogGroups | |
Resource: | |
- !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group::log-stream:*' | |
- Sid: IamRole | |
Effect: Allow | |
Action: | |
- iam:GetRole | |
- iam:PassRole | |
- iam:CreateRole | |
- iam:DeleteRole | |
- iam:DetachRolePolicy | |
- iam:PutRolePolicy | |
- iam:AttachRolePolicy | |
- iam:DeleteRolePolicy | |
Resource: | |
- !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${Service}-${Stage}-${AWS::Region}-lambdaRole' | |
ApiGwPolicy: | |
Type: AWS::IAM::Policy | |
Properties: | |
Users: | |
- !If [UserFullPermissions, !Ref DeployUser, !Ref 'AWS::NoValue'] | |
Roles: | |
- !If [CreateCfnRole, !Ref CfnRole, !Ref 'AWS::NoValue'] | |
PolicyName: !Sub '${Service}-${Stage}-ApiGwPolicy' | |
PolicyDocument: | |
Version: 2012-10-17 | |
Statement: | |
- Sid: ApiGwEvents | |
Effect: Allow | |
Action: | |
- apigateway:GET | |
- apigateway:POST | |
- apigateway:PUT | |
- apigateway:DELETE | |
Resource: | |
- !Sub 'arn:${AWS::Partition}:apigateway:${AWS::Region}:::/restapis' | |
- !Sub 'arn:${AWS::Partition}:apigateway:${AWS::Region}:::/restapis/*' | |
InvokeLambdaPolicy: | |
Condition: AllowInvoke | |
Type: AWS::IAM::Policy | |
Properties: | |
Users: | |
- !Ref DeployUser | |
PolicyName: !Sub '${Service}-${Stage}-InvokeLambdaPolicy' | |
PolicyDocument: | |
Version: 2012-10-17 | |
Statement: | |
- Sid: InvokeFunction | |
Effect: Allow | |
Action: | |
- lambda:InvokeFunction | |
Resource: | |
- !Sub 'arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${Service}-${Stage}*' | |
Outputs: | |
cfnRole: | |
Description: 'The `provider.cfnRole` value to use, or empty string if no role was created.' | |
Value: !If [CreateCfnRole, !GetAtt CfnRole.Arn, ''] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment