From dbf34a4d48152db540bcaacb92453ef33e878ee4 Mon Sep 17 00:00:00 2001 From: Marti Raudsepp Date: Fri, 5 Apr 2019 17:52:55 +0300 Subject: [PATCH 1/2] Rewrite Java Keystore/Truststore support based on pyjks library --- lemur/common/utils.py | 4 +- lemur/plugins/lemur_java/plugin.py | 246 ------------------ lemur/plugins/lemur_java/tests/test_java.py | 63 ----- .../{lemur_java => lemur_jks}/__init__.py | 0 lemur/plugins/lemur_jks/plugin.py | 140 ++++++++++ .../tests/conftest.py | 0 lemur/plugins/lemur_jks/tests/test_jks.py | 96 +++++++ requirements.in | 1 + requirements.txt | 1 + setup.py | 4 +- 10 files changed, 243 insertions(+), 312 deletions(-) delete mode 100644 lemur/plugins/lemur_java/plugin.py delete mode 100644 lemur/plugins/lemur_java/tests/test_java.py rename lemur/plugins/{lemur_java => lemur_jks}/__init__.py (100%) create mode 100644 lemur/plugins/lemur_jks/plugin.py rename lemur/plugins/{lemur_java => lemur_jks}/tests/conftest.py (100%) create mode 100644 lemur/plugins/lemur_jks/tests/test_jks.py diff --git a/lemur/common/utils.py b/lemur/common/utils.py index 62c3182b..24ff5784 100644 --- a/lemur/common/utils.py +++ b/lemur/common/utils.py @@ -85,7 +85,9 @@ def parse_cert_chain(pem_chain): :param pem_chain: string :return: List of parsed certificates """ - return [parse_certificate(cert) for cert in split_pem(pem_chain) if pem_chain] + if pem_chain is None: + return [] + return [parse_certificate(cert) for cert in split_pem(pem_chain) if cert] def parse_csr(csr): diff --git a/lemur/plugins/lemur_java/plugin.py b/lemur/plugins/lemur_java/plugin.py deleted file mode 100644 index 7eb33b90..00000000 --- a/lemur/plugins/lemur_java/plugin.py +++ /dev/null @@ -1,246 +0,0 @@ -""" -.. module: lemur.plugins.lemur_java.plugin - :platform: Unix - :copyright: (c) 2018 by Netflix Inc., see AUTHORS for more - :license: Apache, see LICENSE for more details. - -.. moduleauthor:: Kevin Glisson -""" -import subprocess - -from flask import current_app - -from cryptography.fernet import Fernet - -from lemur.utils import mktempfile, mktemppath -from lemur.plugins.bases import ExportPlugin -from lemur.plugins import lemur_java as java -from lemur.common.utils import parse_certificate -from lemur.common.defaults import common_name - - -def run_process(command): - """ - Runs a given command with pOpen and wraps some - error handling around it. - :param command: - :return: - """ - p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - stdout, stderr = p.communicate() - - if p.returncode != 0: - current_app.logger.debug(" ".join(command)) - current_app.logger.error(stderr) - current_app.logger.error(stdout) - raise Exception(stderr) - - -def split_chain(chain): - """ - Split the chain into individual certificates for import into keystore - - :param chain: - :return: - """ - certs = [] - - if not chain: - return certs - - lines = chain.split('\n') - - cert = [] - for line in lines: - cert.append(line + '\n') - if line == '-----END CERTIFICATE-----': - certs.append("".join(cert)) - cert = [] - - return certs - - -def create_truststore(cert, chain, jks_tmp, alias, passphrase): - assert isinstance(cert, str) - assert isinstance(chain, str) - - with mktempfile() as cert_tmp: - with open(cert_tmp, 'w') as f: - f.write(cert) - - run_process([ - "keytool", - "-importcert", - "-file", cert_tmp, - "-keystore", jks_tmp, - "-alias", "{0}_cert".format(alias), - "-storepass", passphrase, - "-noprompt" - ]) - - # Import the entire chain - for idx, cert in enumerate(split_chain(chain)): - with mktempfile() as c_tmp: - with open(c_tmp, 'w') as f: - f.write(cert) - - # Import signed cert in to JKS keystore - run_process([ - "keytool", - "-importcert", - "-file", c_tmp, - "-keystore", jks_tmp, - "-alias", "{0}_cert_{1}".format(alias, idx), - "-storepass", passphrase, - "-noprompt" - ]) - - -def create_keystore(cert, chain, jks_tmp, key, alias, passphrase): - assert isinstance(cert, str) - assert isinstance(chain, str) - assert isinstance(key, str) - - # Create PKCS12 keystore from private key and public certificate - with mktempfile() as cert_tmp: - with open(cert_tmp, 'w') as f: - if chain: - f.writelines([key.strip() + "\n", cert.strip() + "\n", chain.strip() + "\n"]) - else: - f.writelines([key.strip() + "\n", cert.strip() + "\n"]) - - with mktempfile() as p12_tmp: - run_process([ - "openssl", - "pkcs12", - "-export", - "-nodes", - "-name", alias, - "-in", cert_tmp, - "-out", p12_tmp, - "-password", "pass:{}".format(passphrase) - ]) - - # Convert PKCS12 keystore into a JKS keystore - run_process([ - "keytool", - "-importkeystore", - "-destkeystore", jks_tmp, - "-srckeystore", p12_tmp, - "-srcstoretype", "pkcs12", - "-deststoretype", "JKS", - "-alias", alias, - "-srcstorepass", passphrase, - "-deststorepass", passphrase - ]) - - -class JavaTruststoreExportPlugin(ExportPlugin): - title = 'Java Truststore (JKS)' - slug = 'java-truststore-jks' - description = 'Attempts to generate a JKS truststore' - requires_key = False - version = java.VERSION - - author = 'Kevin Glisson' - author_url = 'https://github.com/netflix/lemur' - - options = [ - { - 'name': 'alias', - 'type': 'str', - 'required': False, - 'helpMessage': 'Enter the alias you wish to use for the truststore.', - }, - { - 'name': 'passphrase', - 'type': 'str', - 'required': False, - 'helpMessage': 'If no passphrase is given one will be generated for you, we highly recommend this. Minimum length is 8.', - 'validation': '' - }, - ] - - def export(self, body, chain, key, options, **kwargs): - """ - Generates a Java Truststore - - :param key: - :param chain: - :param body: - :param options: - :param kwargs: - """ - - if self.get_option('alias', options): - alias = self.get_option('alias', options) - else: - alias = "blah" - - if self.get_option('passphrase', options): - passphrase = self.get_option('passphrase', options) - else: - passphrase = Fernet.generate_key().decode('utf-8') - - with mktemppath() as jks_tmp: - create_truststore(body, chain, jks_tmp, alias, passphrase) - - with open(jks_tmp, 'rb') as f: - raw = f.read() - - return "jks", passphrase, raw - - -class JavaKeystoreExportPlugin(ExportPlugin): - title = 'Java Keystore (JKS)' - slug = 'java-keystore-jks' - description = 'Attempts to generate a JKS keystore' - version = java.VERSION - - author = 'Kevin Glisson' - author_url = 'https://github.com/netflix/lemur' - - options = [ - { - 'name': 'passphrase', - 'type': 'str', - 'required': False, - 'helpMessage': 'If no passphrase is given one will be generated for you, we highly recommend this. Minimum length is 8.', - 'validation': '' - }, - { - 'name': 'alias', - 'type': 'str', - 'required': False, - 'helpMessage': 'Enter the alias you wish to use for the keystore.', - } - ] - - def export(self, body, chain, key, options, **kwargs): - """ - Generates a Java Keystore - - :param key: - :param chain: - :param body: - :param options: - :param kwargs: - """ - - if self.get_option('passphrase', options): - passphrase = self.get_option('passphrase', options) - else: - passphrase = Fernet.generate_key().decode('utf-8') - - if self.get_option('alias', options): - alias = self.get_option('alias', options) - else: - alias = common_name(parse_certificate(body)) - - with mktemppath() as jks_tmp: - create_keystore(body, chain, jks_tmp, key, alias, passphrase) - - with open(jks_tmp, 'rb') as f: - raw = f.read() - - return "jks", passphrase, raw diff --git a/lemur/plugins/lemur_java/tests/test_java.py b/lemur/plugins/lemur_java/tests/test_java.py deleted file mode 100644 index 2b8598b8..00000000 --- a/lemur/plugins/lemur_java/tests/test_java.py +++ /dev/null @@ -1,63 +0,0 @@ -import pytest - -from lemur.tests.vectors import INTERNAL_CERTIFICATE_A_STR, INTERNAL_PRIVATE_KEY_A_STR - - -@pytest.mark.skip(reason="no way of currently testing this") -def test_export_truststore(app): - from lemur.plugins.base import plugins - - p = plugins.get('java-truststore-jks') - options = [{'name': 'passphrase', 'value': 'test1234'}] - actual = p.export(INTERNAL_CERTIFICATE_A_STR, "", "", options) - - assert actual[0] == 'jks' - assert actual[1] == 'test1234' - assert isinstance(actual[2], bytes) - - -@pytest.mark.skip(reason="no way of currently testing this") -def test_export_truststore_default_password(app): - from lemur.plugins.base import plugins - - p = plugins.get('java-truststore-jks') - options = [] - actual = p.export(INTERNAL_CERTIFICATE_A_STR, "", "", options) - - assert actual[0] == 'jks' - assert isinstance(actual[1], str) - assert isinstance(actual[2], bytes) - - -@pytest.mark.skip(reason="no way of currently testing this") -def test_export_keystore(app): - from lemur.plugins.base import plugins - - p = plugins.get('java-keystore-jks') - options = [{'name': 'passphrase', 'value': 'test1234'}] - - with pytest.raises(Exception): - p.export(INTERNAL_CERTIFICATE_A_STR, "", "", options) - - actual = p.export(INTERNAL_CERTIFICATE_A_STR, "", INTERNAL_PRIVATE_KEY_A_STR, options) - - assert actual[0] == 'jks' - assert actual[1] == 'test1234' - assert isinstance(actual[2], bytes) - - -@pytest.mark.skip(reason="no way of currently testing this") -def test_export_keystore_default_password(app): - from lemur.plugins.base import plugins - - p = plugins.get('java-keystore-jks') - options = [] - - with pytest.raises(Exception): - p.export(INTERNAL_CERTIFICATE_A_STR, "", "", options) - - actual = p.export(INTERNAL_CERTIFICATE_A_STR, "", INTERNAL_PRIVATE_KEY_A_STR, options) - - assert actual[0] == 'jks' - assert isinstance(actual[1], str) - assert isinstance(actual[2], bytes) diff --git a/lemur/plugins/lemur_java/__init__.py b/lemur/plugins/lemur_jks/__init__.py similarity index 100% rename from lemur/plugins/lemur_java/__init__.py rename to lemur/plugins/lemur_jks/__init__.py diff --git a/lemur/plugins/lemur_jks/plugin.py b/lemur/plugins/lemur_jks/plugin.py new file mode 100644 index 00000000..3d456f1c --- /dev/null +++ b/lemur/plugins/lemur_jks/plugin.py @@ -0,0 +1,140 @@ +""" +.. module: lemur.plugins.lemur_jks.plugin + :platform: Unix + :copyright: (c) 2018 by Netflix Inc., see AUTHORS for more + :license: Apache, see LICENSE for more details. + +.. moduleauthor:: Marti Raudsepp +""" + +from cryptography.fernet import Fernet +from cryptography.hazmat.primitives import serialization +from jks import PrivateKeyEntry, KeyStore, TrustedCertEntry + +from lemur.common.defaults import common_name +from lemur.common.utils import parse_certificate, parse_cert_chain, parse_private_key +from lemur.plugins import lemur_jks as jks +from lemur.plugins.bases import ExportPlugin + + +def cert_chain_as_der(cert, chain): + """Return a certificate and its chain in a list format, as expected by pyjks.""" + + certs = [parse_certificate(cert)] + certs.extend(parse_cert_chain(chain)) + # certs (list) – A list of certificates, as byte strings. The first one should be the one belonging to the private + # key, the others the chain (in correct order). + return [cert.public_bytes(encoding=serialization.Encoding.DER) for cert in certs] + + +def create_truststore(cert, chain, alias, passphrase): + entries = [] + for idx, cert_bytes in enumerate(cert_chain_as_der(cert, chain)): + # The original cert gets name _cert, first chain element is _cert_1, etc. + cert_alias = alias + '_cert' + ('_{}'.format(idx) if idx else '') + entries.append(TrustedCertEntry.new(cert_alias, cert_bytes)) + + return KeyStore.new('jks', entries).saves(passphrase) + + +def create_keystore(cert, chain, key, alias, passphrase): + certs_bytes = cert_chain_as_der(cert, chain) + key_bytes = parse_private_key(key).private_bytes( + encoding=serialization.Encoding.DER, + format=serialization.PrivateFormat.PKCS8, + encryption_algorithm=serialization.NoEncryption() + ) + entry = PrivateKeyEntry.new(alias, certs_bytes, key_bytes) + + return KeyStore.new('jks', [entry]).saves(passphrase) + + +class JavaTruststoreExportPlugin(ExportPlugin): + title = 'Java Truststore (JKS)' + slug = 'java-truststore-jks' + description = 'Generates a JKS truststore' + requires_key = False + version = jks.VERSION + + author = 'Marti Raudsepp' + author_url = 'https://github.com/intgr' + + options = [ + { + 'name': 'alias', + 'type': 'str', + 'required': False, + 'helpMessage': 'Enter the alias you wish to use for the truststore.', + }, + { + 'name': 'passphrase', + 'type': 'str', + 'required': False, + 'helpMessage': 'If no passphrase is given one will be generated for you, we highly recommend this.', + 'validation': '' + }, + ] + + def export(self, body, chain, key, options, **kwargs): + """ + Generates a Java Truststore + """ + + if self.get_option('alias', options): + alias = self.get_option('alias', options) + else: + alias = common_name(parse_certificate(body)) + + if self.get_option('passphrase', options): + passphrase = self.get_option('passphrase', options) + else: + passphrase = Fernet.generate_key().decode('utf-8') + + raw = create_truststore(body, chain, alias, passphrase) + + return 'jks', passphrase, raw + + +class JavaKeystoreExportPlugin(ExportPlugin): + title = 'Java Keystore (JKS)' + slug = 'java-keystore-jks' + description = 'Generates a JKS keystore' + version = jks.VERSION + + author = 'Marti Raudsepp' + author_url = 'https://github.com/intgr' + + options = [ + { + 'name': 'passphrase', + 'type': 'str', + 'required': False, + 'helpMessage': 'If no passphrase is given one will be generated for you, we highly recommend this.', + 'validation': '' + }, + { + 'name': 'alias', + 'type': 'str', + 'required': False, + 'helpMessage': 'Enter the alias you wish to use for the keystore.', + } + ] + + def export(self, body, chain, key, options, **kwargs): + """ + Generates a Java Keystore + """ + + if self.get_option('passphrase', options): + passphrase = self.get_option('passphrase', options) + else: + passphrase = Fernet.generate_key().decode('utf-8') + + if self.get_option('alias', options): + alias = self.get_option('alias', options) + else: + alias = common_name(parse_certificate(body)) + + raw = create_keystore(body, chain, key, alias, passphrase) + + return 'jks', passphrase, raw diff --git a/lemur/plugins/lemur_java/tests/conftest.py b/lemur/plugins/lemur_jks/tests/conftest.py similarity index 100% rename from lemur/plugins/lemur_java/tests/conftest.py rename to lemur/plugins/lemur_jks/tests/conftest.py diff --git a/lemur/plugins/lemur_jks/tests/test_jks.py b/lemur/plugins/lemur_jks/tests/test_jks.py new file mode 100644 index 00000000..e4a5e64a --- /dev/null +++ b/lemur/plugins/lemur_jks/tests/test_jks.py @@ -0,0 +1,96 @@ +import pytest +from jks import KeyStore, TrustedCertEntry, PrivateKeyEntry + +from lemur.tests.vectors import INTERNAL_CERTIFICATE_A_STR, SAN_CERT_STR, INTERMEDIATE_CERT_STR, ROOTCA_CERT_STR, \ + SAN_CERT_KEY + + +def test_export_truststore(app): + from lemur.plugins.base import plugins + + p = plugins.get('java-truststore-jks') + options = [ + {'name': 'passphrase', 'value': 'hunter2'}, + {'name': 'alias', 'value': 'AzureDiamond'}, + ] + chain = INTERMEDIATE_CERT_STR + '\n' + ROOTCA_CERT_STR + ext, password, raw = p.export(SAN_CERT_STR, chain, SAN_CERT_KEY, options) + + assert ext == 'jks' + assert password == 'hunter2' + assert isinstance(raw, bytes) + + ks = KeyStore.loads(raw, 'hunter2') + assert ks.store_type == 'jks' + # JKS lower-cases alias strings + assert ks.entries.keys() == {'azurediamond_cert', 'azurediamond_cert_1', 'azurediamond_cert_2'} + assert isinstance(ks.entries['azurediamond_cert'], TrustedCertEntry) + + +def test_export_truststore_defaults(app): + from lemur.plugins.base import plugins + + p = plugins.get('java-truststore-jks') + options = [] + ext, password, raw = p.export(INTERNAL_CERTIFICATE_A_STR, '', '', options) + + assert ext == 'jks' + assert isinstance(password, str) + assert isinstance(raw, bytes) + + ks = KeyStore.loads(raw, password) + assert ks.store_type == 'jks' + # JKS lower-cases alias strings + assert ks.entries.keys() == {'acommonname_cert'} + assert isinstance(ks.entries['acommonname_cert'], TrustedCertEntry) + + +def test_export_keystore(app): + from lemur.plugins.base import plugins + + p = plugins.get('java-keystore-jks') + options = [ + {'name': 'passphrase', 'value': 'hunter2'}, + {'name': 'alias', 'value': 'AzureDiamond'}, + ] + + chain = INTERMEDIATE_CERT_STR + '\n' + ROOTCA_CERT_STR + with pytest.raises(Exception): + p.export(INTERNAL_CERTIFICATE_A_STR, chain, '', options) + + ext, password, raw = p.export(SAN_CERT_STR, chain, SAN_CERT_KEY, options) + + assert ext == 'jks' + assert password == 'hunter2' + assert isinstance(raw, bytes) + + ks = KeyStore.loads(raw, password) + assert ks.store_type == 'jks' + # JKS lower-cases alias strings + assert ks.entries.keys() == {'azurediamond'} + entry = ks.entries['azurediamond'] + assert isinstance(entry, PrivateKeyEntry) + assert len(entry.cert_chain) == 3 # Cert and chain were provided + + +def test_export_keystore_defaults(app): + from lemur.plugins.base import plugins + + p = plugins.get('java-keystore-jks') + options = [] + + with pytest.raises(Exception): + p.export(INTERNAL_CERTIFICATE_A_STR, '', '', options) + + ext, password, raw = p.export(SAN_CERT_STR, '', SAN_CERT_KEY, options) + + assert ext == 'jks' + assert isinstance(password, str) + assert isinstance(raw, bytes) + + ks = KeyStore.loads(raw, password) + assert ks.store_type == 'jks' + assert ks.entries.keys() == {'san.example.org'} + entry = ks.entries['san.example.org'] + assert isinstance(entry, PrivateKeyEntry) + assert len(entry.cert_chain) == 1 # Only cert itself, no chain was provided diff --git a/requirements.in b/requirements.in index 9b27f604..ecd95284 100644 --- a/requirements.in +++ b/requirements.in @@ -47,3 +47,4 @@ SQLAlchemy-Utils tabulate xmltodict pyyaml>=4.2b1 #high severity alert +pyjks diff --git a/requirements.txt b/requirements.txt index c0e69fb4..b458fb00 100644 --- a/requirements.txt +++ b/requirements.txt @@ -86,3 +86,4 @@ urllib3==1.24.1 # via botocore, requests vine==1.3.0 # via amqp werkzeug==0.15.1 # via flask xmltodict==0.12.0 +pyjks==18.0.0 diff --git a/setup.py b/setup.py index 148f51b1..6fc55420 100644 --- a/setup.py +++ b/setup.py @@ -143,8 +143,8 @@ setup( 'aws_s3 = lemur.plugins.lemur_aws.plugin:S3DestinationPlugin', 'email_notification = lemur.plugins.lemur_email.plugin:EmailNotificationPlugin', 'slack_notification = lemur.plugins.lemur_slack.plugin:SlackNotificationPlugin', - 'java_truststore_export = lemur.plugins.lemur_java.plugin:JavaTruststoreExportPlugin', - 'java_keystore_export = lemur.plugins.lemur_java.plugin:JavaKeystoreExportPlugin', + 'java_truststore_export = lemur.plugins.lemur_jks.plugin:JavaTruststoreExportPlugin', + 'java_keystore_export = lemur.plugins.lemur_jks.plugin:JavaKeystoreExportPlugin', 'openssl_export = lemur.plugins.lemur_openssl.plugin:OpenSSLExportPlugin', 'atlas_metric = lemur.plugins.lemur_atlas.plugin:AtlasMetricPlugin', 'kubernetes_destination = lemur.plugins.lemur_kubernetes.plugin:KubernetesDestinationPlugin', From d1e5a40d2097e91aaf6dbcf9d9779e3d76fe0b6d Mon Sep 17 00:00:00 2001 From: Hossein Shafagh Date: Mon, 22 Apr 2019 09:49:03 -0700 Subject: [PATCH 2/2] updating requirements, addressing the urllib3 high severity warning --- requirements-dev.txt | 4 ++-- requirements-docs.txt | 8 ++++---- requirements-tests.txt | 14 +++++++------- requirements.txt | 8 ++++---- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index e62d1ee6..f9f1b8f3 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -18,7 +18,7 @@ invoke==1.2.0 mccabe==0.6.1 # via flake8 nodeenv==1.3.3 pkginfo==1.5.0.1 # via twine -pre-commit==1.15.1 +pre-commit==1.15.2 pycodestyle==2.3.1 # via flake8 pyflakes==1.6.0 # via flake8 pygments==2.3.1 # via readme-renderer @@ -30,7 +30,7 @@ six==1.12.0 # via bleach, cfgv, pre-commit, readme-renderer toml==0.10.0 # via pre-commit tqdm==4.31.1 # via twine twine==1.13.0 -urllib3==1.24.1 # via requests +urllib3==1.24.2 # via requests virtualenv==16.4.3 # via pre-commit webencodings==0.5.1 # via bleach zipp==0.3.3 # via importlib-metadata diff --git a/requirements-docs.txt b/requirements-docs.txt index 3948e2a8..3ec6bb3b 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -17,12 +17,12 @@ babel==2.6.0 # via sphinx bcrypt==3.1.6 billiard==3.6.0.0 blinker==1.4 -boto3==1.9.130 -botocore==1.12.130 +boto3==1.9.134 +botocore==1.12.134 celery[redis]==4.3.0 certifi==2019.3.9 certsrv==2.1.1 -cffi==1.12.2 +cffi==1.12.3 chardet==3.0.4 click==7.0 cloudflare==2.1.0 @@ -97,7 +97,7 @@ sphinxcontrib-serializinghtml==1.1.3 # via sphinx sqlalchemy-utils==0.33.11 sqlalchemy==1.3.3 tabulate==0.8.3 -urllib3==1.24.1 +urllib3==1.24.2 vine==1.3.0 werkzeug==0.15.2 xmltodict==0.12.0 diff --git a/requirements-tests.txt b/requirements-tests.txt index e2ddf830..9ae156a1 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -8,11 +8,11 @@ asn1crypto==0.24.0 # via cryptography atomicwrites==1.3.0 # via pytest attrs==19.1.0 # via pytest aws-xray-sdk==0.95 # via moto -boto3==1.9.130 # via moto +boto3==1.9.134 # via moto boto==2.49.0 # via moto -botocore==1.12.130 # via boto3, moto, s3transfer +botocore==1.12.134 # via boto3, moto, s3transfer certifi==2019.3.9 # via requests -cffi==1.12.2 # via cryptography +cffi==1.12.3 # via cryptography chardet==3.0.4 # via requests click==7.0 # via flask coverage==4.5.3 @@ -20,7 +20,7 @@ cryptography==2.6.1 # via moto docker-pycreds==0.4.0 # via docker docker==3.7.2 # via moto docutils==0.14 # via botocore -ecdsa==0.13 # via python-jose +ecdsa==0.13.2 # via python-jose factory-boy==2.11.1 faker==1.0.5 flask==1.0.2 # via pytest-flask @@ -40,12 +40,12 @@ nose==1.3.7 pbr==5.1.3 # via mock pluggy==0.9.0 # via pytest py==1.8.0 # via pytest -pyaml==18.11.0 # via moto +pyaml==19.4.1 # via moto pycparser==2.19 # via cffi pycryptodome==3.8.1 # via python-jose pyflakes==2.1.1 pytest-flask==0.14.0 -pytest-mock==1.10.3 +pytest-mock==1.10.4 pytest==4.4.1 python-dateutil==2.8.0 # via botocore, faker, freezegun, moto python-jose==2.0.2 # via moto @@ -57,7 +57,7 @@ responses==0.10.6 # via moto s3transfer==0.2.0 # via boto3 six==1.12.0 # via cryptography, docker, docker-pycreds, faker, freezegun, mock, moto, pytest, python-dateutil, python-jose, requests-mock, responses, websocket-client text-unidecode==1.2 # via faker -urllib3==1.24.1 # via botocore, requests +urllib3==1.24.2 # via botocore, requests websocket-client==0.56.0 # via docker werkzeug==0.15.2 # via flask, moto, pytest-flask wrapt==1.11.1 # via aws-xray-sdk diff --git a/requirements.txt b/requirements.txt index d16d4bb5..98b4d666 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,12 +15,12 @@ asyncpool==1.0 bcrypt==3.1.6 # via flask-bcrypt, paramiko billiard==3.6.0.0 # via celery blinker==1.4 # via flask-mail, flask-principal, raven -boto3==1.9.130 -botocore==1.12.130 +boto3==1.9.134 +botocore==1.12.134 celery[redis]==4.3.0 certifi==2019.3.9 certsrv==2.1.1 -cffi==1.12.2 # via bcrypt, cryptography, pynacl +cffi==1.12.3 # via bcrypt, cryptography, pynacl chardet==3.0.4 # via requests click==7.0 # via flask cloudflare==2.1.0 @@ -82,7 +82,7 @@ six==1.12.0 sqlalchemy-utils==0.33.11 sqlalchemy==1.3.3 # via alembic, flask-sqlalchemy, marshmallow-sqlalchemy, sqlalchemy-utils tabulate==0.8.3 -urllib3==1.24.1 # via botocore, requests +urllib3==1.24.2 # via botocore, requests vine==1.3.0 # via amqp, celery werkzeug==0.15.2 # via flask xmltodict==0.12.0