Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save NicolasRitouet/a4bb7d5db2ff0bbfd1a644fbd715d23f to your computer and use it in GitHub Desktop.
Save NicolasRitouet/a4bb7d5db2ff0bbfd1a644fbd715d23f to your computer and use it in GitHub Desktop.

Revisions

  1. @bsamuel-ui bsamuel-ui revised this gist Apr 17, 2018. 1 changed file with 79 additions and 35 deletions.
    114 changes: 79 additions & 35 deletions serverless-deploy-user.yaml
    Original file line number Diff line number Diff line change
    @@ -17,9 +17,9 @@ Parameters:
    # From https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateUser.html
    AllowedPattern: '[A-Za-z0-9+=,.@-]+' #'

    Project:
    Service:
    Description: >-
    A name for this serverless project
    A name for this serverless service.
    Type: String

    Stage:
    @@ -31,14 +31,27 @@ Parameters:
    Description: >-
    Allow the constructed user to invoke lambdas.
    Type: String
    AllowedValues:
    - 'allow'
    - 'deny'
    Default: 'deny'
    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]
    AllowInvoke: !Equals [!Ref MayInvoke, allow]
    UserFullPermissions: !Or [!Equals [!Ref MayDeployFunction, allow], !Equals [!Ref CreateCfnRole, ignore]]
    CreateCfnRole: !Equals [!Ref CreateCfnRole, create]

    Resources:

    @@ -48,7 +61,8 @@ Resources:
    UserName: !Ref UserName
    Policies: [] # Prefer managing policies separately.

    CfRole:
    CfnRole:
    Condition: CreateCfnRole
    Type: AWS::IAM::Role
    Properties:
    Policies: []
    @@ -63,11 +77,14 @@ Resources:
    - sts:AssumeRole

    DeployPolicy:
    Type: AWS::IAM::Policy # Or AWS::IAM::ManagedPolicy, also change PolicyName to ManagedPolicyName.
    # 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
    PolicyName: !Sub '${Project}-${Stage}-DeployPolicy'
    ManagedPolicyName: !Sub '${Service}-${Stage}-DeployPolicy'
    PolicyDocument:
    Version: 2012-10-17
    Statement:
    @@ -79,15 +96,15 @@ Resources:
    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:::${Project}-${Stage}-serverlessdeploymentbucket-*'
    - !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:::${Project}-${Stage}-serverlessdeploymentbucket-*/*'
    - !Sub 'arn:${AWS::Partition}:s3:::${Service}-${Stage}-serverlessdeploymentbucket-*/*'
    - Sid: ValidateTemplate
    Effect: Allow
    Action:
    @@ -102,54 +119,76 @@ Resources:
    - 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/${Project}-${Stage}/*'
    - !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/${Project}-${Stage}/*'
    - Sid: PassRoleToCloudFormation
    - !Sub 'arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${Service}-${Stage}/*'
    - Sid: GetLambdaRole
    Effect: Allow
    Action:
    - iam:PassRole
    - iam:GetRole
    Resource:
    - !GetAtt CfRole.Arn
    - Sid: GetCfRole
    - !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:GetRole
    - iam:PassRole
    Resource:
    - !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${Project}-${Stage}-${AWS::Region}-*-lambdaRole'
    - !GetAtt CfnRole.Arn

    UpdateServicePolicy:
    Type: AWS::IAM::Policy
    Type: AWS::IAM::ManagedPolicy
    Properties:
    Users:
    - !Ref DeployUser
    - !If [UserFullPermissions, !Ref DeployUser, !Ref 'AWS::NoValue']
    Roles:
    - !Ref CfRole
    PolicyName: !Sub '${Project}-${Stage}-UpdateServicePolicy'
    - !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:ListVersionsByFunction
    - lambda:PublishVersion
    - lambda:CreateAlias
    - lambda:DeleteAlias
    - lambda:UpdateAlias
    - lambda:AddPermission
    Resource:
    - !Sub 'arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${Project}-${Stage}*'
    - !Sub 'arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${Service}-${Stage}*'
    - Sid: CloudwatchEvents
    Effect: Allow
    Action:
    @@ -158,7 +197,7 @@ Resources:
    - events:Delete*
    - events:Describe*
    Resource:
    - !Sub 'arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:rule/${Project}-${Stage}*'
    - !Sub 'arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:rule/${Service}-${Stage}*'
    - Sid: CloudwatchLogs
    Effect: Allow
    Action:
    @@ -169,7 +208,7 @@ Resources:
    - logs:DescribeLogStreams
    - logs:FilterLogEvents
    Resource:
    - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${Project}-${Stage}*:log-stream:*'
    - !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${Service}-${Stage}*:log-stream:*'
    - Sid: CloudwatchLogGroups
    Effect: Allow
    Action:
    @@ -188,16 +227,16 @@ Resources:
    - iam:AttachRolePolicy
    - iam:DeleteRolePolicy
    Resource:
    - !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${Project}-${Stage}-${AWS::Region}-*-lambdaRole'
    - !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${Service}-${Stage}-${AWS::Region}-lambdaRole'

    ApiGwPolicy:
    Type: AWS::IAM::Policy
    Properties:
    Users:
    - !Ref DeployUser
    - !If [UserFullPermissions, !Ref DeployUser, !Ref 'AWS::NoValue']
    Roles:
    - !Ref CfRole
    PolicyName: !Sub '${Project}-${Stage}-InvokeLambdaPolicy'
    - !If [CreateCfnRole, !Ref CfnRole, !Ref 'AWS::NoValue']
    PolicyName: !Sub '${Service}-${Stage}-ApiGwPolicy'
    PolicyDocument:
    Version: 2012-10-17
    Statement:
    @@ -218,7 +257,7 @@ Resources:
    Properties:
    Users:
    - !Ref DeployUser
    PolicyName: !Sub '${Project}-${Stage}-InvokeLambdaPolicy'
    PolicyName: !Sub '${Service}-${Stage}-InvokeLambdaPolicy'
    PolicyDocument:
    Version: 2012-10-17
    Statement:
    @@ -227,4 +266,9 @@ Resources:
    Action:
    - lambda:InvokeFunction
    Resource:
    - !Sub 'arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${Project}-${Stage}*'
    - !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, '']
  2. @bsamuel-ui bsamuel-ui revised this gist Apr 16, 2018. 1 changed file with 103 additions and 12 deletions.
    115 changes: 103 additions & 12 deletions serverless-deploy-user.yaml
    Original file line number Diff line number Diff line change
    @@ -15,7 +15,7 @@ Parameters:
    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+=,.@-]+'
    AllowedPattern: '[A-Za-z0-9+=,.@-]+' #'

    Project:
    Description: >-
    @@ -27,8 +27,18 @@ Parameters:
    The stage for this project.
    Type: String

    MayInvoke:
    Description: >-
    Allow the constructed user to invoke lambdas.
    Type: String
    AllowedValues:
    - 'allow'
    - 'deny'
    Default: 'deny'

    Conditions: {} # In case we want some...
    Conditions:
    AllowInvoke:
    !Equals [!Ref MayInvoke, allow]

    Resources:

    @@ -38,7 +48,7 @@ Resources:
    UserName: !Ref UserName
    Policies: [] # Prefer managing policies separately.

    ServerlessRole:
    CfRole:
    Type: AWS::IAM::Role
    Properties:
    Policies: []
    @@ -93,7 +103,6 @@ Resources:
    Resource:
    # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-iam-template.html
    - !Sub 'arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${Project}-${Stage}/*'

    - Sid: WriteAccessToCloudFormation
    Effect: Allow
    Action:
    @@ -102,38 +111,120 @@ Resources:
    - cloudformation:DeleteStack
    Resource:
    - !Sub 'arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${Project}-${Stage}/*'

    - Sid: PassRoleToCloudFormation
    Effect: Allow
    Action:
    - iam:PassRole
    Resource:
    - !GetAtt ServerlessRole.Arn
    - Sid: GetServerlessRole
    - !GetAtt CfRole.Arn
    - Sid: GetCfRole
    Effect: Allow
    Action:
    - iam:GetRole
    Resource:
    - !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${Project}-${Stage}-${AWS::Region}-*'
    - !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${Project}-${Stage}-${AWS::Region}-*-lambdaRole'

    UpdateLambdaPolicy:
    UpdateServicePolicy:
    Type: AWS::IAM::Policy
    Properties:
    Users:
    - !Ref DeployUser
    Roles:
    - !Ref ServerlessRole
    PolicyName: !Sub '${Project}-${Stage}-UpdateLambdaPolicy'
    - !Ref CfRole
    PolicyName: !Sub '${Project}-${Stage}-UpdateServicePolicy'
    PolicyDocument:
    Version: 2012-10-17
    Statement:
    - Sid: UpdateLambdaPolicy
    - Sid: Lambdas
    Effect: Allow
    Action:
    - lambda:Get*
    - lambda:List*
    - lambda:UpdateFunctionCode
    - lambda:UpdateFunctionConfiguration
    - lambda:ListVersionsByFunction
    - lambda:PublishVersion
    - lambda:CreateAlias
    - lambda:DeleteAlias
    - lambda:UpdateAlias
    - lambda:AddPermission
    Resource:
    - !Sub 'arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${Project}-${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/${Project}-${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/${Project}-${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/${Project}-${Stage}-${AWS::Region}-*-lambdaRole'

    ApiGwPolicy:
    Type: AWS::IAM::Policy
    Properties:
    Users:
    - !Ref DeployUser
    Roles:
    - !Ref CfRole
    PolicyName: !Sub '${Project}-${Stage}-InvokeLambdaPolicy'
    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 '${Project}-${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:${Project}-${Stage}*'
  3. @bsamuel-ui bsamuel-ui revised this gist Apr 16, 2018. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion serverless-deploy-user.yaml
    Original file line number Diff line number Diff line change
    @@ -90,7 +90,6 @@ Resources:
    - cloudformation:List*
    - cloudformation:Get*
    - cloudformation:PreviewStackUpdate
    - cloudformation:ValidateTemplate
    Resource:
    # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-iam-template.html
    - !Sub 'arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${Project}-${Stage}/*'
  4. @bsamuel-ui bsamuel-ui created this gist Apr 16, 2018.
    140 changes: 140 additions & 0 deletions serverless-deploy-user.yaml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,140 @@
    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+=,.@-]+'

    Project:
    Description: >-
    A name for this serverless project
    Type: String

    Stage:
    Description: >-
    The stage for this project.
    Type: String


    Conditions: {} # In case we want some...

    Resources:

    DeployUser:
    Type: AWS::IAM::User
    Properties:
    UserName: !Ref UserName
    Policies: [] # Prefer managing policies separately.

    ServerlessRole:
    Type: AWS::IAM::Role
    Properties:
    Policies: []
    AssumeRolePolicyDocument:
    Version: 2012-10-17
    Statement:
    - Effect: Allow
    Principal:
    Service:
    - !Sub 'cloudformation.${AWS::URLSuffix}'
    Action:
    - sts:AssumeRole

    DeployPolicy:
    Type: AWS::IAM::Policy # Or AWS::IAM::ManagedPolicy, also change PolicyName to ManagedPolicyName.
    Properties:
    Users:
    - !Ref DeployUser
    PolicyName: !Sub '${Project}-${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:::${Project}-${Stage}-serverlessdeploymentbucket-*'
    - Sid: ReadWriteAccessToDeploymentObjects
    Effect: Allow
    Action:
    - s3:GetObject*
    - s3:PutObject
    - s3:DeleteObject
    Resource:
    - !Sub 'arn:${AWS::Partition}:s3:::${Project}-${Stage}-serverlessdeploymentbucket-*/*'
    - Sid: ValidateTemplate
    Effect: Allow
    Action:
    - cloudformation:ValidateTemplate
    Resource: '*'
    - Sid: ReadAccessToCloudFormation
    Effect: Allow
    Action:
    - cloudformation:Describe*
    - cloudformation:List*
    - cloudformation:Get*
    - cloudformation:PreviewStackUpdate
    - cloudformation:ValidateTemplate
    Resource:
    # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-iam-template.html
    - !Sub 'arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${Project}-${Stage}/*'

    - Sid: WriteAccessToCloudFormation
    Effect: Allow
    Action:
    - cloudformation:CreateStack
    - cloudformation:UpdateStack
    - cloudformation:DeleteStack
    Resource:
    - !Sub 'arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${Project}-${Stage}/*'

    - Sid: PassRoleToCloudFormation
    Effect: Allow
    Action:
    - iam:PassRole
    Resource:
    - !GetAtt ServerlessRole.Arn
    - Sid: GetServerlessRole
    Effect: Allow
    Action:
    - iam:GetRole
    Resource:
    - !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${Project}-${Stage}-${AWS::Region}-*'

    UpdateLambdaPolicy:
    Type: AWS::IAM::Policy
    Properties:
    Users:
    - !Ref DeployUser
    Roles:
    - !Ref ServerlessRole
    PolicyName: !Sub '${Project}-${Stage}-UpdateLambdaPolicy'
    PolicyDocument:
    Version: 2012-10-17
    Statement:
    - Sid: UpdateLambdaPolicy
    Effect: Allow
    Action:
    - lambda:Get*
    - lambda:List*
    - lambda:UpdateFunctionCode
    - lambda:UpdateFunctionConfiguration
    - lambda:InvokeFunction
    Resource:
    - !Sub 'arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${Project}-${Stage}*'