From 86082009b97917320c4f57105a38af8c941f0205 Mon Sep 17 00:00:00 2001 From: Justin P Date: Mon, 9 Jul 2018 23:24:35 -0500 Subject: [PATCH 1/7] Sinful Use of `$` Using the `$` sign within any block of text already marked as a code block is a grievous sin due to the fact that it makes it 100% pointless for you to have USED THE CODE BLOCK IN THE FIRST PLACE! The `$` becomes included in the text we're trying to highlight for us to be able to actually use in our own projects. Why post the info if you don't want us to use it. Thank you. --- docs/quickstart/index.rst | 56 +++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/docs/quickstart/index.rst b/docs/quickstart/index.rst index 32abcc9c..70ca1312 100644 --- a/docs/quickstart/index.rst +++ b/docs/quickstart/index.rst @@ -26,19 +26,19 @@ If installing Lemur on a bare Ubuntu OS you will need to grab the following pack .. code-block:: bash - $ sudo apt-get update - $ sudo apt-get install nodejs nodejs-legacy python-pip python-dev python3-dev libpq-dev build-essential libssl-dev libffi-dev libsasl2-dev libldap2-dev nginx git supervisor npm postgresql + sudo apt-get update + sudo apt-get install nodejs nodejs-legacy python-pip python-dev python3-dev libpq-dev build-essential libssl-dev libffi-dev libsasl2-dev libldap2-dev nginx git supervisor npm postgresql .. note:: PostgreSQL is only required if your database is going to be on the same host as the webserver. npm is needed if you're installing Lemur from the source (e.g., from git). .. note:: Installing node from a package manager may creat the nodejs bin at /usr/bin/nodejs instead of /usr/bin/node If that is the case run the following - $ sudo ln -s /user/bin/nodejs /usr/bin/node + sudo ln -s /user/bin/nodejs /usr/bin/node Now, install Python ``virtualenv`` package: .. code-block:: bash - $ sudo pip install -U virtualenv + sudo pip install -U virtualenv Setting up an Environment @@ -48,28 +48,28 @@ In this guide, Lemur will be installed in ``/www``, so you need to create that s .. code-block:: bash - $ sudo mkdir /www - $ cd /www + sudo mkdir /www + cd /www Clone Lemur inside the just created directory and give yourself write permission (we assume ``lemur`` is the user): .. code-block:: bash - $ sudo useradd lemur - $ sudo passwd lemur - $ sudo mkdir /home/lemur - $ sudo chown lemur:lemur /home/lemur - $ sudo git clone https://github.com/Netflix/lemur - $ sudo chown -R lemur lemur/ + sudo useradd lemur + sudo passwd lemur + sudo mkdir /home/lemur + sudo chown lemur:lemur /home/lemur + sudo git clone https://github.com/Netflix/lemur + sudo chown -R lemur lemur/ Create the virtual environment, activate it and enter the Lemur's directory: .. code-block:: bash - $ su lemur - $ virtualenv -p python3 lemur - $ source /www/lemur/bin/activate - $ cd lemur + su lemur + virtualenv -p python3 lemur + source /www/lemur/bin/activate + cd lemur .. note:: Activating the environment adjusts your PATH, so that things like pip now install into the virtualenv by default. @@ -81,13 +81,13 @@ Once your system is prepared, ensure that you are in the virtualenv: .. code-block:: bash - $ which python + which python And then run: .. code-block:: bash - $ make release + make release .. note:: This command will install npm dependencies as well as compile static assets. @@ -101,7 +101,7 @@ You may also run with the urlContextPath variable set. If this is set it will ad .. code-block:: bash - $ make release urlContextPath={desired context path} + make release urlContextPath={desired context path} Creating a configuration @@ -113,7 +113,7 @@ Simply run: .. code-block:: bash - $ lemur create_config + lemur create_config .. note:: This command will create a default configuration under ``~/.lemur/lemur.conf.py`` you can specify this location by passing the ``config_path`` parameter to the ``create_config`` command. @@ -127,7 +127,7 @@ Once created, you will need to update the configuration file with information ab .. code-block:: bash - $ vi ~/.lemur/lemur.conf.py + vi ~/.lemur/lemur.conf.py .. note:: If you are unfamiliar with the SQLALCHEMY_DATABASE_URI string it can be broken up like so: ``postgresql://userame:password@:/`` @@ -153,8 +153,8 @@ First, set a password for the postgres user. For this guide, we will use ``lemu .. code-block:: bash - $ sudo -u postgres -i - $ psql + sudo -u postgres -i + psql postgres=# CREATE USER lemur WITH PASSWORD 'lemur'; Once successful, type CTRL-D to exit the Postgres shell. @@ -163,7 +163,7 @@ Next, we will create our new database: .. code-block:: bash - $ sudo -u postgres createdb lemur + sudo -u postgres createdb lemur .. _InitializingLemur: @@ -186,8 +186,8 @@ Additional notifications can be created through the UI or API. See :ref:`Creati .. code-block:: bash - $ cd /www/lemur/lemur - $ lemur init + cd /www/lemur/lemur + lemur init .. note:: It is recommended that once the ``lemur`` user is created that you create individual users for every day access. There is currently no way for a user to self enroll for Lemur access, they must have an administrator create an account for them or be enrolled automatically through SSO. This can be done through the CLI or UI. See :ref:`Creating Users ` and :ref:`Command Line Interface ` for details. @@ -228,7 +228,7 @@ After making these changes, restart Nginx service to apply them: .. code-block:: bash - $ sudo service nginx restart + sudo service nginx restart Starting the Web Service @@ -284,7 +284,7 @@ Lemur uses periodic sync tasks to make sure it is up-to-date with its environmen .. code-block:: bash - $ crontab -e + crontab -e */15 * * * * lemur sync -s all 0 22 * * * lemur check_revoked 0 22 * * * lemur notify From 8dc52b859ba2e2183ebe52db510dd546dd13131c Mon Sep 17 00:00:00 2001 From: root Date: Wed, 11 Jul 2018 11:57:36 -0500 Subject: [PATCH 2/7] initial commit --- lemur/dns_providers/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 lemur/dns_providers/__init__.py diff --git a/lemur/dns_providers/__init__.py b/lemur/dns_providers/__init__.py new file mode 100644 index 00000000..e69de29b From 2f32014c75d4707e8fcd48ee8865e7eb3fb290db Mon Sep 17 00:00:00 2001 From: Marti Raudsepp Date: Tue, 19 Jun 2018 18:41:12 +0300 Subject: [PATCH 3/7] Cache parsed certificate instead of re-parsing for each field Use @cached_property decorator to cache the results of parse_certificate(). This significantly cuts down on the number of times certs need to be parsed for a list view. --- lemur/certificates/models.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lemur/certificates/models.py b/lemur/certificates/models.py index f5b60ad5..87ee3b93 100644 --- a/lemur/certificates/models.py +++ b/lemur/certificates/models.py @@ -23,6 +23,8 @@ from sqlalchemy import event, Integer, ForeignKey, String, PassiveDefault, func, from sqlalchemy_utils.types.arrow import ArrowType from werkzeug.utils import cached_property +import lemur.common.utils + from lemur.database import db from lemur.extensions import sentry @@ -186,7 +188,7 @@ class Certificate(db.Model): @cached_property def parsed_cert(self): assert self.body, "Certificate body not set" - return utils.parse_certificate(self.body) + return lemur.common.utils.parse_certificate(self.body) @property def active(self): From ead374db5fa575881f92550921a26d1a19c99818 Mon Sep 17 00:00:00 2001 From: Marti Raudsepp Date: Wed, 27 Jun 2018 13:56:39 +0300 Subject: [PATCH 4/7] Clean up module imports Example: * import lemur.common.utils -> from lemur.common import utils * import sqlalchemy.types as types -> from sqlalchemy import types --- lemur/certificates/models.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lemur/certificates/models.py b/lemur/certificates/models.py index 87ee3b93..f5b60ad5 100644 --- a/lemur/certificates/models.py +++ b/lemur/certificates/models.py @@ -23,8 +23,6 @@ from sqlalchemy import event, Integer, ForeignKey, String, PassiveDefault, func, from sqlalchemy_utils.types.arrow import ArrowType from werkzeug.utils import cached_property -import lemur.common.utils - from lemur.database import db from lemur.extensions import sentry @@ -188,7 +186,7 @@ class Certificate(db.Model): @cached_property def parsed_cert(self): assert self.body, "Certificate body not set" - return lemur.common.utils.parse_certificate(self.body) + return utils.parse_certificate(self.body) @property def active(self): From a19a47dba1d8a22ae41e2e6401b7c642c735dca4 Mon Sep 17 00:00:00 2001 From: Curtis Castrapel Date: Thu, 12 Jul 2018 13:24:44 -0700 Subject: [PATCH 5/7] updated requirements --- requirements-dev.txt | 8 ++++---- requirements-docs.txt | 2 +- requirements-tests.txt | 14 +++++++------- requirements.txt | 12 ++++++------ 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 4f6d3603..58d6e277 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -10,16 +10,16 @@ certifi==2018.4.16 # via requests cfgv==1.1.0 # via pre-commit chardet==3.0.4 # via requests flake8==3.5.0 -identify==1.1.0 # via pre-commit +identify==1.1.3 # via pre-commit idna==2.7 # via requests -invoke==1.0.0 +invoke==1.1.0 mccabe==0.6.1 # via flake8 nodeenv==1.3.1 pkginfo==1.4.2 # via twine -pre-commit==1.10.2 +pre-commit==1.10.3 pycodestyle==2.3.1 # via flake8 pyflakes==1.6.0 # via flake8 -pyyaml==3.12 # via aspy.yaml, pre-commit +pyyaml==3.13 # via aspy.yaml, pre-commit requests-toolbelt==0.8.0 # via twine requests==2.19.1 # via requests-toolbelt, twine six==1.11.0 # via cfgv, pre-commit diff --git a/requirements-docs.txt b/requirements-docs.txt index 146ddf25..9cfa1b7b 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -79,7 +79,7 @@ six==1.11.0 snowballstemmer==1.2.1 # via sphinx sphinx-rtd-theme==0.4.0 sphinx==1.7.5 -sphinxcontrib-httpdomain==1.6.1 +sphinxcontrib-httpdomain==1.7.0 sphinxcontrib-websupport==1.1.0 # via sphinx sqlalchemy-utils==0.33.3 sqlalchemy==1.2.9 diff --git a/requirements-tests.txt b/requirements-tests.txt index 1da5269f..219c445a 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -8,9 +8,9 @@ asn1crypto==0.24.0 # via cryptography atomicwrites==1.1.5 # via pytest attrs==18.1.0 # via pytest aws-xray-sdk==0.95 # via moto -boto3==1.7.48 # via moto -boto==2.48.0 # via moto -botocore==1.10.48 # via boto3, moto, s3transfer +boto3==1.7.56 # via moto +boto==2.49.0 # via moto +botocore==1.10.56 # via boto3, moto, s3transfer certifi==2018.4.16 # via requests cffi==1.11.5 # via cryptography chardet==3.0.4 # via requests @@ -22,7 +22,7 @@ docker-pycreds==0.3.0 # via docker docker==3.4.1 # via moto docutils==0.14 # via botocore factory-boy==2.11.1 -faker==0.8.16 +faker==0.8.17 flask==1.0.2 # via pytest-flask freezegun==0.3.10 idna==2.7 # via cryptography, requests @@ -36,7 +36,7 @@ mock==2.0.0 # via moto more-itertools==4.2.0 # via pytest moto==1.3.3 nose==1.3.7 -pbr==4.0.4 # via mock +pbr==4.1.0 # via mock pluggy==0.6.0 # via pytest py==1.5.4 # via pytest pyaml==17.12.1 # via moto @@ -44,10 +44,10 @@ pycparser==2.18 # via cffi pyflakes==2.0.0 pytest-flask==0.10.0 pytest-mock==1.10.0 -pytest==3.6.2 +pytest==3.6.3 python-dateutil==2.6.1 # via botocore, faker, freezegun, moto pytz==2018.5 # via moto -pyyaml==3.12 # via pyaml +pyyaml==3.13 # via pyaml requests-mock==1.5.0 requests==2.19.1 # via aws-xray-sdk, docker, moto, requests-mock, responses responses==0.9.0 # via moto diff --git a/requirements.txt b/requirements.txt index dd6ce10f..d80d7e09 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,7 @@ # # pip-compile --no-index --output-file requirements.txt requirements.in # -acme==0.25.1 +acme==0.26.0 alembic-autogenerate-enums==0.0.2 alembic==0.9.10 # via flask-migrate aniso8601==3.0.2 # via flask-restful @@ -13,8 +13,8 @@ asn1crypto==0.24.0 # via cryptography asyncpool==1.0 bcrypt==3.1.4 # via flask-bcrypt, paramiko blinker==1.4 # via flask-mail, flask-principal, raven -boto3==1.7.48 -botocore==1.10.48 # via boto3, s3transfer +boto3==1.7.56 +botocore==1.10.56 # via boto3, s3transfer certifi==2018.4.16 cffi==1.11.5 # via bcrypt, cryptography, pynacl click==6.7 # via flask @@ -34,7 +34,7 @@ flask-script==2.0.6 flask-sqlalchemy==2.3.2 flask==0.12 future==0.16.0 -gunicorn==19.8.1 +gunicorn==19.9.0 idna==2.7 # via cryptography inflection==0.3.1 itsdangerous==0.24 # via flask @@ -50,7 +50,7 @@ marshmallow==2.15.3 mock==2.0.0 # via acme ndg-httpsclient==0.5.0 paramiko==2.4.1 -pbr==4.0.4 # via mock +pbr==4.1.0 # via mock pem==18.1.0 psycopg2==2.7.5 pyasn1-modules==0.2.2 # via python-ldap @@ -64,7 +64,7 @@ python-dateutil==2.7.3 # via alembic, arrow, botocore python-editor==1.0.3 # via alembic python-ldap==3.1.0 pytz==2018.5 # via acme, flask-restful, pyrfc3339 -pyyaml==3.12 # via cloudflare +pyyaml==3.13 # via cloudflare raven[flask]==6.9.0 requests-toolbelt==0.8.0 # via acme requests[security]==2.11.1 From 7f3454128d379da8733c4d528ebd4c2a587c861a Mon Sep 17 00:00:00 2001 From: Steven Reiling Date: Fri, 13 Jul 2018 13:34:43 -0700 Subject: [PATCH 6/7] Adds an optional interval variable to notification service's create_default_expiration_notifications and introduces a new optional configuration variable, LEMUR_SECURITY_TEAM_EMAIL_INTERVALS, to allow admins control over the centralized email notification defaults. --- docs/administration.rst | 10 +++++++++- lemur/certificates/schemas.py | 4 +++- lemur/notifications/service.py | 10 ++++++---- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/docs/administration.rst b/docs/administration.rst index aab7cd58..eec01cc5 100644 --- a/docs/administration.rst +++ b/docs/administration.rst @@ -274,7 +274,6 @@ Lemur supports sending certification expiration notifications through SES and SM LEMUR_SECURITY_TEAM_EMAIL = ['security@example.com'] - .. data:: LEMUR_DEFAULT_EXPIRATION_NOTIFICATION_INTERVALS :noindex: @@ -284,6 +283,15 @@ Lemur supports sending certification expiration notifications through SES and SM LEMUR_DEFAULT_EXPIRATION_NOTIFICATION_INTERVALS = [30, 15, 2] +.. data:: LEMUR_SECURITY_TEAM_EMAIL_INTERVALS + :noindex: + + Alternate notification interval set for security team notifications. Use this if you would like the default security team notification interval for new certificates to differ from the global default as specified in LEMUR_DEFAULT_EXPIRATION_NOTIFICATION_INTERVALS. If unspecified, the value of LEMUR_DEFAULT_EXPIRATION_NOTIFICATION_INTERVALS is used. Security team default notifications for new certificates can effectively be disabled by setting this value to an empty array. + + :: + + LEMUR_SECURITY_TEAM_EMAIL_INTERVALS = [15, 2] + Authentication Options ---------------------- diff --git a/lemur/certificates/schemas.py b/lemur/certificates/schemas.py index 72b42fb9..e88b6e73 100644 --- a/lemur/certificates/schemas.py +++ b/lemur/certificates/schemas.py @@ -48,9 +48,11 @@ class CertificateCreationSchema(CertificateSchema): "DEFAULT_{0}".format(data['owner'].split('@')[0].upper()), [data['owner']], ) + data['notifications'] += notification_service.create_default_expiration_notifications( 'DEFAULT_SECURITY', - current_app.config.get('LEMUR_SECURITY_TEAM_EMAIL') + current_app.config.get('LEMUR_SECURITY_TEAM_EMAIL'), + current_app.config.get('LEMUR_SECURITY_TEAM_EMAIL_INTERVALS', None) ) return data diff --git a/lemur/notifications/service.py b/lemur/notifications/service.py index 466c680b..957757bd 100644 --- a/lemur/notifications/service.py +++ b/lemur/notifications/service.py @@ -16,10 +16,11 @@ from lemur.common.utils import truthiness from lemur.notifications.models import Notification -def create_default_expiration_notifications(name, recipients): +def create_default_expiration_notifications(name, recipients, intervals=None): """ - Will create standard 30, 10 and 2 day notifications for a given owner. If standard notifications - already exist these will be returned instead of new notifications. + Will create standard 30, 10 and 2 day notifications for a given owner unless an alternate set of + intervals is supplied. If standard notifications already exist these will be returned instead of + new notifications. :param name: :param recipients: @@ -48,7 +49,8 @@ def create_default_expiration_notifications(name, recipients): }, ] - intervals = current_app.config.get("LEMUR_DEFAULT_EXPIRATION_NOTIFICATION_INTERVALS", [30, 15, 2]) + if intervals is None: + intervals = current_app.config.get("LEMUR_DEFAULT_EXPIRATION_NOTIFICATION_INTERVALS", [30, 15, 2]) notifications = [] for i in intervals: From be9be6d3cd283351486992c51bf0e41114d88b78 Mon Sep 17 00:00:00 2001 From: Curtis Castrapel Date: Tue, 17 Jul 2018 18:38:15 -0700 Subject: [PATCH 7/7] Unpinning requests --- requirements-docs.txt | 14 +++++++------- requirements-tests.txt | 4 ++-- requirements.in | 4 ++-- requirements.txt | 20 +++++++++++--------- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/requirements-docs.txt b/requirements-docs.txt index 9cfa1b7b..bc930c58 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -4,7 +4,7 @@ # # pip-compile --no-index --output-file requirements-docs.txt requirements-docs.in # -acme==0.25.1 +acme==0.26.0 alabaster==0.7.11 # via sphinx alembic-autogenerate-enums==0.0.2 alembic==0.9.10 @@ -15,8 +15,8 @@ asyncpool==1.0 babel==2.6.0 # via sphinx bcrypt==3.1.4 blinker==1.4 -boto3==1.7.48 -botocore==1.10.48 +boto3==1.7.56 +botocore==1.10.56 certifi==2018.4.16 cffi==1.11.5 click==6.7 @@ -36,7 +36,7 @@ flask-script==2.0.6 flask-sqlalchemy==2.3.2 flask==0.12 future==0.16.0 -gunicorn==19.8.1 +gunicorn==19.9.0 idna==2.7 imagesize==1.0.0 # via sphinx inflection==0.3.1 @@ -54,7 +54,7 @@ mock==2.0.0 ndg-httpsclient==0.5.0 packaging==17.1 # via sphinx paramiko==2.4.1 -pbr==4.0.4 +pbr==4.1.0 pem==18.1.0 psycopg2==2.7.5 pyasn1-modules==0.2.2 @@ -69,7 +69,7 @@ pyrfc3339==1.1 python-dateutil==2.7.3 python-editor==1.0.3 pytz==2018.5 -pyyaml==3.12 +pyyaml==3.13 raven[flask]==6.9.0 requests-toolbelt==0.8.0 requests[security]==2.11.1 @@ -78,7 +78,7 @@ s3transfer==0.1.13 six==1.11.0 snowballstemmer==1.2.1 # via sphinx sphinx-rtd-theme==0.4.0 -sphinx==1.7.5 +sphinx==1.7.6 sphinxcontrib-httpdomain==1.7.0 sphinxcontrib-websupport==1.1.0 # via sphinx sqlalchemy-utils==0.33.3 diff --git a/requirements-tests.txt b/requirements-tests.txt index 219c445a..55836e9a 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -8,9 +8,9 @@ asn1crypto==0.24.0 # via cryptography atomicwrites==1.1.5 # via pytest attrs==18.1.0 # via pytest aws-xray-sdk==0.95 # via moto -boto3==1.7.56 # via moto +boto3==1.7.59 # via moto boto==2.49.0 # via moto -botocore==1.10.56 # via boto3, moto, s3transfer +botocore==1.10.59 # via boto3, moto, s3transfer certifi==2018.4.16 # via requests cffi==1.11.5 # via cryptography chardet==3.0.4 # via requests diff --git a/requirements.in b/requirements.in index 2a5051a7..0e028261 100644 --- a/requirements.in +++ b/requirements.in @@ -31,10 +31,10 @@ paramiko # required for the SFTP destination plugin pem psycopg2 pyjwt -pyOpenSSL==17.2.0 # PINNED for a specific reason. This needs to be merged in before upgrade: https://github.com/shazow/urllib3/pull/1246 +pyOpenSSL python_ldap raven[flask] -requests==2.11.1 # PINNED for a specific reason. This needs to be merged in before upgrade: https://github.com/shazow/urllib3/pull/1246 +requests retrying six SQLAlchemy-Utils diff --git a/requirements.txt b/requirements.txt index d80d7e09..82817e7e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,19 +4,20 @@ # # pip-compile --no-index --output-file requirements.txt requirements.in # -acme==0.26.0 +acme==0.26.1 alembic-autogenerate-enums==0.0.2 -alembic==0.9.10 # via flask-migrate +alembic==1.0.0 # via flask-migrate aniso8601==3.0.2 # via flask-restful arrow==0.12.1 asn1crypto==0.24.0 # via cryptography asyncpool==1.0 bcrypt==3.1.4 # via flask-bcrypt, paramiko blinker==1.4 # via flask-mail, flask-principal, raven -boto3==1.7.56 -botocore==1.10.56 # via boto3, s3transfer +boto3==1.7.59 +botocore==1.10.59 # via boto3, s3transfer certifi==2018.4.16 cffi==1.11.5 # via bcrypt, cryptography, pynacl +chardet==3.0.4 # via requests click==6.7 # via flask cloudflare==2.1.0 cryptography==2.2.2 @@ -35,7 +36,7 @@ flask-sqlalchemy==2.3.2 flask==0.12 future==0.16.0 gunicorn==19.9.0 -idna==2.7 # via cryptography +idna==2.7 # via cryptography, requests inflection==0.3.1 itsdangerous==0.24 # via flask jinja2==2.10 @@ -54,11 +55,11 @@ pbr==4.1.0 # via mock pem==18.1.0 psycopg2==2.7.5 pyasn1-modules==0.2.2 # via python-ldap -pyasn1==0.4.3 # via ndg-httpsclient, paramiko, pyasn1-modules, python-ldap, requests +pyasn1==0.4.3 # via ndg-httpsclient, paramiko, pyasn1-modules, python-ldap pycparser==2.18 # via cffi pyjwt==1.6.4 pynacl==1.2.1 # via paramiko -pyopenssl==17.2.0 +pyopenssl==18.0.0 pyrfc3339==1.1 # via acme python-dateutil==2.7.3 # via alembic, arrow, botocore python-editor==1.0.3 # via alembic @@ -67,12 +68,13 @@ pytz==2018.5 # via acme, flask-restful, pyrfc3339 pyyaml==3.13 # via cloudflare raven[flask]==6.9.0 requests-toolbelt==0.8.0 # via acme -requests[security]==2.11.1 +requests[security]==2.19.1 retrying==1.3.3 s3transfer==0.1.13 # via boto3 six==1.11.0 sqlalchemy-utils==0.33.3 -sqlalchemy==1.2.9 # via alembic, flask-sqlalchemy, marshmallow-sqlalchemy, sqlalchemy-utils +sqlalchemy==1.2.10 # via alembic, flask-sqlalchemy, marshmallow-sqlalchemy, sqlalchemy-utils tabulate==0.8.2 +urllib3==1.23 # via requests werkzeug==0.14.1 # via flask xmltodict==0.11.0