amazon-web-servicesamazon-sqsaws-event-bridge

How to specify SQS message attributes when used as AWS EventBridge (CloudWatch Events) target?


I want to use AWS EventBridge (CloudWatch Events) to send a message to SQS on a predefined schedule. The message body is irrelevant, but it does require several message attributes.

While creating this Events rule in CloudFormation I could not find any documentation on how to specify the message attributes. At the moment the resource looks like this -

ScheduledEvent:
  Type: AWS::Events::Rule
  Properties:
    RoleArn: !Ref ScheduledEventRole
    ScheduleExpression: !Ref ScheduledEventRule
    Targets:
    - Arn: !Ref Queue
      Id: !GetAtt Queue.Name
      Input: "message body"

What should be the message body so that attributes are sent to SQS?


Solution

  • Seems I'm a little late to the party, but here it goes:
    There, in fact, is a way to specify MessageAttributes of SQS message sent from the scheduler.

    However, to do so, you can't use SQS target for your schedule. You have to use the universal target (see https://docs.aws.amazon.com/scheduler/latest/UserGuide/managing-targets-universal.html).

    Set your scheduler target ARN to "arn:aws:scheduler:::aws-sdk:sqs:sendMessage", then you can specify a QueueUrl, Body and MessageAttributes as part of the schedule input:

    {
        "QueueUrl": "<SQS_QUEUE_ARN>",
        "MessageAttributes": {
            "<ATTRIBUTE_NAME>": {
                "DataType": "String",
                "StringValue": "<ATTRIBUTE_VALUE>"
            }
        },
        "Body": "<MESSAGE_BODY>"
    }
    

    Example (Terraform)

    resource "aws_scheduler_schedule" "testSchedule" {
      name                         = "test-ec1-schedule-weekly"
      schedule_expression          = "cron(0 3 ? * 2 *)"
      schedule_expression_timezone = "Europe/Prague"
    
      flexible_time_window {
        mode = "OFF"
      }
    
      target {
        # Set the universal target, instead of directly setting SQS queue URL
        arn      = "arn:aws:scheduler:::aws-sdk:sqs:sendMessage"
        role_arn = aws_iam_role.testSchedule.arn
    
        input = jsonencode({
          # Set the SQS queue URL here
          QueueUrl: aws_sqs_queue.testQueue.url,
          # And specify your MessageAttributes
          MessageAttributes: {
            myAttributeName: {
              DataType: "String",
              StringValue: "myAttributeValue",
            },
          },
          MessageBody: jsonencode({
            some: "payload",
          }),
        })
      }
    }
    

    Example (CloudFormation)

    (Just in case someone took your family hostage and is now forcing you to write CF...)

    ScheduledEvent:
      Type: AWS::Events::Rule
      Properties:
        RoleArn: !Ref ScheduledEventRole
        ScheduleExpression: !Ref ScheduledEventRule
        Targets:
        - Arn: "arn:aws:scheduler:::aws-sdk:sqs:sendMessage"
          Input: |
            {
              "QueueUrl": "<SQS_QUEUE_URL>",
              "MessageAttributes": {
                "myAttributeName": {
                  "DataType": "String",
                  "StringValue": "myAttributeValue"
                }
              },
              "MessageBody": "{\"foo\":\"bar\"}",
            }