Adding ability to exclude certificates from expiration (#730)

* adding ability to exclude certificates from expiration

* fixing tests
This commit is contained in:
kevgliss 2017-03-15 11:25:19 -07:00 committed by GitHub
parent b0ea027769
commit f0dde845db
4 changed files with 26 additions and 10 deletions

View File

@ -12,16 +12,21 @@ from lemur.notifications.messaging import send_expiration_notifications
manager = Manager(usage="Handles notification related tasks.") manager = Manager(usage="Handles notification related tasks.")
@manager.command @manager.option('-e', '--exclude', dest='exclude', nargs="*", help='Common name matching of certificates that should be excluded from notification')
def expirations(): def expirations(exclude):
""" """
Runs Lemur's notification engine, that looks for expired certificates and sends Runs Lemur's notification engine, that looks for expired certificates and sends
notifications out to those that have subscribed to them. notifications out to those that have subscribed to them.
Every certificate receives notifications by default. When expiration notifications are handled outside of Lemur
we exclude their names (or matching) from expiration notifications.
It performs simple subset matching and is case insensitive.
:return: :return:
""" """
print("Starting to notify subscribers about expiring certificates!") print("Starting to notify subscribers about expiring certificates!")
success, failed = send_expiration_notifications() success, failed = send_expiration_notifications(exclude)
print( print(
"Finished notifying subscribers about expiring certificates! Sent: {success} Failed: {failed}".format( "Finished notifying subscribers about expiring certificates! Sent: {success} Failed: {failed}".format(
success=success, success=success,

View File

@ -15,6 +15,8 @@ import arrow
from datetime import timedelta from datetime import timedelta
from flask import current_app from flask import current_app
from sqlalchemy import and_
from lemur import database, metrics from lemur import database, metrics
from lemur.common.utils import windowed_query from lemur.common.utils import windowed_query
@ -25,9 +27,10 @@ from lemur.plugins import plugins
from lemur.plugins.utils import get_plugin_option from lemur.plugins.utils import get_plugin_option
def get_certificates(): def get_certificates(exclude=None):
""" """
Finds all certificates that are eligible for notifications. Finds all certificates that are eligible for notifications.
:param exclude:
:return: :return:
""" """
now = arrow.utcnow() now = arrow.utcnow()
@ -38,6 +41,13 @@ def get_certificates():
.filter(Certificate.notify == True) \ .filter(Certificate.notify == True) \
.filter(Certificate.expired == False) # noqa .filter(Certificate.expired == False) # noqa
exclude_conditions = []
if exclude:
for e in exclude:
exclude_conditions.append(~Certificate.name.ilike('%{}%'.format(e)))
q = q.filter(and_(*exclude_conditions))
certs = [] certs = []
for c in windowed_query(q, Certificate.id, 100): for c in windowed_query(q, Certificate.id, 100):
@ -47,13 +57,14 @@ def get_certificates():
return certs return certs
def get_eligible_certificates(): def get_eligible_certificates(exclude=None):
""" """
Finds all certificates that are eligible for certificate expiration. Finds all certificates that are eligible for certificate expiration.
:param exclude:
:return: :return:
""" """
certificates = defaultdict(dict) certificates = defaultdict(dict)
certs = get_certificates() certs = get_certificates(exclude=exclude)
# group by owner # group by owner
for owner, items in groupby(certs, lambda x: x.owner): for owner, items in groupby(certs, lambda x: x.owner):
@ -91,7 +102,7 @@ def send_notification(event_type, data, targets, notification):
current_app.logger.exception(e) current_app.logger.exception(e)
def send_expiration_notifications(): def send_expiration_notifications(exclude):
""" """
This function will check for upcoming certificate expiration, This function will check for upcoming certificate expiration,
and send out notification emails at given intervals. and send out notification emails at given intervals.
@ -102,7 +113,7 @@ def send_expiration_notifications():
security_email = current_app.config.get('LEMUR_SECURITY_TEAM_EMAIL') security_email = current_app.config.get('LEMUR_SECURITY_TEAM_EMAIL')
security_data = [] security_data = []
for owner, notification_group in get_eligible_certificates().items(): for owner, notification_group in get_eligible_certificates(exclude=exclude).items():
for notification_label, certificates in notification_group.items(): for notification_label, certificates in notification_group.items():
notification_data = [] notification_data = []

View File

@ -40,7 +40,7 @@ def send_via_smtp(subject, body, targets):
:param targets: :param targets:
:return: :return:
""" """
msg = Message(subject, recipients=targets) msg = Message(subject, recipients=targets, sender=current_app.config.get("LEMUR_EMAIL"))
msg.body = "" # kinda a weird api for sending html emails msg.body = "" # kinda a weird api for sending html emails
msg.html = body msg.html = body
smtp_mail.send(msg) smtp_mail.send(msg)

View File

@ -71,7 +71,7 @@ def test_send_expiration_notification(certificate, notification, notification_pl
delta = certificate.not_after - timedelta(days=10) delta = certificate.not_after - timedelta(days=10)
with freeze_time(delta.datetime): with freeze_time(delta.datetime):
assert send_expiration_notifications() == (2, 0) assert send_expiration_notifications([]) == (2, 0)
@mock_ses @mock_ses