From 8efa68285874b7d9d98c55dbd54f360d9c80f31f Mon Sep 17 00:00:00 2001 From: Hossein Shafagh Date: Tue, 10 Nov 2020 17:43:35 -0800 Subject: [PATCH 01/27] add delete acme token --- lemur/plugins/lemur_aws/plugin.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/lemur/plugins/lemur_aws/plugin.py b/lemur/plugins/lemur_aws/plugin.py index b54787ac..8fca73e9 100644 --- a/lemur/plugins/lemur_aws/plugin.py +++ b/lemur/plugins/lemur_aws/plugin.py @@ -449,6 +449,34 @@ class S3DestinationPlugin(ExportDestinationPlugin): metrics.send(f"{function}", "counter", 1, metric_tags={"result": res, "bucket_name": bucket_name, "filename": filename}) + return response + + def delete_acme_token(self, token_path, options, **kwargs): + + current_app.logger.debug("S3 destination plugin is started to delete HTTP-01 challenge") + + function = f"{__name__}.{sys._getframe().f_code.co_name}" + + account_number = self.get_option("accountNumber", options) + bucket_name = self.get_option("bucket", options) + prefix = self.get_option("prefix", options) + filename = token_path.split("/")[-1] + response = s3.delete(bucket_name=bucket_name, + prefixed_object_name=prefix + filename, + account_number=account_number) + res = "Success" if response else "Failure" + log_data = { + "function": function, + "message": "delete acme token challenge", + "result": res, + "bucket_name": bucket_name, + "filename": filename + } + current_app.logger.info(log_data) + metrics.send(f"{function}", "counter", 1, metric_tags={"result": res, + "bucket_name": bucket_name, + "filename": filename}) + return response class SNSNotificationPlugin(ExpirationNotificationPlugin): From ea77ef08aa2656b8c1b873d782d7932f37a25ab4 Mon Sep 17 00:00:00 2001 From: Hossein Shafagh Date: Tue, 10 Nov 2020 17:45:02 -0800 Subject: [PATCH 02/27] testing for delete --- lemur/plugins/lemur_aws/tests/test_plugin.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lemur/plugins/lemur_aws/tests/test_plugin.py b/lemur/plugins/lemur_aws/tests/test_plugin.py index be9b14fd..89a318ca 100644 --- a/lemur/plugins/lemur_aws/tests/test_plugin.py +++ b/lemur/plugins/lemur_aws/tests/test_plugin.py @@ -80,3 +80,8 @@ def test_upload_acme_token(app): # put data, and getting the same data assert (response == token_content) + + response = p.delete_acme_token(token_path=token_path, + options=additional_options, + account_number=account) + assert response From 252f84cf213b6a66926e72df56c49fb11f68165c Mon Sep 17 00:00:00 2001 From: Hossein Shafagh Date: Tue, 10 Nov 2020 17:46:00 -0800 Subject: [PATCH 03/27] adding also response to upload acme token, just for future use-cases --- lemur/plugins/lemur_aws/plugin.py | 18 +++++++++--------- lemur/plugins/lemur_aws/tests/test_plugin.py | 9 +++++---- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/lemur/plugins/lemur_aws/plugin.py b/lemur/plugins/lemur_aws/plugin.py index 8fca73e9..fcc2e0cf 100644 --- a/lemur/plugins/lemur_aws/plugin.py +++ b/lemur/plugins/lemur_aws/plugin.py @@ -419,7 +419,7 @@ class S3DestinationPlugin(ExportDestinationPlugin): :param kwargs: :return: """ - current_app.logger.debug("S3 destination plugin is started for HTTP-01 challenge") + current_app.logger.debug("S3 destination plugin is started to upload HTTP-01 challenge") function = f"{__name__}.{sys._getframe().f_code.co_name}" @@ -431,16 +431,16 @@ class S3DestinationPlugin(ExportDestinationPlugin): if not prefix.endswith("/"): prefix + "/" - res = s3.put(bucket_name=bucket_name, - region_name=region, - prefix=prefix + filename, - data=token, - encrypt=False, - account_number=account_number) - res = "Success" if res else "Failure" + response = s3.put(bucket_name=bucket_name, + region_name=region, + prefix=prefix + filename, + data=token, + encrypt=False, + account_number=account_number) + res = "Success" if response else "Failure" log_data = { "function": function, - "message": "check if any valid certificate is revoked", + "message": "upload acme token challenge", "result": res, "bucket_name": bucket_name, "filename": filename diff --git a/lemur/plugins/lemur_aws/tests/test_plugin.py b/lemur/plugins/lemur_aws/tests/test_plugin.py index 89a318ca..e032cf02 100644 --- a/lemur/plugins/lemur_aws/tests/test_plugin.py +++ b/lemur/plugins/lemur_aws/tests/test_plugin.py @@ -68,10 +68,11 @@ def test_upload_acme_token(app): s3_client.create_bucket(Bucket=bucket) p = plugins.get("aws-s3") - p.upload_acme_token(token_path=token_path, - token_content=token_content, - token=token_content, - options=additional_options) + response = p.upload_acme_token(token_path=token_path, + token_content=token_content, + token=token_content, + options=additional_options) + assert response response = get(bucket_name=bucket, prefixed_object_name=prefix + token_name, From 1a65e09a9996b48471612383fa129c0279176ea9 Mon Sep 17 00:00:00 2001 From: Jasmine Schladen Date: Wed, 11 Nov 2020 15:21:40 -0800 Subject: [PATCH 04/27] Send a single email to multiple recipients instead of multiple emails --- lemur/notifications/messaging.py | 77 +++++++++---------- lemur/plugins/bases/notification.py | 10 +-- lemur/plugins/lemur_email/plugin.py | 8 +- lemur/plugins/lemur_email/tests/test_email.py | 23 ++++-- 4 files changed, 61 insertions(+), 57 deletions(-) diff --git a/lemur/notifications/messaging.py b/lemur/notifications/messaging.py index 75d227b1..4ba32b38 100644 --- a/lemur/notifications/messaging.py +++ b/lemur/notifications/messaging.py @@ -103,8 +103,9 @@ def send_plugin_notification(event_type, data, recipients, notification): function = f"{__name__}.{sys._getframe().f_code.co_name}" log_data = { "function": function, - "message": f"Sending expiration notification for to recipients {recipients}", - "notification_type": "expiration", + "message": f"Sending {event_type} notification for to recipients {recipients}", + "notification_type": event_type, + "notification_plugin": notification.plugin.slug, "certificate_targets": recipients, } status = FAILURE_METRIC_STATUS @@ -121,7 +122,7 @@ def send_plugin_notification(event_type, data, recipients, notification): "notification", "counter", 1, - metric_tags={"status": status, "event_type": event_type}, + metric_tags={"status": status, "event_type": event_type, "plugin": notification.plugin.slug}, ) if status == SUCCESS_METRIC_STATUS: @@ -142,7 +143,6 @@ def send_expiration_notifications(exclude): for notification_label, certificates in notification_group.items(): notification_data = [] - security_data = [] notification = certificates[0][0] @@ -152,33 +152,30 @@ def send_expiration_notifications(exclude): certificate ).data notification_data.append(cert_data) - security_data.append(cert_data) - if send_default_notification( - "expiration", notification_data, [owner], notification.options - ): - success += 1 + email_recipients = security_email + [owner] + if notification.plugin.slug == "email-notification": + email_recipients = notification.plugin.get_recipients(notification.options, email_recipients) + if send_plugin_notification( + "expiration", notification_data, email_recipients, notification + ): + success += len(email_recipients) + else: + failure += len(email_recipients) else: - failure += 1 + if send_default_notification( + "expiration", notification_data, email_recipients, notification.options + ): + success += len(email_recipients) + else: + failure += len(email_recipients) - recipients = notification.plugin.filter_recipients(notification.options, security_email + [owner]) - - if send_plugin_notification( - "expiration", - notification_data, - recipients, - notification, - ): - success += 1 - else: - failure += 1 - - if send_default_notification( - "expiration", security_data, security_email, notification.options - ): - success += 1 - else: - failure += 1 + if send_plugin_notification( + "expiration", notification_data, [], notification + ): + success += 1 + else: + failure += 1 return success, failure @@ -195,15 +192,16 @@ def send_default_notification(notification_type, data, targets, notification_opt :return: """ function = f"{__name__}.{sys._getframe().f_code.co_name}" - log_data = { - "function": function, - "message": f"Sending notification for certificate data {data}", - "notification_type": notification_type, - } status = FAILURE_METRIC_STATUS notification_plugin = plugins.get( current_app.config.get("LEMUR_DEFAULT_NOTIFICATION_PLUGIN", "email-notification") ) + log_data = { + "function": function, + "message": f"Sending {notification_type} notification for certificate data {data} to targets {targets}", + "notification_type": notification_type, + "notification_plugin": notification_plugin.slug, + } try: current_app.logger.debug(log_data) @@ -212,7 +210,7 @@ def send_default_notification(notification_type, data, targets, notification_opt status = SUCCESS_METRIC_STATUS except Exception as e: log_data["message"] = f"Unable to send {notification_type} notification for certificate data {data} " \ - f"to target {targets}" + f"to targets {targets}" current_app.logger.error(log_data, exc_info=True) sentry.captureException() @@ -220,7 +218,7 @@ def send_default_notification(notification_type, data, targets, notification_opt "notification", "counter", 1, - metric_tags={"status": status, "event_type": notification_type}, + metric_tags={"status": status, "event_type": notification_type, "plugin": notification_plugin.slug}, ) if status == SUCCESS_METRIC_STATUS: @@ -247,15 +245,14 @@ def send_pending_failure_notification( data = pending_certificate_output_schema.dump(pending_cert).data data["security_email"] = current_app.config.get("LEMUR_SECURITY_TEAM_EMAIL") - notify_owner_success = False + email_recipients = [] if notify_owner: - notify_owner_success = send_default_notification("failed", data, [data["owner"]], pending_cert) + email_recipients = email_recipients + [data["owner"]] - notify_security_success = False if notify_security: - notify_security_success = send_default_notification("failed", data, data["security_email"], pending_cert) + email_recipients = email_recipients + data["security_email"] - return notify_owner_success or notify_security_success + return send_default_notification("failed", data, email_recipients, pending_cert) def needs_notification(certificate): diff --git a/lemur/plugins/bases/notification.py b/lemur/plugins/bases/notification.py index 76aa33de..03de95ce 100644 --- a/lemur/plugins/bases/notification.py +++ b/lemur/plugins/bases/notification.py @@ -20,14 +20,14 @@ class NotificationPlugin(Plugin): def send(self, notification_type, message, targets, options, **kwargs): raise NotImplementedError - def filter_recipients(self, options, excluded_recipients): + def get_recipients(self, options, additional_recipients): """ - Given a set of options (which should include configured recipient info), filters out recipients that - we do NOT want to notify. + Given a set of options (which should include configured recipient info), returns the parsed list of recipients + from those options plus the additional recipients specified. The returned value has no duplicates. - For any notification types where recipients can't be dynamically modified, this returns an empty list. + For any notification types where recipients can't be dynamically modified, this returns only the additional recipients. """ - return [] + return additional_recipients class ExpirationNotificationPlugin(NotificationPlugin): diff --git a/lemur/plugins/lemur_email/plugin.py b/lemur/plugins/lemur_email/plugin.py index 041b27ec..214586ab 100644 --- a/lemur/plugins/lemur_email/plugin.py +++ b/lemur/plugins/lemur_email/plugin.py @@ -105,6 +105,8 @@ class EmailNotificationPlugin(ExpirationNotificationPlugin): @staticmethod def send(notification_type, message, targets, options, **kwargs): + if not targets: + return subject = "Lemur: {0} Notification".format(notification_type.capitalize()) @@ -119,11 +121,9 @@ class EmailNotificationPlugin(ExpirationNotificationPlugin): send_via_smtp(subject, body, targets) @staticmethod - def filter_recipients(options, excluded_recipients, **kwargs): + def get_recipients(options, additional_recipients, **kwargs): notification_recipients = get_plugin_option("recipients", options) if notification_recipients: notification_recipients = notification_recipients.split(",") - # removing owner and security_email from notification_recipient - notification_recipients = [i for i in notification_recipients if i not in excluded_recipients] - return notification_recipients + return list(set(notification_recipients + additional_recipients)) diff --git a/lemur/plugins/lemur_email/tests/test_email.py b/lemur/plugins/lemur_email/tests/test_email.py index fd4dc575..448c4f5c 100644 --- a/lemur/plugins/lemur_email/tests/test_email.py +++ b/lemur/plugins/lemur_email/tests/test_email.py @@ -54,7 +54,7 @@ def test_send_expiration_notification(): certificate.notifications[0].options = get_options() verify_sender_email() - assert send_expiration_notifications([]) == (3, 0) # owner, recipients (only counted as 1), and security + assert send_expiration_notifications([]) == (4, 0) # owner (1), recipients (2), and security (1) @mock_ses @@ -76,15 +76,22 @@ def test_send_pending_failure_notification(user, pending_certificate, async_issu verify_sender_email() assert send_pending_failure_notification(pending_certificate) + assert send_pending_failure_notification(pending_certificate, True, True) + assert send_pending_failure_notification(pending_certificate, True, False) + assert send_pending_failure_notification(pending_certificate, False, True) + assert send_pending_failure_notification(pending_certificate, False, False) def test_filter_recipients(certificate, endpoint): from lemur.plugins.lemur_email.plugin import EmailNotificationPlugin - options = [{"name": "recipients", "value": "security@example.com,bob@example.com,joe@example.com"}] - assert EmailNotificationPlugin.filter_recipients(options, []) == ["security@example.com", "bob@example.com", - "joe@example.com"] - assert EmailNotificationPlugin.filter_recipients(options, ["security@example.com"]) == ["bob@example.com", - "joe@example.com"] - assert EmailNotificationPlugin.filter_recipients(options, ["security@example.com", "bob@example.com", - "joe@example.com"]) == [] + options = [{"name": "recipients", "value": "security@example.com,joe@example.com"}] + assert sorted(EmailNotificationPlugin.get_recipients(options, [])) == sorted([ + "security@example.com", "joe@example.com"]) + assert sorted(EmailNotificationPlugin.get_recipients(options, ["security@example.com"])) == sorted([ + "security@example.com", "joe@example.com"]) + assert sorted(EmailNotificationPlugin.get_recipients(options, ["bob@example.com"])) == sorted([ + "security@example.com", "bob@example.com", "joe@example.com"]) + assert sorted(EmailNotificationPlugin.get_recipients(options, + ["security@example.com", "bob@example.com", "joe@example.com"])) == sorted([ + "security@example.com", "bob@example.com", "joe@example.com"]) From d4d51c702a8f835ef7963681d73dee3af6666b41 Mon Sep 17 00:00:00 2001 From: sirferl Date: Thu, 12 Nov 2020 13:51:08 +0100 Subject: [PATCH 05/27] Entrust: add organization handling --- lemur/plugins/lemur_entrust/plugin.py | 48 +++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/lemur/plugins/lemur_entrust/plugin.py b/lemur/plugins/lemur_entrust/plugin.py index 9b7848ed..5a6daf05 100644 --- a/lemur/plugins/lemur_entrust/plugin.py +++ b/lemur/plugins/lemur_entrust/plugin.py @@ -40,7 +40,7 @@ def determine_end_date(end_date): return end_date.format('YYYY-MM-DD') -def process_options(options): +def process_options(options, client_id): """ Processes and maps the incoming issuer options to fields/options that Entrust understands @@ -74,10 +74,36 @@ def process_options(options): "certType": product_type, "certExpiryDate": validity_end, # "keyType": "RSA", Entrust complaining about this parameter - "tracking": tracking_data + "tracking": tracking_data, + "org": options.get("organization"), + "clientId": client_id } return data +def get_client_id(my_response, organization): + """ + Helper function for parsing responses from the Entrust API. + :param content: + :return: :raise Exception: + """ + try: + d = json.loads(my_response.content) + except ValueError: + # catch an empty json object here + d = {'response': 'No detailed message'} + s = my_response.status_code + if s > 399: + raise Exception(f"ENTRUST error: {msg.get(s, s)}\n{d['errors']}") + + found = False + for y in d["organizations"]: + if y["name"] == organization: + found = True + client_id = y["clientId"] + if found: + return client_id + else: + raise Exception(f"Error on Organization - Use on of the List: {d['organizations']}") def handle_response(my_response): """ @@ -163,9 +189,25 @@ class EntrustIssuerPlugin(IssuerPlugin): } current_app.logger.info(log_data) + #firstly we need the organization ID + url = current_app.config.get("ENTRUST_URL") + "/organizations" + try: + response = self.session.get(url, timeout=(15, 40)) + except requests.exceptions.Timeout: + raise Exception("Timeout for Getting Organizations") + except requests.exceptions.RequestException as e: + raise Exception(f"Error for Getting Organization {e}") + + client_id = get_client_id(response, issuer_options.get("organization")) + log_data = { + "function": f"{__name__}.{sys._getframe().f_code.co_name}", + "message": f"Organization id: {client_id}" + } + current_app.logger.info(log_data) + url = current_app.config.get("ENTRUST_URL") + "/certificates" - data = process_options(issuer_options) + data = process_options(issuer_options, client_id) data["csr"] = csr try: From e1926f2f3cefd1adfae3d20a5055e3a98adf0243 Mon Sep 17 00:00:00 2001 From: sirferl Date: Thu, 12 Nov 2020 14:09:24 +0100 Subject: [PATCH 06/27] Entrust: add organization handling-linting --- lemur/plugins/lemur_entrust/plugin.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lemur/plugins/lemur_entrust/plugin.py b/lemur/plugins/lemur_entrust/plugin.py index 5a6daf05..16197836 100644 --- a/lemur/plugins/lemur_entrust/plugin.py +++ b/lemur/plugins/lemur_entrust/plugin.py @@ -105,6 +105,7 @@ def get_client_id(my_response, organization): else: raise Exception(f"Error on Organization - Use on of the List: {d['organizations']}") + def handle_response(my_response): """ Helper function for parsing responses from the Entrust API. @@ -189,7 +190,7 @@ class EntrustIssuerPlugin(IssuerPlugin): } current_app.logger.info(log_data) - #firstly we need the organization ID + # firstly we need the organization ID url = current_app.config.get("ENTRUST_URL") + "/organizations" try: response = self.session.get(url, timeout=(15, 40)) @@ -221,7 +222,7 @@ class EntrustIssuerPlugin(IssuerPlugin): external_id = response_dict['trackingId'] cert = response_dict['endEntityCert'] if len(response_dict['chainCerts']) < 2: - # certificate signed by CA directly, no ICA included ini the chain + # certificate signed by CA directly, no ICA included in the chain chain = None else: chain = response_dict['chainCerts'][1] From 8738c4d893da3d69e41e6df3a635bdea59ab2f2e Mon Sep 17 00:00:00 2001 From: sirferl Date: Thu, 12 Nov 2020 14:14:20 +0100 Subject: [PATCH 07/27] Entrust: add organization handling-linting --- lemur/plugins/lemur_entrust/plugin.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/lemur/plugins/lemur_entrust/plugin.py b/lemur/plugins/lemur_entrust/plugin.py index ab08f948..3e00a1f4 100644 --- a/lemur/plugins/lemur_entrust/plugin.py +++ b/lemur/plugins/lemur_entrust/plugin.py @@ -83,6 +83,7 @@ def process_options(options, client_id): } return data + def get_client_id(my_response, organization): """ Helper function for parsing responses from the Entrust API. @@ -94,19 +95,16 @@ def get_client_id(my_response, organization): except ValueError: # catch an empty json object here d = {'response': 'No detailed message'} - s = my_response.status_code - if s > 399: - raise Exception(f"ENTRUST error: {msg.get(s, s)}\n{d['errors']}") found = False for y in d["organizations"]: - if y["name"] == organization: - found = True - client_id = y["clientId"] + if y["name"] == organization: + found = True + client_id = y["clientId"] if found: - return client_id + return client_id else: - raise Exception(f"Error on Organization - Use on of the List: {d['organizations']}") + raise Exception(f"Error on Organization - Use on of the List: {d['organizations']}") def handle_response(my_response): From 50ffe6a29c34afae9633633065c1a15c68f4dcb6 Mon Sep 17 00:00:00 2001 From: sirferl Date: Thu, 12 Nov 2020 14:31:49 +0100 Subject: [PATCH 08/27] Entrust: add organization handling-test change --- lemur/plugins/lemur_entrust/tests/test_entrust.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lemur/plugins/lemur_entrust/tests/test_entrust.py b/lemur/plugins/lemur_entrust/tests/test_entrust.py index 354e204e..bcb2f50a 100644 --- a/lemur/plugins/lemur_entrust/tests/test_entrust.py +++ b/lemur/plugins/lemur_entrust/tests/test_entrust.py @@ -59,4 +59,5 @@ def test_process_options(mock_current_app, authority): } } - assert expected == plugin.process_options(options) + client_id = 1 + assert expected == plugin.process_options(options, client_id) From b191b32312d380543e37ce3b5340d58ceeb50437 Mon Sep 17 00:00:00 2001 From: sirferl Date: Fri, 13 Nov 2020 07:57:06 +0100 Subject: [PATCH 09/27] Entrust: add organization handling-error in script --- lemur/plugins/lemur_entrust/plugin.py | 4 +++- lemur/plugins/lemur_kubernetes/plugin.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lemur/plugins/lemur_entrust/plugin.py b/lemur/plugins/lemur_entrust/plugin.py index 3e00a1f4..924345eb 100644 --- a/lemur/plugins/lemur_entrust/plugin.py +++ b/lemur/plugins/lemur_entrust/plugin.py @@ -79,7 +79,9 @@ def process_options(options, client_id): "certType": product_type, "certExpiryDate": validity_end, # "keyType": "RSA", Entrust complaining about this parameter - "tracking": tracking_data + "tracking": tracking_data, + "org": options.get("organization"), + "clientId": client_id } return data diff --git a/lemur/plugins/lemur_kubernetes/plugin.py b/lemur/plugins/lemur_kubernetes/plugin.py index f7ff00f7..b8ea3d1b 100644 --- a/lemur/plugins/lemur_kubernetes/plugin.py +++ b/lemur/plugins/lemur_kubernetes/plugin.py @@ -96,7 +96,7 @@ def build_secret(secret_format, secret_name, body, private_key, cert_chain): if secret_format == "TLS": secret["type"] = "kubernetes.io/tls" secret["data"] = { - "tls.crt": base64encode(body), + "tls.crt": base64encode("%s\n%s" % (body, cert_chain)), "tls.key": base64encode(private_key), } if secret_format == "Certificate": From ff540069e29138434348408f1f418a030aebbb09 Mon Sep 17 00:00:00 2001 From: sirferl Date: Fri, 13 Nov 2020 08:08:54 +0100 Subject: [PATCH 10/27] Entrust: add organization handling-Update test --- lemur/plugins/lemur_entrust/tests/test_entrust.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lemur/plugins/lemur_entrust/tests/test_entrust.py b/lemur/plugins/lemur_entrust/tests/test_entrust.py index bcb2f50a..3fe75422 100644 --- a/lemur/plugins/lemur_entrust/tests/test_entrust.py +++ b/lemur/plugins/lemur_entrust/tests/test_entrust.py @@ -56,7 +56,9 @@ def test_process_options(mock_current_app, authority): "requesterName": mock_current_app.config.get("ENTRUST_NAME"), "requesterEmail": mock_current_app.config.get("ENTRUST_EMAIL"), "requesterPhone": mock_current_app.config.get("ENTRUST_PHONE") - } + }, + "org": "Example, Inc.", + "clientID": 1 } client_id = 1 From 75107bcd695552dad2f58a5da5798841803762fd Mon Sep 17 00:00:00 2001 From: sirferl Date: Fri, 13 Nov 2020 08:18:33 +0100 Subject: [PATCH 11/27] Entrust: add organization handling-Lint error --- lemur/plugins/lemur_entrust/tests/test_entrust.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lemur/plugins/lemur_entrust/tests/test_entrust.py b/lemur/plugins/lemur_entrust/tests/test_entrust.py index 3fe75422..f6835c96 100644 --- a/lemur/plugins/lemur_entrust/tests/test_entrust.py +++ b/lemur/plugins/lemur_entrust/tests/test_entrust.py @@ -57,7 +57,7 @@ def test_process_options(mock_current_app, authority): "requesterEmail": mock_current_app.config.get("ENTRUST_EMAIL"), "requesterPhone": mock_current_app.config.get("ENTRUST_PHONE") }, - "org": "Example, Inc.", + "org": "Example, Inc.", "clientID": 1 } From fc7db4a9b20d81ce1b6bf5245b0d0b871e86f46b Mon Sep 17 00:00:00 2001 From: Jasmine Schladen Date: Fri, 13 Nov 2020 13:13:37 -0800 Subject: [PATCH 12/27] Fix style --- lemur/plugins/lemur_email/tests/test_email.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/lemur/plugins/lemur_email/tests/test_email.py b/lemur/plugins/lemur_email/tests/test_email.py index 448c4f5c..3522f21c 100644 --- a/lemur/plugins/lemur_email/tests/test_email.py +++ b/lemur/plugins/lemur_email/tests/test_email.py @@ -21,7 +21,6 @@ def get_options(): def test_render_expiration(certificate, endpoint): - new_cert = CertificateFactory() new_cert.replaces.append(certificate) @@ -82,16 +81,14 @@ def test_send_pending_failure_notification(user, pending_certificate, async_issu assert send_pending_failure_notification(pending_certificate, False, False) -def test_filter_recipients(certificate, endpoint): +def test_get_recipients(certificate, endpoint): from lemur.plugins.lemur_email.plugin import EmailNotificationPlugin options = [{"name": "recipients", "value": "security@example.com,joe@example.com"}] - assert sorted(EmailNotificationPlugin.get_recipients(options, [])) == sorted([ - "security@example.com", "joe@example.com"]) - assert sorted(EmailNotificationPlugin.get_recipients(options, ["security@example.com"])) == sorted([ - "security@example.com", "joe@example.com"]) - assert sorted(EmailNotificationPlugin.get_recipients(options, ["bob@example.com"])) == sorted([ - "security@example.com", "bob@example.com", "joe@example.com"]) - assert sorted(EmailNotificationPlugin.get_recipients(options, - ["security@example.com", "bob@example.com", "joe@example.com"])) == sorted([ - "security@example.com", "bob@example.com", "joe@example.com"]) + two_emails = sorted(["security@example.com", "joe@example.com"]) + assert sorted(EmailNotificationPlugin.get_recipients(options, [])) == two_emails + assert sorted(EmailNotificationPlugin.get_recipients(options, ["security@example.com"])) == two_emails + three_emails = sorted(["security@example.com", "bob@example.com", "joe@example.com"]) + assert sorted(EmailNotificationPlugin.get_recipients(options, ["bob@example.com"])) == three_emails + assert sorted(EmailNotificationPlugin.get_recipients(options, ["security@example.com", "bob@example.com", + "joe@example.com"])) == three_emails From bb11ff9f60663d9e2d7b9434a4d7244463689d69 Mon Sep 17 00:00:00 2001 From: Jasmine Schladen Date: Fri, 13 Nov 2020 17:31:40 -0800 Subject: [PATCH 13/27] Remove python-ldap from requirements-docs.txt --- requirements-docs.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements-docs.txt b/requirements-docs.txt index 1fcf06ab..69c4710c 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -79,7 +79,6 @@ pyrfc3339==1.1 # via -r requirements.txt, acme python-dateutil==2.8.1 # via -r requirements.txt, alembic, arrow, botocore python-editor==1.0.4 # via -r requirements.txt, alembic python-json-logger==0.1.11 # via -r requirements.txt, logmatic-python -python-ldap==3.3.1 # via -r requirements.txt pytz==2019.3 # via -r requirements.txt, acme, babel, celery, flask-restful, pyrfc3339 pyyaml==5.3.1 # via -r requirements.txt, cloudflare raven[flask]==6.10.0 # via -r requirements.txt From 50483c01da63d9c65822e9681d4fc7d5b263067b Mon Sep 17 00:00:00 2001 From: Hossein Shafagh Date: Fri, 13 Nov 2020 17:37:01 -0800 Subject: [PATCH 14/27] preparing for release 0.8.0 --- CHANGELOG.rst | 81 ++++++++++++++++++++++++++++++++++++++++++++++ lemur/__about__.py | 2 +- 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index ea8d23b7..67b792f8 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,87 @@ Changelog ========= +0.8.0 - `2020-11-13` +~~~~~~~~~~~~~~ + +This release comes after more than two years and contains many interesting new features and improvements. +In addition to multiple new plugins, such as ACME-http01, ADCS, PowerDNS, UltraDNS, Entrust, SNS, many of Lemur's existing +flows have improved. + +In the future, we plan to do frequent releases. + + +Summary of notable changes: + +- AWS S3 plugin: added delete, get methods, and support for uploading/deleting acme tokens +- ACME plugin: + - revamp of the plugin + - support for http01 domain validation, via S3 and SFTP as destination for the acme token + - support for CNAME delegated domain validation + - store-acme-account-details +- PowerDNS plugin +- UltraDNS plugin +- ADCS plugin +- SNS plugin +- Entrust plugin +- Rotation: + - respecting keyType and extensions + - region-by-region rotation option + - default to auto-rotate when cert attached to endpoint + - default to 1y validity during rotation for multi-year browser-trusted certs +- Certificate: search_by_name, and important performance improvements +- UI + - reducing the EC curve options to the relevant ones + - edit option for notifications, destinations and sources + - showing 13 month validity as default + - option to hide certs expired since 3month + - faster Permalink (no search involved) + - commonName Auto Added as DNS in the UI + - improved search and cert lookup +- celery tasks instead of crone, for better logging and monitoring +- countless bugfixes + - group-lookup-fix-referral + - url_context_path + - duplicate notification + - digicert-time-bug-fix + - improved-csr-support + - fix-cryptography-intermediate-ca + - enhanced logging + - vault-k8s-auth + - cfssl-key-fix + - cert-sync-endpoint-find-by-hash + - nlb-naming-bug + - fix_vault_api_v2_append + - aid_openid_roles_provider_integration + - rewrite-java-keystore-use-pyjks + - vault_kv2 + + +To see the full list of changes, you can run + + $ git log --merges --first-parent master --pretty=format:"%h %<(10,trunc)%aN %C(white)%<(15)%ar%Creset %C(red bold)%<(15)%D%Creset %s" | grep -v "depend" + + +Special thanks to all who contributed to this release, notably: + +- `peschmae `_ +- `sirferl `_ +- `lukasmrtvy `_ +- `intgr `_ +- `kush-bavishi `_ +- `alwaysjolley `_ +- `jplana `_ +- `explody `_ +- `titouanc `_ +- `jramosf `_ + + +Upgrading +--------- + +.. note:: This release will need a migration change. Please follow the `documentation `_ to upgrade Lemur. + + 0.7 - `2018-05-07` ~~~~~~~~~~~~~~ diff --git a/lemur/__about__.py b/lemur/__about__.py index 766d3668..0926ef33 100644 --- a/lemur/__about__.py +++ b/lemur/__about__.py @@ -15,7 +15,7 @@ __title__ = "lemur" __summary__ = "Certificate management and orchestration service" __uri__ = "https://github.com/Netflix/lemur" -__version__ = "0.7.0" +__version__ = "0.8.0" __author__ = "The Lemur developers" __email__ = "security@netflix.com" From db11f0c1b7edf5cb7e901b0bea2328dd76e626ee Mon Sep 17 00:00:00 2001 From: Jasmine Schladen Date: Fri, 13 Nov 2020 20:10:21 -0800 Subject: [PATCH 15/27] Condense sending notifications --- lemur/notifications/messaging.py | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/lemur/notifications/messaging.py b/lemur/notifications/messaging.py index 4ba32b38..5f414b8c 100644 --- a/lemur/notifications/messaging.py +++ b/lemur/notifications/messaging.py @@ -153,29 +153,23 @@ def send_expiration_notifications(exclude): ).data notification_data.append(cert_data) - email_recipients = security_email + [owner] - if notification.plugin.slug == "email-notification": - email_recipients = notification.plugin.get_recipients(notification.options, email_recipients) - if send_plugin_notification( - "expiration", notification_data, email_recipients, notification - ): - success += len(email_recipients) - else: - failure += len(email_recipients) + email_recipients = notification.plugin.get_recipients(notification.options, security_email + [owner]) + # Plugin will ONLY use the provided recipients if it's email; any other notification plugin ignores them + if send_plugin_notification( + "expiration", notification_data, email_recipients, notification + ): + success += len(email_recipients) else: + failure += len(email_recipients) + # If we're using an email plugin, we're done; + # if not, we also need to send an email notification to the security team and owner + if notification.plugin.slug != "email-notification": if send_default_notification( "expiration", notification_data, email_recipients, notification.options ): - success += len(email_recipients) + success = 1 + len(email_recipients) else: - failure += len(email_recipients) - - if send_plugin_notification( - "expiration", notification_data, [], notification - ): - success += 1 - else: - failure += 1 + failure = 1 + len(email_recipients) return success, failure From 334367376f80781b3655eee67f438536ae5fec65 Mon Sep 17 00:00:00 2001 From: sirferl Date: Sat, 14 Nov 2020 11:50:25 +0100 Subject: [PATCH 16/27] Entrust: add organization handling-param error --- lemur/plugins/lemur_entrust/tests/test_entrust.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lemur/plugins/lemur_entrust/tests/test_entrust.py b/lemur/plugins/lemur_entrust/tests/test_entrust.py index f6835c96..2c501581 100644 --- a/lemur/plugins/lemur_entrust/tests/test_entrust.py +++ b/lemur/plugins/lemur_entrust/tests/test_entrust.py @@ -58,7 +58,7 @@ def test_process_options(mock_current_app, authority): "requesterPhone": mock_current_app.config.get("ENTRUST_PHONE") }, "org": "Example, Inc.", - "clientID": 1 + "clientId": 1 } client_id = 1 From 5f1978a4da9a3da210d39408bad8d1ee88c54f39 Mon Sep 17 00:00:00 2001 From: sirferl Date: Sat, 14 Nov 2020 12:00:59 +0100 Subject: [PATCH 17/27] Kubernetes: revert unintentionally change --- lemur/plugins/lemur_kubernetes/plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lemur/plugins/lemur_kubernetes/plugin.py b/lemur/plugins/lemur_kubernetes/plugin.py index b8ea3d1b..f7ff00f7 100644 --- a/lemur/plugins/lemur_kubernetes/plugin.py +++ b/lemur/plugins/lemur_kubernetes/plugin.py @@ -96,7 +96,7 @@ def build_secret(secret_format, secret_name, body, private_key, cert_chain): if secret_format == "TLS": secret["type"] = "kubernetes.io/tls" secret["data"] = { - "tls.crt": base64encode("%s\n%s" % (body, cert_chain)), + "tls.crt": base64encode(body), "tls.key": base64encode(private_key), } if secret_format == "Certificate": From 24e74ab8739d6c9f604076d7b40246753052af5b Mon Sep 17 00:00:00 2001 From: Hossein Shafagh Date: Mon, 16 Nov 2020 15:27:17 -0800 Subject: [PATCH 18/27] updating release steps --- docs/doing-a-release.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/doing-a-release.rst b/docs/doing-a-release.rst index 09848eb6..71268b10 100644 --- a/docs/doing-a-release.rst +++ b/docs/doing-a-release.rst @@ -11,18 +11,18 @@ software. * Update the version number in ``lemur/__about__.py``. * Set the release date in the :doc:`/changelog`. -* Do a commit indicating this. -* Send a pull request with this. +* Do a commit indicating this, and raise a pull request with this. * Wait for it to be merged. Performing the release ---------------------- The commit that merged the version number bump is now the official release -commit for this release. You will need to have ``gpg`` installed and a ``gpg`` -key in order to do a release. Once this has happened: +commit for this release. You need an `API key `_, +which requires permissions to maintain the Lemur `project `_. -* Run ``invoke release {version}``. + ``python3 -m pip install --user --upgrade twine`` + ``python3 -m twine upload --repository pypi dist/*`` The release should now be available on PyPI and a tag should be available in the repository. From e4f89c93b5978329b6e5d13bd5dbb20378cc0f66 Mon Sep 17 00:00:00 2001 From: Hossein Shafagh Date: Mon, 16 Nov 2020 16:31:50 -0800 Subject: [PATCH 19/27] updating the release docs --- docs/doing-a-release.rst | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/docs/doing-a-release.rst b/docs/doing-a-release.rst index 71268b10..747668fb 100644 --- a/docs/doing-a-release.rst +++ b/docs/doing-a-release.rst @@ -21,12 +21,37 @@ The commit that merged the version number bump is now the official release commit for this release. You need an `API key `_, which requires permissions to maintain the Lemur `project `_. +For creating the release, follow these steps (more details `here `_) + +* Make sure you have the latest versions of setuptools and wheel installed: + + ``python3 -m pip install --user --upgrade setuptools wheel`` + +* Now run this command from the same directory where setup.py is located: + + ``python3 setup.py sdist bdist_wheel`` + +* Once completed it should generate two files in the dist directory: + +.. code-block:: pycon + + $ ls dist/ + lemur-0.8.0-py2.py3-none-any.whl lemur-0.8.0.tar.gz + + +* In this step, the distribution will be uploaded. You’ll need to install Twine: + ``python3 -m pip install --user --upgrade twine`` + +* Once installed, run Twine to upload all of the archives under dist. Once installed, run Twine to upload all of the archives under dist: + ``python3 -m twine upload --repository pypi dist/*`` -The release should now be available on PyPI and a tag should be available in +The release should now be available on `PyPI Lemur `_ and a tag should be available in the repository. +Make sure to also make a github `release `_ which will pick up the latest version. + Verifying the release --------------------- From 9aaf507dd65083dd8e198470cefd9f4dac1704c5 Mon Sep 17 00:00:00 2001 From: Jasmine Schladen Date: Mon, 16 Nov 2020 17:36:59 -0800 Subject: [PATCH 20/27] Clarify comment --- lemur/notifications/messaging.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lemur/notifications/messaging.py b/lemur/notifications/messaging.py index 5f414b8c..2658e1a0 100644 --- a/lemur/notifications/messaging.py +++ b/lemur/notifications/messaging.py @@ -161,8 +161,10 @@ def send_expiration_notifications(exclude): success += len(email_recipients) else: failure += len(email_recipients) - # If we're using an email plugin, we're done; - # if not, we also need to send an email notification to the security team and owner + # If we're using an email plugin, we're done, + # since "security_email + [owner]" were added as email_recipients. + # If we're not using an email plugin, we also need to send an email to the security team and owner, + # since the plugin notification didn't send anything to them. if notification.plugin.slug != "email-notification": if send_default_notification( "expiration", notification_data, email_recipients, notification.options From c342fb894d94a88cde3ca7dd2efbf88cc9c687c6 Mon Sep 17 00:00:00 2001 From: Mathias Petermann Date: Mon, 23 Nov 2020 14:55:21 +0100 Subject: [PATCH 21/27] Add documentation for ACME http-01 challenge --- docs/production/index.rst | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/docs/production/index.rst b/docs/production/index.rst index c6f561ca..6b01e951 100644 --- a/docs/production/index.rst +++ b/docs/production/index.rst @@ -415,8 +415,8 @@ And the worker can be started with desired options such as the following:: supervisor or systemd configurations should be created for these in production environments as appropriate. -Add support for LetsEncrypt -=========================== +Add support for LetsEncrypt/ACME +================================ LetsEncrypt is a free, limited-feature certificate authority that offers publicly trusted certificates that are valid for 90 days. LetsEncrypt does not use organizational validation (OV), and instead relies on domain validation (DV). @@ -424,7 +424,10 @@ LetsEncrypt requires that we prove ownership of a domain before we're able to is time we want a certificate. The most common methods to prove ownership are HTTP validation and DNS validation. Lemur supports DNS validation -through the creation of DNS TXT records. +through the creation of DNS TXT records as well as HTTP validation, reusing the destination concept. + +ACME DNS Challenge +------------------ In a nutshell, when we send a certificate request to LetsEncrypt, they generate a random token and ask us to put that token in a DNS text record to prove ownership of a domain. If a certificate request has multiple domains, we must @@ -462,6 +465,24 @@ possible. To enable this functionality, periodically (or through Cron/Celery) ru This command will traverse all DNS providers, determine which zones they control, and upload this list of zones to Lemur's database (in the dns_providers table). Alternatively, you can manually input this data. +ACME HTTP Challenge +------------------- + +The flow for requesting a certificate using the HTTP challenge is not that different from the one described for the DNS +challenge. The only difference is, that instead of creating a DNS TXT record, a file is uploaded to a Webserver which +serves the file at `http:///.well-known/acme-challenge/` + +Currently the HTTP challenge also works without Celery, since it's done while creating the certificate, and doesn't +rely on celery to create the DNS record. This will change when we implement mix & match of acme challenge types. + +To create a HTTP compatible Authority, you first need to create a new destination that will be used to deploy the +challenge token. Visit `Admin` -> `Destination` and click `Create`. The path you provide for the destination needs to +be the exact path that is called when the ACME providers calls ``http:///.well-known/acme-challenge/`. The +token part will be added dynamically by the acme_upload. +Currently only the SFTP and S3 Bucket destination support the ACME HTTP challenge. + +Afterwards you can create a new certificate authority as described in the DNS challenge, but need to choose +`Acme HTTP-01` as the plugin type, and then the destination you created beforehand. LetsEncrypt: pinning to cross-signed ICA ---------------------------------------- From 72da149fde725486c5dd43b1d72d38be2ff07746 Mon Sep 17 00:00:00 2001 From: Mathias Petermann Date: Mon, 23 Nov 2020 15:32:01 +0100 Subject: [PATCH 22/27] Fix ACME revoke_certificate --- lemur/plugins/lemur_acme/acme_handlers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lemur/plugins/lemur_acme/acme_handlers.py b/lemur/plugins/lemur_acme/acme_handlers.py index c1ab5281..55e4a076 100644 --- a/lemur/plugins/lemur_acme/acme_handlers.py +++ b/lemur/plugins/lemur_acme/acme_handlers.py @@ -224,7 +224,7 @@ class AcmeHandler(object): def revoke_certificate(self, certificate): if not self.reuse_account(certificate.authority): raise InvalidConfiguration("There is no ACME account saved, unable to revoke the certificate.") - acme_client, _ = self.acme.setup_acme_client(certificate.authority) + acme_client, _ = self.setup_acme_client(certificate.authority) fullchain_com = jose.ComparableX509( OpenSSL.crypto.load_certificate( From 320e0e75133ea592b792564dda9d93879c32dd99 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 23 Nov 2020 20:10:15 +0000 Subject: [PATCH 23/27] Bump pre-commit from 2.8.2 to 2.9.0 Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 2.8.2 to 2.9.0. - [Release notes](https://github.com/pre-commit/pre-commit/releases) - [Changelog](https://github.com/pre-commit/pre-commit/blob/master/CHANGELOG.md) - [Commits](https://github.com/pre-commit/pre-commit/compare/v2.8.2...v2.9.0) Signed-off-by: dependabot-preview[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index e2eb7051..886f7187 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -24,7 +24,7 @@ keyring==21.2.0 # via twine mccabe==0.6.1 # via flake8 nodeenv==1.5.0 # via -r requirements-dev.in, pre-commit pkginfo==1.5.0.1 # via twine -pre-commit==2.8.2 # via -r requirements-dev.in +pre-commit==2.9.0 # via -r requirements-dev.in pycodestyle==2.6.0 # via flake8 pycparser==2.20 # via cffi pyflakes==2.2.0 # via flake8 From a0104dd026f524f27a75b4501cf61c63113d40ba Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 23 Nov 2020 20:19:34 +0000 Subject: [PATCH 24/27] Bump sphinx from 3.3.0 to 3.3.1 Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 3.3.0 to 3.3.1. - [Release notes](https://github.com/sphinx-doc/sphinx/releases) - [Changelog](https://github.com/sphinx-doc/sphinx/blob/3.x/CHANGES) - [Commits](https://github.com/sphinx-doc/sphinx/compare/v3.3.0...v3.3.1) Signed-off-by: dependabot-preview[bot] --- requirements-docs.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements-docs.txt b/requirements-docs.txt index 69c4710c..28cf467d 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -79,6 +79,7 @@ pyrfc3339==1.1 # via -r requirements.txt, acme python-dateutil==2.8.1 # via -r requirements.txt, alembic, arrow, botocore python-editor==1.0.4 # via -r requirements.txt, alembic python-json-logger==0.1.11 # via -r requirements.txt, logmatic-python +python-ldap==3.3.1 # via -r requirements.txt pytz==2019.3 # via -r requirements.txt, acme, babel, celery, flask-restful, pyrfc3339 pyyaml==5.3.1 # via -r requirements.txt, cloudflare raven[flask]==6.10.0 # via -r requirements.txt @@ -91,7 +92,7 @@ six==1.15.0 # via -r requirements.txt, acme, bcrypt, cryptography, snowballstemmer==2.0.0 # via sphinx soupsieve==2.0.1 # via -r requirements.txt, beautifulsoup4 sphinx-rtd-theme==0.5.0 # via -r requirements-docs.in -sphinx==3.3.0 # via -r requirements-docs.in, sphinx-rtd-theme, sphinxcontrib-httpdomain +sphinx==3.3.1 # via -r requirements-docs.in, sphinx-rtd-theme, sphinxcontrib-httpdomain sphinxcontrib-applehelp==1.0.2 # via sphinx sphinxcontrib-devhelp==1.0.2 # via sphinx sphinxcontrib-htmlhelp==1.0.3 # via sphinx From 378e34d3d8f0991d600dd24f50524922b372a93e Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 23 Nov 2020 20:29:06 +0000 Subject: [PATCH 25/27] Bump faker from 4.14.2 to 4.17.1 Bumps [faker](https://github.com/joke2k/faker) from 4.14.2 to 4.17.1. - [Release notes](https://github.com/joke2k/faker/releases) - [Changelog](https://github.com/joke2k/faker/blob/master/CHANGELOG.md) - [Commits](https://github.com/joke2k/faker/compare/v4.14.2...v4.17.1) Signed-off-by: dependabot-preview[bot] --- requirements-tests.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-tests.txt b/requirements-tests.txt index b82e2ac8..14549802 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -24,7 +24,7 @@ decorator==4.4.2 # via networkx docker==4.2.0 # via moto ecdsa==0.14.1 # via moto, python-jose, sshpubkeys factory-boy==3.1.0 # via -r requirements-tests.in -faker==4.14.2 # via -r requirements-tests.in, factory-boy +faker==4.17.1 # via -r requirements-tests.in, factory-boy fakeredis==1.4.4 # via -r requirements-tests.in flask==1.1.2 # via pytest-flask freezegun==1.0.0 # via -r requirements-tests.in From 1474a399b7dc657834feec2573c51f2394e19e51 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 23 Nov 2020 20:47:10 +0000 Subject: [PATCH 26/27] Bump requests from 2.24.0 to 2.25.0 Bumps [requests](https://github.com/psf/requests) from 2.24.0 to 2.25.0. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/master/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.24.0...v2.25.0) Signed-off-by: dependabot-preview[bot] --- requirements-dev.txt | 2 +- requirements-docs.txt | 2 +- requirements-tests.txt | 2 +- requirements.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 886f7187..adc8304b 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -32,7 +32,7 @@ pygments==2.6.1 # via readme-renderer pyyaml==5.3.1 # via -r requirements-dev.in, pre-commit readme-renderer==25.0 # via twine requests-toolbelt==0.9.1 # via twine -requests==2.24.0 # via requests-toolbelt, twine +requests==2.25.0 # via requests-toolbelt, twine rfc3986==1.4.0 # via twine secretstorage==3.1.2 # via keyring six==1.15.0 # via bleach, cryptography, readme-renderer, virtualenv diff --git a/requirements-docs.txt b/requirements-docs.txt index 28cf467d..97af2a9f 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -85,7 +85,7 @@ pyyaml==5.3.1 # via -r requirements.txt, cloudflare raven[flask]==6.10.0 # via -r requirements.txt redis==3.5.3 # via -r requirements.txt, celery requests-toolbelt==0.9.1 # via -r requirements.txt, acme -requests[security]==2.24.0 # via -r requirements.txt, acme, certsrv, cloudflare, hvac, requests-toolbelt, sphinx +requests[security]==2.25.0 # via -r requirements.txt, acme, certsrv, cloudflare, hvac, requests-toolbelt, sphinx retrying==1.3.3 # via -r requirements.txt s3transfer==0.3.3 # via -r requirements.txt, boto3 six==1.15.0 # via -r requirements.txt, acme, bcrypt, cryptography, flask-cors, flask-restful, hvac, josepy, jsonlines, packaging, pynacl, pyopenssl, python-dateutil, retrying, sphinxcontrib-httpdomain, sqlalchemy-utils diff --git a/requirements-tests.txt b/requirements-tests.txt index 14549802..1f89a36a 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -69,7 +69,7 @@ pyyaml==5.3.1 # via -r requirements-tests.in, bandit, cfn-lint, moto redis==3.5.3 # via fakeredis regex==2020.4.4 # via black requests-mock==1.8.0 # via -r requirements-tests.in -requests==2.24.0 # via docker, moto, requests-mock, responses +requests==2.25.0 # via docker, moto, requests-mock, responses responses==0.10.12 # via moto rsa==4.0 # via python-jose s3transfer==0.3.3 # via boto3 diff --git a/requirements.txt b/requirements.txt index d7b56f2b..09a2a9b8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -78,7 +78,7 @@ pyyaml==5.3.1 # via -r requirements.in, cloudflare raven[flask]==6.10.0 # via -r requirements.in redis==3.5.3 # via -r requirements.in, celery requests-toolbelt==0.9.1 # via acme -requests[security]==2.24.0 # via -r requirements.in, acme, certsrv, cloudflare, hvac, requests-toolbelt +requests[security]==2.25.0 # via -r requirements.in, acme, certsrv, cloudflare, hvac, requests-toolbelt retrying==1.3.3 # via -r requirements.in s3transfer==0.3.3 # via boto3 six==1.15.0 # via -r requirements.in, acme, bcrypt, cryptography, flask-cors, flask-restful, hvac, josepy, jsonlines, pynacl, pyopenssl, python-dateutil, retrying, sqlalchemy-utils From 1d247f3df4651becd01ebd92958d67f26b166d9c Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 23 Nov 2020 20:57:15 +0000 Subject: [PATCH 27/27] Bump boto3 from 1.16.14 to 1.16.23 Bumps [boto3](https://github.com/boto/boto3) from 1.16.14 to 1.16.23. - [Release notes](https://github.com/boto/boto3/releases) - [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst) - [Commits](https://github.com/boto/boto3/compare/1.16.14...1.16.23) Signed-off-by: dependabot-preview[bot] --- requirements-docs.txt | 4 ++-- requirements-tests.txt | 4 ++-- requirements.txt | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/requirements-docs.txt b/requirements-docs.txt index 97af2a9f..0642dce7 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -17,8 +17,8 @@ bcrypt==3.1.7 # via -r requirements.txt, flask-bcrypt, paramiko beautifulsoup4==4.9.1 # via -r requirements.txt, cloudflare billiard==3.6.3.0 # via -r requirements.txt, celery blinker==1.4 # via -r requirements.txt, flask-mail, flask-principal, raven -boto3==1.16.14 # via -r requirements.txt -botocore==1.19.14 # via -r requirements.txt, boto3, s3transfer +boto3==1.16.24 # via -r requirements.txt +botocore==1.19.24 # via -r requirements.txt, boto3, s3transfer celery[redis]==4.4.2 # via -r requirements.txt certifi==2020.11.8 # via -r requirements.txt, requests certsrv==2.1.1 # via -r requirements.txt diff --git a/requirements-tests.txt b/requirements-tests.txt index 1f89a36a..4fd96f95 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -10,9 +10,9 @@ aws-sam-translator==1.22.0 # via cfn-lint aws-xray-sdk==2.5.0 # via moto bandit==1.6.2 # via -r requirements-tests.in black==20.8b1 # via -r requirements-tests.in -boto3==1.16.14 # via aws-sam-translator, moto +boto3==1.16.24 # via aws-sam-translator, moto boto==2.49.0 # via moto -botocore==1.19.14 # via aws-xray-sdk, boto3, moto, s3transfer +botocore==1.19.24 # via aws-xray-sdk, boto3, moto, s3transfer certifi==2020.11.8 # via requests cffi==1.14.0 # via cryptography cfn-lint==0.29.5 # via moto diff --git a/requirements.txt b/requirements.txt index 09a2a9b8..e029b61c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,8 +15,8 @@ bcrypt==3.1.7 # via flask-bcrypt, paramiko beautifulsoup4==4.9.1 # via cloudflare billiard==3.6.3.0 # via celery blinker==1.4 # via flask-mail, flask-principal, raven -boto3==1.16.14 # via -r requirements.in -botocore==1.19.14 # via -r requirements.in, boto3, s3transfer +boto3==1.16.24 # via -r requirements.in +botocore==1.19.24 # via -r requirements.in, boto3, s3transfer celery[redis]==4.4.2 # via -r requirements.in certifi==2020.11.8 # via -r requirements.in, requests certsrv==2.1.1 # via -r requirements.in