Friday, December 4, 2020

AWS EventBridge to SQS

How to create new EventBridge (CloudWatch Events) to send message to existing SQS queue

Event to SQS

If you want to send alerts directly from EventBridge to SQS, you must modify your SQS to accept it from the Rule. 

{
  "Sid": "EventsToMyQueue",
  "Effect": "Allow",
  "Principal": {
     "Service": "events.amazonaws.com"
  },
  "Action": "sqs:SendMessage",
  "Resource": "arn:aws:sqs:region:account-id:queue-name",
  "Condition": {
    "ArnEquals": {
      "aws:SourceArn": "arn:aws:events:region:account-id:rule/rule-name"
    }
  }
}

Reference: SQS Permissions.

This is fine if you know the arn of the rule in advance. However, if you require this SQS queue to receive messages from rules unknown and you want to limit who or what can send to this queue then you can't seem to use direct to SQS. 

Because we're on an AWS Org, I tried this rule instead but unfortunately, services doesn't bring the necessary PrincipalOrgId information. Or I did it wrong... 

{
      "Sid": "doesnt_work",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "sqs:SendMessage",
      "Resource": "arn:aws:sqs:region:account-id:queue-name",
      "Condition": {
        "StringEquals": {
          "aws:PrincipalOrgID": "o-9999999999"
        }
      }
    }

Event to Lambda to SQS

Instead of sending directly to SQS, we can create a Lambda in conjunction with EventBridge rule and attach the necessary role with permission onto the Lambda function and then use PrincipalOrgId condition from SQS.

When you create your EventBridge and Lambda target, following permission needs to be attached to the Lambda.

{
  "Effect": "Allow",
  "Action": "lambda:InvokeFunction",
  "Resource": "arn:aws:lambda:region:account-id:function:function-name",
  "Principal": {
    "Service": "events.amazonaws.com"
  },
  "Condition": {
    "ArnLike": {
      "AWS:SourceArn": "arn:aws:events:region:account-id:rule/rule-name"
    }
  },
  "Sid": "InvokeLambdaFunction"
}

Reference: Lambda Permissions.

And the IAM Role attached to the Lambda function needs to have (at least) this policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "SidOrgLook",
            "Effect": "Allow",
            "Action": "sqs:SendMessage",
            "Resource": "arn:aws:sqs:region:account-id:queue-name"
        }
    ]
}

The lambda would have a function like this to send to queue:

def send_message(message,region):
    queue_name = os.environ.get("queue_name","generic_queue")
    sqs = boto3.resource('sqs', region_name = region)
    try:
        queue = sqs.get_queue_by_name(QueueName=queue_name)
    except:
        print("Error in fetching queue from name")
        return False
    try:
        response = queue.send_message(MessageBody=message)
    except:
        print("Error sending message")
        return False
    return response.get('MessageId')

Then the SQS itself has this Access Policy:

    {
      "Sid": "sqsQueueOrgSendPolicy",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": [
        "SQS:SendMessage"
      ],
      "Resource": "arn:aws:sqs:region:account-id:queue-name",
      "Condition": {
        "StringEquals": {
          "aws:PrincipalOrgID": "o-9999999999"
        }
      }
    

Don't copy & paste policy into SQS Access Policy Web Console. I kept running into invalid JSON error. Do it using API call instead. 

AWS WAF log4j query

How to query AWS WAF log for log4j attacks 1. Setup your Athena table using this instruction https://docs.aws.amazon.com/athena/latest/ug/wa...