Merge pull request #25 from kevgliss/smtp

Adding support for SMTP emails
This commit is contained in:
kevgliss 2015-07-23 16:28:54 -07:00
commit 1191fbe6c2
9 changed files with 105 additions and 80 deletions

View File

@ -63,26 +63,6 @@ Basic Configuration
SQLALCHEMY_DATABASE_URI = 'postgresql://<user>:<password>@<hostname>:5432/lemur' SQLALCHEMY_DATABASE_URI = 'postgresql://<user>:<password>@<hostname>: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 .. data:: LEMUR_RESTRICTED_DOMAINS
:noindex: :noindex:
@ -122,6 +102,57 @@ Basic Configuration
LEMUR_ENCRYPTION_KEY = 'supersupersecret' 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 <https://pythonhosted.org/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 <http://docs.aws.amazon.com/ses/latest/DeveloperGuide/verify-email-addresses.html>`_
.. 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 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://<yourpingserver>/pf/JWKS" PING_JWKS_URL = "https://<yourpingserver>/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 AWS Configuration
================= =================

View File

@ -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 <kglisson@netflix.com>
"""
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')

View File

@ -14,3 +14,6 @@ bcrypt = Bcrypt()
from flask.ext.principal import Principal from flask.ext.principal import Principal
principal = Principal() principal = Principal()
from flask_mail import Mail
smtp_mail = Mail()

View File

@ -19,7 +19,7 @@ from logging.handlers import RotatingFileHandler
from flask import Flask from flask import Flask
from lemur.common.health import mod as health 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 = ( DEFAULT_BLUEPRINTS = (
@ -111,6 +111,7 @@ def configure_extensions(app):
db.init_app(app) db.init_app(app)
migrate.init_app(app, db) migrate.init_app(app, db)
principal.init_app(app) principal.init_app(app)
smtp_mail.init_app(app)
def configure_blueprints(app, blueprints): def configure_blueprints(app, blueprints):

View File

@ -72,8 +72,6 @@ LEMUR_RESTRICTED_DOMAINS = []
# Mail Server # Mail Server
# Lemur currently only supports SES for sending email, this address
# needs to be verified
LEMUR_EMAIL = '' LEMUR_EMAIL = ''
LEMUR_SECURITY_TEAM_EMAIL = [] LEMUR_SECURITY_TEAM_EMAIL = []
@ -92,34 +90,32 @@ SQLALCHEMY_DATABASE_URI = 'postgresql://lemur:lemur@localhost:5432/lemur'
# AWS # AWS
# Lemur will need STS assume role access to every destination you want to monitor # Lemur will need STS assume role access to every destination you want to monitor
#AWS_ACCOUNT_MAPPINGS = {{ # AWS_ACCOUNT_MAPPINGS = {{
# '1111111111': 'myawsacount' # '1111111111': 'myawsacount'
#}} # }}
## This is useful if you know you only want to monitor one destination ## This is useful if you know you only want to monitor one destination
#AWS_REGIONS = ['us-east-1'] #AWS_REGIONS = ['us-east-1']
#LEMUR_INSTANCE_PROFILE = 'Lemur' #LEMUR_INSTANCE_PROFILE = 'Lemur'
############# # Issuers
## Issuers ##
#############
# These will be dependent on which 3rd party that Lemur is # These will be dependent on which 3rd party that Lemur is
# configured to use. # configured to use.
#CLOUDCA_URL = '' # CLOUDCA_URL = ''
#CLOUDCA_PEM_PATH = '' # CLOUDCA_PEM_PATH = ''
#CLOUDCA_BUNDLE = '' # CLOUDCA_BUNDLE = ''
# number of years to issue if not specified # number of years to issue if not specified
#CLOUDCA_DEFAULT_VALIDITY = 2 # CLOUDCA_DEFAULT_VALIDITY = 2
#VERISIGN_URL = '' # VERISIGN_URL = ''
#VERISIGN_PEM_PATH = '' # VERISIGN_PEM_PATH = ''
#VERISIGN_FIRST_NAME = '' # VERISIGN_FIRST_NAME = ''
#VERISIGN_LAST_NAME = '' # VERISIGN_LAST_NAME = ''
#VERSIGN_EMAIL = '' # VERSIGN_EMAIL = ''
""" """

View File

@ -12,13 +12,19 @@ import ssl
import socket import socket
import arrow import arrow
import boto.ses
from flask import current_app from flask import current_app
from flask_mail import Message
from lemur import database from lemur import database
from lemur.common.services.aws import ses
from lemur.certificates.models import Certificate from lemur.certificates.models import Certificate
from lemur.domains.models import Domain from lemur.domains.models import Domain
from lemur.templates.config import env
from lemur.extensions import smtp_mail
NOTIFICATION_INTERVALS = [30, 15, 5, 2] NOTIFICATION_INTERVALS = [30, 15, 5, 2]
@ -84,7 +90,7 @@ def send_expiration_notifications():
for messages, recipients in roll_ups: for messages, recipients in roll_ups:
notifications += 1 notifications += 1
ses.send("Certificate Expiration", dict(messages=messages), 'event', recipients) send("Certificate Expiration", dict(messages=messages), 'event', recipients)
print notifications print notifications
current_app.logger.info("Lemur has sent {0} certification notifications".format(notifications)) current_app.logger.info("Lemur has sent {0} certification notifications".format(notifications))
@ -182,3 +188,31 @@ def _create_roll_ups(messages):
else: else:
roll_ups.append(([message_data], recipients)) roll_ups.append(([message_data], recipients))
return roll_ups 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!")

View File

@ -29,6 +29,7 @@ install_requires = [
'Flask-Migrate>=1.4.0', 'Flask-Migrate>=1.4.0',
'Flask-Bcrypt>=0.6.2', 'Flask-Bcrypt>=0.6.2',
'Flask-Principal>=0.4.0', 'Flask-Principal>=0.4.0',
'Flask-Mail==0.9.1',
'SQLAlchemy-Utils>=0.30.11', 'SQLAlchemy-Utils>=0.30.11',
'BeautifulSoup4', 'BeautifulSoup4',
'requests>=2.7.0', 'requests>=2.7.0',