2016-05-08 18:07:16 +02:00
|
|
|
"""
|
2016-12-14 18:29:04 +01:00
|
|
|
.. module: lemur.plugins.lemur_slack.plugin
|
2016-05-08 18:07:16 +02:00
|
|
|
:platform: Unix
|
2018-05-29 19:18:16 +02:00
|
|
|
: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>
|
2016-07-06 19:27:13 +02:00
|
|
|
.. moduleauthor:: Kevin Glisson <kglisson@netflix.com>
|
2016-05-08 18:07:16 +02:00
|
|
|
"""
|
2016-07-06 19:27:13 +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
|
|
|
|
|
|
|
|
|
2016-07-06 19:27:13 +02:00
|
|
|
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-07-06 19:27:13 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
|
2016-12-08 20:33:40 +01:00
|
|
|
def create_expiration_attachments(certificates):
|
2016-07-06 19:27:13 +02:00
|
|
|
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"],
|
|
|
|
}
|
|
|
|
)
|
2016-07-06 19:27:13 +02:00
|
|
|
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": [
|
2016-12-08 20:33:40 +01:00
|
|
|
{
|
2019-05-16 16:57:02 +02:00
|
|
|
{"title": "Owner", "value": certificate["owner"], "short": True},
|
2016-12-08 20:33:40 +01:00
|
|
|
{
|
2019-05-16 16:57:02 +02:00
|
|
|
"title": "Expires",
|
|
|
|
"value": arrow.get(certificate["validityEnd"]).format(
|
|
|
|
"dddd, MMMM D, YYYY"
|
|
|
|
),
|
|
|
|
"short": True,
|
2016-12-08 20:33:40 +01:00
|
|
|
},
|
|
|
|
{
|
2019-05-16 16:57:02 +02:00
|
|
|
"title": "Replaced By",
|
|
|
|
"value": len(certificate["replaced"][0]["name"]),
|
|
|
|
"short": True,
|
2016-12-08 20:33:40 +01:00
|
|
|
},
|
|
|
|
{
|
2019-05-16 16:57:02 +02:00
|
|
|
"title": "Endpoints Rotated",
|
|
|
|
"value": len(certificate["endpoints"]),
|
|
|
|
"short": True,
|
2016-12-08 20:33:40 +01:00
|
|
|
},
|
|
|
|
}
|
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,
|
|
|
|
"validation": "^https:\/\/hooks\.slack\.com\/services\/.+$",
|
|
|
|
"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`
|
|
|
|
"""
|
2016-12-08 20:33:40 +01:00
|
|
|
attachments = None
|
2019-05-16 16:57:02 +02:00
|
|
|
if notification_type == "expiration":
|
2016-07-06 19:27:13 +02:00
|
|
|
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)
|
|
|
|
|
2016-07-06 19:27:13 +02:00
|
|
|
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
|
|
|
|
2016-07-06 19:27:13 +02:00
|
|
|
body = {
|
2019-05-16 16:57:02 +02:00
|
|
|
"text": "Lemur {0} Notification".format(notification_type.capitalize()),
|
|
|
|
"attachments": attachments,
|
|
|
|
"channel": self.get_option("recipients", options),
|
|
|
|
"username": self.get_option("username", options),
|
2016-07-06 19:27:13 +02:00
|
|
|
}
|
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]:
|
2019-05-16 16:57:02 +02:00
|
|
|
raise Exception("Failed to send message")
|
2016-12-08 20:33:40 +01:00
|
|
|
|
2019-05-16 16:57:02 +02:00
|
|
|
current_app.logger.error(
|
|
|
|
"Slack response: {0} Message Body: {1}".format(r.status_code, body)
|
|
|
|
)
|