Skip to content
Merged
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
- None

## New features
- None
- Add AWS SQS alerter for sending alerts to Amazon Simple Queue Service queues - [#1750](https://github.com/jertel/elastalert2/pull/1750) - @AnthraX1

## Other changes
- [Docs] Clarified Slack webhook URL documentation as it related to legacy vs app webhooks - [#1745](https://github.com/jertel/elastalert2/pull/1745) - @jertel
Expand Down
41 changes: 41 additions & 0 deletions docs/source/alerts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,47 @@ Example When to use aws_profile usage::
sns_topic_arn: 'arn:aws:sns:us-east-1:123456789:somesnstopic'
sns_aws_profile: 'default'

AWS SQS (Amazon Simple Queue Service)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The AWS SQS alerter will send an alert message to an AWS SQS queue as a JSON object containing the rule name, matches, and alert text.
The AWS SQS alerter uses boto3 and can use credentials in the rule yaml, in a standard AWS credential and config files, or
via environment variables. See http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html for details.

Messages that exceed the SQS 1 MB size limit will be automatically truncated.

If ``sqs_aws_region`` is not set in the rule, the region will be automatically inferred from the SQS queue URL (for example, ``https://sqs.eu-west-1.amazonaws.com/...`` will use ``eu-west-1``).

AWS SQS requires one option:

``sqs_queue_url``: The URL of the SQS queue. For example, ``https://sqs.us-east-1.amazonaws.com/123456789012/my-queue``

Optional:

``sqs_aws_access_key_id``: An access key to connect to SQS with.

``sqs_aws_secret_access_key``: The secret key associated with the access key.

``sqs_aws_region``: The AWS region in which the SQS resource is located. Default is us-east-1

``sqs_aws_profile``: The AWS profile to use. If none specified, the default will be used.

Example when not using aws_profile::

alert:
- sqs
sqs_queue_url: 'https://sqs.us-east-1.amazonaws.com/123456789012/my-queue'
sqs_aws_access_key_id: 'XXXXXXXXXXXXXXXXXX'
sqs_aws_secret_access_key: 'YYYYYYYYYYYYYYYYYYYY'
sqs_aws_region: 'us-east-1'

Example when using aws_profile::

alert:
- sqs
sqs_queue_url: 'https://sqs.us-east-1.amazonaws.com/123456789012/my-queue'
sqs_aws_profile: 'default'

Chatwork
~~~~~~~~

Expand Down
1 change: 1 addition & 0 deletions docs/source/elastalert.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Currently, we have support built in for these alert types:
- Alertmanager
- AWS SES (Amazon Simple Email Service)
- AWS SNS (Amazon Simple Notification Service)
- AWS SQS (Amazon Simple Queue Service)
- Chatwork
- Command
- Datadog
Expand Down
83 changes: 83 additions & 0 deletions elastalert/alerters/sqs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import boto3
import json
from urllib.parse import urlparse

from elastalert.alerts import Alerter
from elastalert.util import elastalert_logger, EAException


def _get_region_from_sqs_url(queue_url, default_region="us-east-1"):
"""Infer the AWS region from an SQS queue URL like
https://sqs.us-east-1.amazonaws.com/123456789012/my-queue.
Falls back to default_region if it cannot be determined.
"""
host = urlparse(queue_url).hostname or ""
parts = host.split(".")
if len(parts) >= 3 and parts[0] == "sqs":
return parts[1]
return default_region


class SqsAlerter(Alerter):
"""Send alert using AWS SQS service"""

required_options = frozenset(["sqs_queue_url"])

def __init__(self, *args):
super(SqsAlerter, self).__init__(*args)
self.sqs_queue_url = self.rule.get("sqs_queue_url", None)
self.sqs_aws_access_key_id = self.rule.get("sqs_aws_access_key_id")
self.sqs_aws_secret_access_key = self.rule.get("sqs_aws_secret_access_key")
explicit_region = self.rule.get("sqs_aws_region")
if explicit_region:
self.sqs_aws_region = explicit_region
else:
# If no region is configured explicitly, derive it from the queue URL.
self.sqs_aws_region = _get_region_from_sqs_url(self.sqs_queue_url or "")
self.profile = self.rule.get("sqs_aws_profile", None)

def alert(self, matches):
# Create the alert as a JSON object
alert_data = {
"rule_name": self.rule["name"],
"matches": matches,
}
alert_text = self.create_alert_body(matches)
# SQS message body limit is 1 MB; crop text at ~800KB to be safe
if len(alert_text) > 800000:
alert_text = alert_text[:800000]
alert_text += "\n*message was cropped according to SQS limits!*"
alert_data["text"] = alert_text
body = json.dumps(alert_data, default=str)

# If the body is still too long, remove the text field
if len(body) > 1048576:
alert_data["text"] = "Text message omitted due to SQS size limit."
body = json.dumps(alert_data, default=str)
try:
# Always create the session in the configured region. SQS does not
# infer the region from the queue URL; the client region must match.
if self.profile is None:
session = boto3.Session(
aws_access_key_id=self.sqs_aws_access_key_id,
aws_secret_access_key=self.sqs_aws_secret_access_key,
region_name=self.sqs_aws_region,
)
else:
session = boto3.Session(
profile_name=self.profile,
region_name=self.sqs_aws_region,
)

sqs_client = session.client("sqs")

response = sqs_client.send_message(
QueueUrl=self.sqs_queue_url,
MessageBody=body,
)
except Exception as e:
raise EAException("Error sending Amazon SQS: %s" % e)
elastalert_logger.info("Sent Amazon SQS message to %s, MessageId: %s" % (self.sqs_queue_url, response.get("MessageId")))

def get_info(self):
return {"type": "sqs"}
2 changes: 2 additions & 0 deletions elastalert/loaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
from elastalert.alerters.slack import SlackAlerter
from elastalert.alerters.smseagle import SMSEagleAlerter
from elastalert.alerters.sns import SnsAlerter
from elastalert.alerters.sqs import SqsAlerter
from elastalert.alerters.teams import MsTeamsAlerter
from elastalert.alerters.powerautomate import MsPowerAutomateAlerter
from elastalert.alerters.yzj import YzjAlerter
Expand Down Expand Up @@ -115,6 +116,7 @@ class RulesLoader(object):
'debug': elastalert.alerters.debug.DebugAlerter,
'command': elastalert.alerters.command.CommandAlerter,
'sns': SnsAlerter,
'sqs': SqsAlerter,
'ms_teams': MsTeamsAlerter,
'ms_power_automate': MsPowerAutomateAlerter,
'slack': SlackAlerter,
Expand Down
7 changes: 7 additions & 0 deletions elastalert/schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,13 @@ properties:
sns_aws_region: {type: string}
sns_aws_profile: {type: string}

### AWS SQS
sqs_queue_url: {type: string}
sqs_aws_access_key_id: {type: string}
sqs_aws_secret_access_key: {type: string}
sqs_aws_region: {type: string}
sqs_aws_profile: {type: string}

### Chatwork
chatwork_apikey: {type: string}
chatwork_room_id: {type: string}
Expand Down
Loading