lemur/lemur/plugins/lemur_slack/plugin.py

144 lines
4.6 KiB
Python
Raw Normal View History

2016-05-08 18:07:16 +02:00
"""
.. module: lemur.plugins.lemur_slack.plugin
2016-05-08 18:07:16 +02:00
:platform: Unix
:copyright: (c) 2018 by Netflix Inc., see AUTHORS for more
2016-05-08 18:07:16 +02:00
:license: Apache, see LICENSE for more details.
.. moduleauthor:: Harm Weites <harm@weites.com>
.. moduleauthor:: Kevin Glisson <kglisson@netflix.com>
2016-05-08 18:07:16 +02:00
"""
import json
import arrow
2016-05-08 18:07:16 +02:00
from flask import current_app
from lemur.plugins.bases import ExpirationNotificationPlugin
from lemur.plugins import lemur_slack as slack
import requests
def create_certificate_url(name):
2019-05-16 16:57:02 +02:00
return "https://{hostname}/#/certificates/{name}".format(
hostname=current_app.config.get("LEMUR_HOSTNAME"), name=name
)
2016-12-08 20:33:40 +01:00
def create_expiration_attachments(certificates):
attachments = []
2016-12-08 20:33:40 +01:00
for certificate in certificates:
2019-05-16 16:57:02 +02:00
attachments.append(
{
"title": certificate["name"],
"title_link": create_certificate_url(certificate["name"]),
"color": "danger",
"fallback": "",
"fields": [
{"title": "Owner", "value": certificate["owner"], "short": True},
{
"title": "Expires",
"value": arrow.get(certificate["validityEnd"]).format(
"dddd, MMMM D, YYYY"
),
"short": True,
},
{
"title": "Endpoints Detected",
"value": len(certificate["endpoints"]),
"short": True,
},
],
"text": "",
"mrkdwn_in": ["text"],
}
)
return attachments
2016-05-08 18:07:16 +02:00
2016-12-08 20:33:40 +01:00
def create_rotation_attachments(certificate):
return {
2019-05-16 16:57:02 +02:00
"title": certificate["name"],
"title_link": create_certificate_url(certificate["name"]),
"fields": [
{"title": "Owner", "value": certificate["owner"], "short": True},
2016-12-08 20:33:40 +01:00
{
"title": "Expires",
"value": arrow.get(certificate["validityEnd"]).format(
"dddd, MMMM D, YYYY"
),
"short": True,
},
{
"title": "Endpoints Rotated",
"value": len(certificate["endpoints"]),
"short": True,
},
2019-05-16 16:57:02 +02:00
],
2016-12-08 20:33:40 +01:00
}
2016-05-08 18:07:16 +02:00
class SlackNotificationPlugin(ExpirationNotificationPlugin):
2019-05-16 16:57:02 +02:00
title = "Slack"
slug = "slack-notification"
description = "Sends notifications to Slack"
2016-05-08 18:07:16 +02:00
version = slack.VERSION
2019-05-16 16:57:02 +02:00
author = "Harm Weites"
author_url = "https://github.com/netflix/lemur"
2016-05-08 18:07:16 +02:00
additional_options = [
{
2019-05-16 16:57:02 +02:00
"name": "webhook",
"type": "str",
"required": True,
2020-11-03 03:45:38 +01:00
"validation": r"^https:\/\/hooks\.slack\.com\/services\/.+$",
2019-05-16 16:57:02 +02:00
"helpMessage": "The url Slack told you to use for this integration",
},
{
"name": "username",
"type": "str",
"validation": "^.+$",
"helpMessage": "The great storyteller",
"default": "Lemur",
},
{
"name": "recipients",
"type": "str",
"required": True,
"validation": "^(@|#).+$",
"helpMessage": "Where to send to, either @username or #channel",
2016-05-08 18:07:16 +02:00
},
]
2016-12-08 20:33:40 +01:00
def send(self, notification_type, message, targets, options, **kwargs):
2016-05-08 18:07:16 +02:00
"""
A typical check can be performed using the notify command:
`lemur notify`
2020-10-16 19:40:11 +02:00
While we receive a `targets` parameter here, it is unused, as Slack webhooks do not allow
dynamic re-targeting of messages. The webhook itself specifies a channel.
2016-05-08 18:07:16 +02:00
"""
2016-12-08 20:33:40 +01:00
attachments = None
2019-05-16 16:57:02 +02:00
if notification_type == "expiration":
attachments = create_expiration_attachments(message)
2019-05-16 16:57:02 +02:00
elif notification_type == "rotation":
2016-12-08 20:33:40 +01:00
attachments = create_rotation_attachments(message)
if not attachments:
2019-05-16 16:57:02 +02:00
raise Exception("Unable to create message attachments")
2016-05-08 18:07:16 +02:00
body = {
2020-10-23 18:34:33 +02:00
"text": f"Lemur {notification_type.capitalize()} Notification",
2019-05-16 16:57:02 +02:00
"attachments": attachments,
"channel": self.get_option("recipients", options),
"username": self.get_option("username", options),
}
2016-05-08 18:07:16 +02:00
2019-05-16 16:57:02 +02:00
r = requests.post(self.get_option("webhook", options), json.dumps(body))
2016-12-08 20:33:40 +01:00
2016-05-08 18:07:16 +02:00
if r.status_code not in [200]:
2020-10-23 18:34:33 +02:00
raise Exception(f"Failed to send message. Slack response: {r.status_code} {body}")
2016-12-08 20:33:40 +01:00
2020-10-16 19:40:11 +02:00
current_app.logger.info(
2020-10-23 18:34:33 +02:00
f"Slack response: {r.status_code} Message Body: {body}"
2019-05-16 16:57:02 +02:00
)