Search code examples
aws-lambdayamlaws-cloudformation

how to use !Sub for array of arn in cloudformation


I have function defined like this:

Type: AWS::Serverless::Function
Properties:
  FunctionName: !Join
    - "-"
    - - !Ref NamePrefix
      - !FindInMap [ NameMap, SEND-SES-EMAIL-FUNCTION, NAME ]
      - !Ref NamePostfix
  Description: "Lambda function to send email with CSV file through SES"
  CodeUri: source/resources/sendSESEmailFunction
  Handler: sendSESEmail.lambda_handler
  Policies:
    - AWSLambdaBasicExecutionRole
    - Version: 2012-10-17
      Statement:
        - Sid: SESPermissions
          Effect: Allow
          Action:
            - 'ses:SendEmail'
          Resource:
            - !Sub
            - 'arn:aws:ses:${AWS::Region}:${SESAccountID}:identity/${SenderEmail}'
            - SenderEmail: !Ref SenderSESEmail
              SESAccountID: !Ref SESAccountID
            - !Sub
            - 'arn:aws:ses:${AWS::Region}:${SESAccountID}:identity/${ReceiverEmail}'
            - ReceiverEmail: 'testing'
              SESAccountID: !Ref SESAccountID

My goal is to use !Sub on multiple ARN's under Resource of Lambda policy but this is throwing error like this: Syntax errors in policy. (Service:
AmazonIdentityManagement; Status Code: 400; Error Code: MalformedPolicyDocument


Solution

  • If you look at your policy, Resource takes a list of resource ARNs which you're creating with Fn::Sub. But SenderEmail and ReceiverEmail are defined as separate items in the list of Resource not within the !Sub to which they apply.

    The correct structure would be:

                  Resource:
                    - !Sub 
                      - 'arn:aws:ses:${AWS::Region}:${SESAccountID}:identity/${SenderEmail}'
                      - SenderEmail: !Ref SenderSESEmail
                        SESAccountID: !Ref SESAccountID
                    - !Sub
                      -'arn:aws:ses:${AWS::Region}:${SESAccountID}:identity/${ReceiverEmail}'
                      - ReceiverEmail: 'testing'
    

    I've always found the !Sub syntax confusing. This is the alternative which makes the structure more clear:

                  Resource:
                    - Fn::Sub: 
                      - 'arn:aws:ses:${AWS::Region}:${SESAccountID}:identity/${SenderEmail}'
                      - SenderEmail: !Ref SenderSESEmail
                        SESAccountID: !Ref SESAccountID
                    - Fn::Sub:
                      -'arn:aws:ses:${AWS::Region}:${SESAccountID}:identity/${ReceiverEmail}'
                      - ReceiverEmail: 'testing'