Skip to content

Commit

Permalink
Merge pull request #1505 from marssilva/powerautomate
Browse files Browse the repository at this point in the history
[Powerautomate] New Alert Channel with Microsoft Power Automate
  • Loading branch information
jertel authored Jul 28, 2024
2 parents 6b58dc3 + 96c191c commit b5eb6bc
Show file tree
Hide file tree
Showing 7 changed files with 829 additions and 1 deletion.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
- TBD

## New features
- TBD
- [MS Power Automate] New Alert Channel with Microsoft Power Automate - [#1505](https://github.com/jertel/elastalert2/pull/1505) - @marssilva

## Other changes
- [Indexer] Fixed fields types error on instance indexer_alert_config in schema.yml - [#1499](https://github.com/jertel/elastalert2/pull/1499) - @olehpalanskyi
Expand Down
101 changes: 101 additions & 0 deletions docs/source/alerts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ or
- linenotify
- mattermost
- ms_teams
- ms_power_automate
- opsgenie
- pagerduty
- pagertree
Expand Down Expand Up @@ -1630,6 +1631,106 @@ Example usage::
ms_teams_theme_color: "#6600ff"
ms_teams_webhook_url: "MS Teams Webhook URL"

Microsoft Power Automate
~~~~~~~~~~~~~~~~~~~~~~~~

Microsoft Power Automate alerter will send a notification to a predefined Microsoft Teams channel.

The alerter requires the following options:

``ms_power_automate_webhook_url``: The webhook URL provided in Power Automate, `doc Microsoft <https://support.microsoft.com/en-us/office/post-a-workflow-when-a-webhook-request-is-received-in-microsoft-teams-8ae491c7-0394-4861-ba59-055e33f75498>`_. After creating the flow select your Teams channel under "Send each adaptive card". You can use a list of URLs to send to multiple channels.

Optional:

``ms_power_automate_alert_summary``: Microsoft Power Automate use this value for notification title, defaults to `alert_subject <https://elastalert2.readthedocs.io/en/latest/alerts.html#alert-subject>`_. You can set this value with arbitrary text if you don't want to use the default.

``ms_power_automate_kibana_discover_color``: By default, the alert will be published with the ``default`` type blue if not specified. If set to ``positive``, action is displayed with a positive style (typically the button becomes accent color), If set to ``destructive``, Action is displayed with a destructive style (typically the button becomes red)

``ms_power_automate_proxy``: By default ElastAlert 2 will not use a network proxy to send notifications to MS Teams. Set this option using ``hostname:port`` if you need to use a proxy. only supports https.

``ms_power_automate_teams_card_width_full``: By default, this is ``False`` and the notification will be sent to MS Teams without rendering full width in Microsoft Teams. Setting this attribute to ``True`` will render the alert in full width. `doc feature <https://github.com/microsoft/AdaptiveCards/issues/8102>`_.

``ms_power_automate_alert_facts``: You can add additional facts to your MS Teams alerts using this field. Specify the title using `name` and a value for the field or arbitrary text using `value`.

Example ms_power_automate_alert_facts::

ms_power_automate_alert_facts:
- name: Team
value: Teste
- name: Level
value: Critical

``ms_power_automate_kibana_discover_attach_url``: Enables the attachment of the ``kibana_discover_url`` to the MS Power Automate notification. The config ``generate_kibana_discover_url`` must also be ``True`` in order to generate the url. Defaults to ``False``.

``ms_power_automate_kibana_discover_title``: The title of the Kibana Discover url attachment. Defaults to ``Discover in Kibana``.

``ms_power_automate_opensearch_discover_attach_url``: Enables the attachment of the ``opensearch_discover_url`` to the MS Teams notification. The config ``generate_opensearch_discover_url`` must also be ``True`` in order to generate the url. Defaults to ``False``.

``ms_power_automate_opensearch_discover_title``: The title of the Opensearch Discover url attachment. Defaults to ``Discover in opensearch``.

Example ms_power_automate_kibana_discover_attach_url, ms_power_automate_kibana_discover_title::

# (Required)
generate_kibana_discover_url: True
kibana_discover_app_url: "http://localhost:5601/app/discover#/"
kibana_discover_index_pattern_id: "4babf380-c3b1-11eb-b616-1b59c2feec54"
kibana_discover_version: "8.13"

# (Optional)
kibana_discover_from_timedelta:
minutes: 10
kibana_discover_to_timedelta:
minutes: 10

# (Required)
ms_power_automate_kibana_discover_attach_url: True

# (Optional)
ms_power_automate_kibana_discover_title: "Discover in Kibana"

Example ms_power_automate_opensearch_discover_attach_url, ms_power_automate_opensearch_discover_title::

# (Required)
generate_opensearch_discover_url: True
opensearch_discover_app_url: "http://localhost:5601/app/discover#/"
opensearch_discover_index_pattern_id: "4babf380-c3b1-11eb-b616-1b59c2feec54"
opensearch_discover_version: "7.15"

# (Optional)
opensearch_discover_from_timedelta:
minutes: 10
opensearch_discover_to_timedelta:
minutes: 10

# (Required)
ms_power_automate_opensearch_discover_attach_url: True

# (Optional)
ms_power_automate_opensearch_discover_title: "Discover in opensearch"

``ms_power_automate_ca_certs``: Set this option to ``True`` or a path to a CA cert bundle or directory (eg: ``/etc/ssl/certs/ca-certificates.crt``) to validate the SSL certificate.

``ms_power_automate_ignore_ssl_errors``: By default ElastAlert 2 will verify SSL certificate. Set this option to ``True`` if you want to ignore SSL errors.

Example usage::

ms_power_automate_kibana_discover_attach_url: true
ms_power_automate_kibana_discover_title: "See More"
ms_power_automate_kibana_discover_color: 'destructive'
ms_power_automate_teams_card_width_full: true

ms_power_automate_alert_facts:
- name: Team
value: Teste
- name: Level
value: Critical

alert:
- ms_power_automate

ms_power_automate_webhook_url: >-
webhook

OpsGenie
~~~~~~~~

Expand Down
1 change: 1 addition & 0 deletions docs/source/elastalert.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ Currently, we have support built in for these alert types:
- Line Notify
- Mattermost
- Microsoft Teams
- Microsoft Power Automate
- OpsGenie
- PagerDuty
- PagerTree
Expand Down
129 changes: 129 additions & 0 deletions elastalert/alerters/powerautomate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import copy
import json
import requests

from elastalert.alerts import Alerter, DateTimeEncoder
from elastalert.util import EAException, elastalert_logger, lookup_es_key
from requests.exceptions import RequestException


class MsPowerAutomateAlerter(Alerter):
""" Creates a Microsoft Power Automate message for each alert """
required_options = frozenset(['ms_power_automate_webhook_url'])

def __init__(self, rule):
super(MsPowerAutomateAlerter, self).__init__(rule)
self.ms_power_automate_webhook_url = self.rule.get('ms_power_automate_webhook_url', None)
if isinstance(self.ms_power_automate_webhook_url, str):
self.ms_power_automate_webhook_url = [self.ms_power_automate_webhook_url]
self.ms_power_automate_proxy = self.rule.get('ms_power_automate_proxy', None)
self.ms_power_automate_alert_summary = self.rule.get('ms_power_automate_alert_summary', None)
self.ms_power_automate_kibana_discover_color = self.rule.get('ms_power_automate_kibana_discover_color', 'default')
self.ms_power_automate_ca_certs = self.rule.get('ms_power_automate_ca_certs')
self.ms_power_automate_ignore_ssl_errors = self.rule.get('ms_power_automate_ignore_ssl_errors', False)
self.ms_power_automate_alert_facts = self.rule.get('ms_power_automate_alert_facts', '')
self.ms_power_automate_kibana_discover_attach_url = self.rule.get('ms_power_automate_kibana_discover_attach_url', False)
self.ms_power_automate_kibana_discover_title = self.rule.get('ms_power_automate_kibana_discover_title', 'Discover in Kibana')
self.ms_power_automate_opensearch_discover_attach_url = self.rule.get('ms_power_automate_opensearch_discover_attach_url', False)
self.ms_power_automate_opensearch_discover_title = self.rule.get('ms_power_automate_opensearch_discover_title', 'Discover in opensearch')
self.ms_power_automate_teams_card_width_full = self.rule.get('ms_power_automate_teams_card_width_full', False)

def populate_facts(self, matches):
alert_facts = []
for arg in self.ms_power_automate_alert_facts:
arg = copy.copy(arg)
matched_value = lookup_es_key(matches[0], arg['value'])
arg['value'] = matched_value if matched_value is not None else arg['value']
alert_facts.append(arg)
return alert_facts

def alert(self, matches):
body = self.create_alert_body(matches)

title = self.create_title(matches)
summary = title if self.ms_power_automate_alert_summary is None else self.ms_power_automate_alert_summary
# post to Power Automate
headers = {'content-type': 'application/json'}

if self.ms_power_automate_ca_certs:
verify = self.ms_power_automate_ca_certs
else:
verify = not self.ms_power_automate_ignore_ssl_errors
if self.ms_power_automate_ignore_ssl_errors:
requests.packages.urllib3.disable_warnings()

# set https proxy, if it was provided
proxies = {'https': self.ms_power_automate_proxy} if self.ms_power_automate_proxy else None
payload = {
"type": "message",
"attachments": [
{
"contentType": "application/vnd.microsoft.card.adaptive",
"content": {
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.4",
"body": [
{
"type": "TextBlock",
"text": summary,
"weight": "Bolder",
"size": "ExtraLarge",
},
{
"type": "TextBlock",
"text": body,
"spacing": "Large",
"wrap": True
}
],
"actions": []
}
}
]
}

if self.ms_power_automate_teams_card_width_full:
payload['attachments'][0]['content']['msteams'] = {
"width": "Full"
}

if self.ms_power_automate_alert_facts != '':
facts = self.populate_facts(matches)
payload['attachments'][0]['content']['body'].append({
"type": "FactSet",
"facts": [{"title": fact['name'], "value": fact['value']} for fact in facts]
})

if self.ms_power_automate_kibana_discover_attach_url:
kibana_discover_url = lookup_es_key(matches[0], 'kibana_discover_url')
if kibana_discover_url:
payload['attachments'][0]['content']['actions'].append({
"type": "Action.OpenUrl",
"title": self.ms_power_automate_kibana_discover_title,
"url": kibana_discover_url,
"style": self.ms_power_automate_kibana_discover_color
})

if self.ms_power_automate_opensearch_discover_attach_url:
opensearch_discover_url = lookup_es_key(matches[0], 'opensearch_discover_url')
if opensearch_discover_url:
payload['attachments'][0]['content']['actions'].append({
"type": "Action.OpenUrl",
"title": self.ms_power_automate_opensearch_discover_title,
"url": opensearch_discover_url,
"style": self.ms_power_automate_kibana_discover_color
})

for url in self.ms_power_automate_webhook_url:
try:
response = requests.post(url, data=json.dumps(payload, cls=DateTimeEncoder),
headers=headers, proxies=proxies, verify=verify)
response.raise_for_status()
except RequestException as e:
raise EAException("Error posting to Power Automate: %s" % e)
elastalert_logger.info("Alert sent to Power Automate")

def get_info(self):
return {'type': 'ms_power_automate',
'ms_power_automate_webhook_url': self.ms_power_automate_webhook_url}
2 changes: 2 additions & 0 deletions elastalert/loaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
from elastalert.alerters.slack import SlackAlerter
from elastalert.alerters.sns import SnsAlerter
from elastalert.alerters.teams import MsTeamsAlerter
from elastalert.alerters.powerautomate import MsPowerAutomateAlerter
from elastalert.alerters.zabbix import ZabbixAlerter
from elastalert.alerters.tencentsms import TencentSMSAlerter
from elastalert.alerters.indexer import IndexerAlerter
Expand Down Expand Up @@ -111,6 +112,7 @@ class RulesLoader(object):
'command': elastalert.alerters.command.CommandAlerter,
'sns': SnsAlerter,
'ms_teams': MsTeamsAlerter,
'ms_power_automate': MsPowerAutomateAlerter,
'slack': SlackAlerter,
'mattermost': MattermostAlerter,
'pagerduty': PagerDutyAlerter,
Expand Down
26 changes: 26 additions & 0 deletions elastalert/schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,21 @@ definitions:
name: {type: string}
value: {type: string}

msPowerAutomateFact: &msPowerAutomateFact
type: object
additionalProperties: false
properties:
name: {type: string}
value: {type: string}

arrayOfMsTeamsFacts: &arrayOfMsTeamsFacts
type: array
items: *msTeamsFact

arrayOfMsPowerAutomateFacts: &arrayOfMsPowerAutomateFacts
type: array
items: *msPowerAutomateFact

mattermostField: &mattermostField
type: object
additionalProperties: false
Expand Down Expand Up @@ -673,6 +684,21 @@ properties:
ms_teams_attach_opensearch_discover_url: {type: boolean}
ms_teams_opensearch_discover_title: {type: string}


### Microsoft Power Automate
ms_power_automate_webhook_url: *arrayOfString
ms_power_automate_alert_summary: {type: string}
ms_power_automate_proxy: {type: string}
ms_power_automate_alert_facts: *arrayOfMsPowerAutomateFacts
ms_power_automate_kibana_discover_attach_url: {type: boolean}
ms_power_automate_kibana_discover_title: {type: string}
ms_power_automate_kibana_discover_color: {type: string}
ms_power_automate_ca_certs: {type: [boolean, string]}
ms_power_automate_ignore_ssl_errors: {type: boolean}
ms_power_automate_opensearch_discover_attach_url: {type: boolean}
ms_power_automate_opensearch_discover_title: {type: string}
ms_power_automate_teams_card_width_full: {type: boolean}

### Opsgenie
opsgenie_key: {type: string}
opsgenie_account: {type: string}
Expand Down
Loading

0 comments on commit b5eb6bc

Please sign in to comment.