IAM

IAM provides identity management in AWS. It can create users, roles and policies. For more information please refer to the official documentation.

For this workshop, every user will have an IAM user with access to the console and API credentials so it can bootstrap the serverless deployment.

Every user will only have access to its own resources. In order to do so, a separate Cloudformation stack creates all users according to its policy.

Here there are the policies that the user will have. Please note some AWS services won’t fully provide fine grained permission access level as of this time of writing.

IAMUserPolicy{{ loop.index }}:
Type: AWS::IAM::ManagedPolicy
Properties:
  ManagedPolicyName: user{{ loop.index }}-serverless-workshop-policy
  PolicyDocument:
    Version: '2012-10-17'
    Statement:
      - Action:
          - ec2:CreateNetworkInterface
          - ec2:DeleteNetworkInterface
          - ec2:DescribeNetworkInterfaces
          - dynamodb:List*
          - dynamodb:DescribeReservedCapacity
          - dynamodb:DescribeLimits
          - dynamodb:DescribeTimeToLive
          - cloudformation:DescribeStackEvents
          - cloudformation:ValidateTemplate
          - cloudformation:ListStacks
          - s3:GetEncryptionConfiguration
          - s3:PutEncryptionConfigurations
          - s3:PutBucketAcl
        Effect: Allow
        Resource: "*"

      - Action:
          - s3:*
        Effect: Allow
        Resource: "arn:aws:s3:::user{{ loop.index }}-dev*"

      - Action:
          - cloudformation:DescribeStacks
          - cloudformation:CreateStack
          - cloudformation:DescribeStackResource
          - cloudformation:DeleteStack
          - cloudformation:UpdateStack
          - cloudformation:ListStackResources
        Effect: Allow
        Resource: !Sub "arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/user{{ loop.index }}-dev/*"

      - Action:
          - iam:ChangePassword
        Effect: Allow
        Resource: !Sub "arn:aws:iam::${AWS::AccountId}:user/user{{ loop.index }}"

      - Action:
          - iam:GetRole
          - iam:CreateRole
          - iam:DeleteRole
          - iam:PassRole
          - iam:PutRolePolicy
          - iam:DeleteRolePolicy
          - iam:AttachRolePolicy
          - iam:DetachRolePolicy
        Effect: Allow
        Resource: !Sub "arn:aws:iam::${AWS::AccountId}:role/user{{ loop.index }}-dev-${AWS::Region}-lambdaRole"

      - Effect: Allow
        Action:
          - dynamodb:Query
          - dynamodb:Scan
          - dynamodb:Get*
          - dynamodb:PutItem
          - dynamodb:UpdateItem
          - dynamodb:DeleteTable
          - dynamodb:CreateTable
          - dynamodb:DeleteItem
          - dynamodb:DescribeTable
          - dynamodb:TagResource
        Resource: !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/user{{ loop.index }}"

      - Effect: Allow
        Action:
          - lambda:GetFunction
          - lambda:GetFunctionConfiguration
          - lambda:CreateFunction
          - lambda:DeleteFunction
          - lambda:AddPermission
          - lambda:ListVersionsByFunction
          - lambda:AddPermission
          - lambda:RemovePermission
          - lambda:PublishVersion
          - lambda:UpdateFunctionCode
          - lambda:UpdateFunctionConfiguration
        Resource: !Sub "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:user{{ loop.index }}*"

      - Effect: Allow
        Action:
          - events:PutRule
          - events:DeleteRule
          - events:DescribeRule
          - events:RemoveTargets
          - events:PutTargets
        Resource: !Sub "arn:aws:events:${AWS::Region}:${AWS::AccountId}:rule/user{{ loop.index }}-dev*"

      - Effect: Allow
        Action:
          - apigateway:*
        Resource: "*"

      - Effect: Allow
        Action:
          - logs:List*
          - logs:Describe*
          - logs:CreateLogGroup
          - logs:DeleteLogGroup
        Resource: "*"

      - Effect: Allow
        Action:
          - logs:*
        Resource: "*"
        Condition:
          StringLike:
            "logs:ResourceTag/user": "user{{ loop.index }}"