From 7d8cac66054f7f1927175b00c6ea3f7cd114db23 Mon Sep 17 00:00:00 2001 From: kevgliss Date: Thu, 23 Jul 2015 13:46:54 -0700 Subject: [PATCH] Adding support for SMTP emails --- docs/administration/index.rst | 84 ++++++++++++++++----------- lemur/common/services/__init__.py | 0 lemur/common/services/aws/__init__.py | 0 lemur/common/services/aws/ses.py | 28 --------- lemur/extensions.py | 3 + lemur/factory.py | 3 +- lemur/manage.py | 28 ++++----- lemur/notifications.py | 38 +++++++++++- setup.py | 1 + 9 files changed, 105 insertions(+), 80 deletions(-) delete mode 100644 lemur/common/services/__init__.py delete mode 100644 lemur/common/services/aws/__init__.py delete mode 100644 lemur/common/services/aws/ses.py diff --git a/docs/administration/index.rst b/docs/administration/index.rst index c8c31dea..fff50c45 100644 --- a/docs/administration/index.rst +++ b/docs/administration/index.rst @@ -63,26 +63,6 @@ Basic Configuration SQLALCHEMY_DATABASE_URI = 'postgresql://:@:5432/lemur' -.. data:: LEMUR_MAIL - :noindex: - - Lemur mail service - - :: - - LEMUR_MAIL = 'lemur.example.com' - - -.. data:: LEMUR_SECURITY_TEAM_EMAIL - :noindex: - - This is an email or list of emails that should be notified when a certificate is expiring. It is also the contact email address for any discovered certificate. - - :: - - LEMUR_SECURITY_TEAM_EMAIL = ['security@example.com'] - - .. data:: LEMUR_RESTRICTED_DOMAINS :noindex: @@ -122,6 +102,57 @@ Basic Configuration LEMUR_ENCRYPTION_KEY = 'supersupersecret' +Notification Options +-------------------- + +Lemur currently has very basic support for notifications. Notifications are sent to the certificate creator, owner and +security team as specified by the `SECURITY_TEAM_EMAIL` configuration parameter. + +The template for all of these notifications lives under lemur/template/event.html and can be easily modified to fit your +needs. + +Certificates marked as in-active will **not** be notified of upcoming expiration. This enables a user to essentially +silence the expiration. If a certificate is active and is expiring the above will be notified at 30, 15, 5, 2 days +respectively. + +Lemur supports sending certification expiration notifications through SES and SMTP. + + +.. data:: LEMUR_EMAIL_SENDER + :noindex: + + Specifies which service will be delivering notification emails. Valid values are `SMTP` or `SES` + +.. note:: + If using STMP as your provider you will need to define additional configuration options as specified by Flask-Mail. + See: `Flask-Mail `_ + + If you are using SES the email specified by the `LEMUR_MAIL` configuration will need to be verified by AWS before + you can send any mail. See: `Verifying Email Address in Amazon SES `_ + +.. data:: LEMUR_MAIL + :noindex: + + Lemur sender's email + + :: + + LEMUR_MAIL = 'lemur.example.com' + + +.. data:: LEMUR_SECURITY_TEAM_EMAIL + :noindex: + + This is an email or list of emails that should be notified when a certificate is expiring. It is also the contact email address for any discovered certificate. + + :: + + LEMUR_SECURITY_TEAM_EMAIL = ['security@example.com'] + + +.. data:: + + Authority Options ----------------- @@ -191,19 +222,6 @@ If you are not using PING you do not need to configure any of these options PING_JWKS_URL = "https:///pf/JWKS" -Notifications -============= - -Lemur currently has very basic support for notifications. Notifications are send to the certificate creator, owner and -security team as specified by the `SECURITY_TEAM_EMAIL` configuration parameter. - -The template for all of these notifications lives under lemur/template/event.html and can be easily modified to fit your -needs. - -Certificates marked as in-active will **not** be notified of upcoming expiration. This enables a user to essentially -silence the expiration. If a certificate is active and is expiring the above will be notified at 30, 15, 5, 2 days -respectively. Lemur will not attempt to notify about certificate that have already expired. - AWS Configuration ================= diff --git a/lemur/common/services/__init__.py b/lemur/common/services/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/lemur/common/services/aws/__init__.py b/lemur/common/services/aws/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/lemur/common/services/aws/ses.py b/lemur/common/services/aws/ses.py deleted file mode 100644 index 8e5aeb4f..00000000 --- a/lemur/common/services/aws/ses.py +++ /dev/null @@ -1,28 +0,0 @@ -""" -.. module: lemur.common.services.aws - :platform: Unix - :copyright: (c) 2015 by Netflix Inc., see AUTHORS for more - :license: Apache, see LICENSE for more details. - -.. moduleauthor:: Kevin Glisson -""" -import boto.ses -from flask import current_app - -from lemur.templates.config import env - - -def send(subject, data, email_type, recipients): - """ - Configures all Lemur email messaging - - :param subject: - :param data: - :param email_type: - :param recipients: - """ - conn = boto.connect_ses() - # jinja template depending on type - template = env.get_template('{}.html'.format(email_type)) - body = template.render(**data) - conn.send_email(current_app.config.get("LEMUR_EMAIL"), subject, body, recipients, format='html') diff --git a/lemur/extensions.py b/lemur/extensions.py index 8c945f80..47c8d024 100644 --- a/lemur/extensions.py +++ b/lemur/extensions.py @@ -14,3 +14,6 @@ bcrypt = Bcrypt() from flask.ext.principal import Principal principal = Principal() + +from flask_mail import Mail +smtp_mail = Mail() diff --git a/lemur/factory.py b/lemur/factory.py index f895a136..3ba7f01e 100644 --- a/lemur/factory.py +++ b/lemur/factory.py @@ -19,7 +19,7 @@ from logging.handlers import RotatingFileHandler from flask import Flask from lemur.common.health import mod as health -from lemur.extensions import db, migrate, principal +from lemur.extensions import db, migrate, principal, smtp_mail DEFAULT_BLUEPRINTS = ( @@ -111,6 +111,7 @@ def configure_extensions(app): db.init_app(app) migrate.init_app(app, db) principal.init_app(app) + smtp_mail.init_app(app) def configure_blueprints(app, blueprints): diff --git a/lemur/manage.py b/lemur/manage.py index c939fc58..3db88f17 100755 --- a/lemur/manage.py +++ b/lemur/manage.py @@ -72,8 +72,6 @@ LEMUR_RESTRICTED_DOMAINS = [] # Mail Server -# Lemur currently only supports SES for sending email, this address -# needs to be verified LEMUR_EMAIL = '' LEMUR_SECURITY_TEAM_EMAIL = [] @@ -92,34 +90,32 @@ SQLALCHEMY_DATABASE_URI = 'postgresql://lemur:lemur@localhost:5432/lemur' # AWS # Lemur will need STS assume role access to every destination you want to monitor -#AWS_ACCOUNT_MAPPINGS = {{ +# AWS_ACCOUNT_MAPPINGS = {{ # '1111111111': 'myawsacount' -#}} +# }} ## This is useful if you know you only want to monitor one destination #AWS_REGIONS = ['us-east-1'] #LEMUR_INSTANCE_PROFILE = 'Lemur' -############# -## Issuers ## -############# +# Issuers # These will be dependent on which 3rd party that Lemur is # configured to use. -#CLOUDCA_URL = '' -#CLOUDCA_PEM_PATH = '' -#CLOUDCA_BUNDLE = '' +# CLOUDCA_URL = '' +# CLOUDCA_PEM_PATH = '' +# CLOUDCA_BUNDLE = '' # number of years to issue if not specified -#CLOUDCA_DEFAULT_VALIDITY = 2 +# CLOUDCA_DEFAULT_VALIDITY = 2 -#VERISIGN_URL = '' -#VERISIGN_PEM_PATH = '' -#VERISIGN_FIRST_NAME = '' -#VERISIGN_LAST_NAME = '' -#VERSIGN_EMAIL = '' +# VERISIGN_URL = '' +# VERISIGN_PEM_PATH = '' +# VERISIGN_FIRST_NAME = '' +# VERISIGN_LAST_NAME = '' +# VERSIGN_EMAIL = '' """ diff --git a/lemur/notifications.py b/lemur/notifications.py index 055b6b42..a6a47a32 100644 --- a/lemur/notifications.py +++ b/lemur/notifications.py @@ -12,13 +12,19 @@ import ssl import socket import arrow +import boto.ses + from flask import current_app +from flask_mail import Message from lemur import database -from lemur.common.services.aws import ses from lemur.certificates.models import Certificate from lemur.domains.models import Domain +from lemur.templates.config import env +from lemur.extensions import smtp_mail + + NOTIFICATION_INTERVALS = [30, 15, 5, 2] @@ -84,7 +90,7 @@ def send_expiration_notifications(): for messages, recipients in roll_ups: notifications += 1 - ses.send("Certificate Expiration", dict(messages=messages), 'event', recipients) + send("Certificate Expiration", dict(messages=messages), 'event', recipients) print notifications current_app.logger.info("Lemur has sent {0} certification notifications".format(notifications)) @@ -182,3 +188,31 @@ def _create_roll_ups(messages): else: roll_ups.append(([message_data], recipients)) return roll_ups + + +def send(subject, data, email_type, recipients): + """ + Configures all Lemur email messaging + + :param subject: + :param data: + :param email_type: + :param recipients: + """ + # jinja template depending on type + template = env.get_template('{}.html'.format(email_type)) + body = template.render(**data) + + s_type = current_app.config.get("LEMUR_EMAIL_SENDER").lower() + if s_type == 'ses': + conn = boto.connect_ses() + conn.send_email(current_app.config.get("LEMUR_EMAIL"), subject, body, recipients, format='html') + + elif s_type == 'smtp': + msg = Message(subject, recipients=recipients) + msg.body = "" # kinda a weird api for sending html emails + msg.html = body + smtp_mail.send(msg) + + else: + current_app.logger.error("No mail carrier specified, notification emails were not able to be sent!") diff --git a/setup.py b/setup.py index 2caf245f..13aca086 100644 --- a/setup.py +++ b/setup.py @@ -29,6 +29,7 @@ install_requires = [ 'Flask-Migrate>=1.4.0', 'Flask-Bcrypt>=0.6.2', 'Flask-Principal>=0.4.0', + 'Flask-Mail==0.9.1', 'SQLAlchemy-Utils>=0.30.11', 'BeautifulSoup4', 'requests>=2.7.0',