Adding PermissionBoundary fails in SAM template

2019-08-25 17:43发布

问题:

Below is the SAM template:

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function 
    Properties:
      CodeUri: hello-world/
      Handler: app.LambdaHandler
      Runtime: nodejs8.10
      Events:
        MySQSEvent:
          Type: SQS
          Properties:
            Queue: !GetAtt SomeQueue.Arn
            BatchSize: 10
      PermissionsBoundary: "arn:aws:iam::${AWS::AccountId}:policy/AddPermission"

  SomeQueue:
    Type: AWS::SQS::Queue

  AddPermission:
    Type: AWS::IAM::ManagedPolicy
    Properties:
      PolicyDocument: 
        Version: 2012-10-17
        Statement: 
          - Sid: "PermissionBoundaryForLogGroup"
            Effect: "Allow"
            Action: 
            - "logs:CreateLogGroup"
            Resource:
              - !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:*"

that gives below error:

{
            "StackId": "arn:aws:cloudformation:us-east-1:285774445527:stack/somestack/f986eb30-a5a0-11e9-9771-1273bfab49fc", 
            "EventId": "cb4be9e0-a682-11e9-bac4-12d48e821f84", 
            "ResourceStatus": "UPDATE_ROLLBACK_IN_PROGRESS", 
            "ResourceType": "AWS::CloudFormation::Stack", 
            "Timestamp": "2019-07-14T22:00:29.808Z", 
            "ResourceStatusReason": "The following resource(s) failed to create: [AddPermission]. The following resource(s) failed to update: [HelloWorldFunctionRole]. ", 
            "StackName": "pocstack", 
            "PhysicalResourceId": "arn:aws:cloudformation:us-east-1:285774445527:stack/somestack/f986eb30-a5a0-11e9-9771-1273bfab49fc", 
            "LogicalResourceId": "pocstack"
        }, 
        {
            "StackId": "arn:aws:cloudformation:us-east-1:285774445527:stack/pocstack/f986eb30-a5a0-11e9-9771-1273bfab49fc", 
            "EventId": "AddPermission-CREATE_FAILED-2019-07-14T22:00:29.100Z", 
            "ResourceStatus": "CREATE_FAILED", 
            "ResourceType": "AWS::IAM::ManagedPolicy", 
            "Timestamp": "2019-07-14T22:00:29.100Z", 
            "ResourceStatusReason": "Resource creation cancelled", 
            "StackName": "pocstack", 
            "ResourceProperties": "{\"PolicyDocument\":{\"Version\":\"2012-10-17\",\"Statement\":[{\"Action\":[\"logs:CreateLogGroup\"],\"Resource\":[\"arn:aws:logs:us-east-1:285774445527:log-group:*\"],\"Effect\":\"Allow\",\"Sid\":\"PermissionBoundaryForLogGroup\"}]}}", 
            "PhysicalResourceId": "arn:aws:iam::285774445527:policy/somestack-AddPermission-GKXVOXLQARLR", 
            "LogicalResourceId": "AddPermission"
        }, 

If I use the new stack, then the error is: "ResourceStatusReason": "Resource creation cancelled"

Why Managed policy by name AddPermission fails to get created?

回答1:

There are few issues with this.

First, you can't hard code resource name of AddPermission like that

PermissionsBoundary: "arn:aws:iam::${AWS::AccountId}:policy/AddPermission"

because you don't know the actual name of the resource that will be created. It will be something like this

arn:aws:iam::859119227216:policy/test-permissions-AddPermission-CK3PYCO10NV1

with the random string at the end. Correct way to reference it is via Ref function.

PermissionsBoundary: !Ref AddPermission

Another issue is that you are creating SQS poller lambda function but your permission boundaries block SQS permissions therefore the stack will fail to create that lambda function.

You will need to add something like this to your permission boundaries (of course, you don't need to add full SQS permissions to any resource, just enough for function to work with a particular queue).

- Sid: 'AllowReadSQSMessages'
  Effect: 'Allow'
  Action:
      - 'sqs:*'
  Resource: '*'

Here is full template that works (assuming correct code location and handler name but feel free to change it).

Transform: 'AWS::Serverless-2016-10-31'
Resources:
    HelloWorldFunction:
        Type: AWS::Serverless::Function
        Properties:
            CodeUri: ./src
            Handler: index.handler
            Runtime: nodejs8.10
            Events:
                MySQSEvent:
                    Type: SQS
                    Properties:
                        Queue: !GetAtt SomeQueue.Arn
                        BatchSize: 10
            PermissionsBoundary: !Ref AddPermission

    SomeQueue:
        Type: AWS::SQS::Queue

    AddPermission:
        Type: AWS::IAM::ManagedPolicy
        Properties:
            PolicyDocument:
                Version: 2012-10-17
                Statement:
                    - Sid: 'PermissionBoundaryForLogGroup'
                      Effect: 'Allow'
                      Action:
                          - 'logs:CreateLogGroup'
                      Resource:
                          - !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:*'
                    - Sid: 'AllowReadSQSMessages'
                      Effect: 'Allow'
                      Action:
                          - 'sqs:*'
                      Resource: '*'

While this will work, be sure that you understand what you are doing. Permission boundaries will block any additional permissions that are not part of it. For example, SAM would automatically create necessary permissions for CW Logs. Those are

  • logs:CreateLogGroup
  • logs:CreateLogStream
  • logs:PutLogEvents

You have allowed only logs:CreateLogGroup in your permission boundaries, hence your function will not be able to log anything to CloudWatch.