From 77270a6a21c865bb2ced375c3ebd8e3c8f9bc8bb Mon Sep 17 00:00:00 2001 From: Alexander J Sheehan Date: Tue, 5 Dec 2023 23:00:01 +0000 Subject: [PATCH] feat: adding timeouts to sso orchestrator configurations and api cleanup --- CHANGELOG.rst | 4 ++++ enterprise/__init__.py | 2 +- .../enterprise_customer_sso_configuration.py | 13 +++++----- enterprise/models.py | 24 ++++++++++++++----- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 5ad7c28a64..1f0bbddebe 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -15,6 +15,10 @@ Change Log Unreleased ---------- +[4.8.9] +------- +feat: adding timeouts to sso orchestrator configurations and api cleanup + [4.8.8] -------- fix: added more logs and handled edge cases in Degreed assign skills job diff --git a/enterprise/__init__.py b/enterprise/__init__.py index 0d14033546..49f6ee888a 100644 --- a/enterprise/__init__.py +++ b/enterprise/__init__.py @@ -2,4 +2,4 @@ Your project description goes here. """ -__version__ = "4.8.8" +__version__ = "4.8.9" diff --git a/enterprise/api/v1/views/enterprise_customer_sso_configuration.py b/enterprise/api/v1/views/enterprise_customer_sso_configuration.py index f123e136e9..49c03e9ae8 100644 --- a/enterprise/api/v1/views/enterprise_customer_sso_configuration.py +++ b/enterprise/api/v1/views/enterprise_customer_sso_configuration.py @@ -37,6 +37,7 @@ BAD_CUSTOMER_ERROR = 'Must provide valid enterprise customer' CONFIG_UPDATE_ERROR = 'Error updating SSO configuration record' CONFIG_CREATE_ERROR = 'Error creating SSO configuration record' +BAD_IDP_METADATA_URL = 'Must provide valid IDP metadata url' class EnterpriseCustomerInactiveException(Exception): @@ -243,9 +244,9 @@ def create(self, request, *args, **kwargs): # If the metadata url has changed, we need to update the metadata xml try: sso_config_metadata_xml = get_metadata_xml_from_url(request_metadata_url) - except SsoConfigurationApiError as e: - LOGGER.error(f'{CONFIG_UPDATE_ERROR}{e}') - return Response({'error': f'{CONFIG_UPDATE_ERROR} {e}'}, status=HTTP_400_BAD_REQUEST) + except (SsoConfigurationApiError, requests.exceptions.SSLError) as e: + LOGGER.error(f'{BAD_IDP_METADATA_URL}{e}') + return Response({'error': f'{BAD_IDP_METADATA_URL} {e}'}, status=HTTP_400_BAD_REQUEST) request_data['metadata_xml'] = sso_config_metadata_xml if sso_config_metadata_xml or (sso_config_metadata_xml := request_data.get('metadata_xml')): try: @@ -292,9 +293,9 @@ def update(self, request, *args, **kwargs): # If the metadata url has changed, we need to update the metadata xml try: sso_config_metadata_xml = get_metadata_xml_from_url(request_metadata_url) - except SsoConfigurationApiError as e: - LOGGER.error(f'{CONFIG_UPDATE_ERROR} {e}') - return Response({'error': f'{CONFIG_UPDATE_ERROR} {e}'}, status=HTTP_400_BAD_REQUEST) + except (SsoConfigurationApiError, requests.exceptions.SSLError) as e: + LOGGER.error(f'{BAD_IDP_METADATA_URL}{e}') + return Response({'error': f'{BAD_IDP_METADATA_URL} {e}'}, status=HTTP_400_BAD_REQUEST) request_data['metadata_xml'] = sso_config_metadata_xml if request_metadata_xml := request_data.get('metadata_xml'): if request_metadata_xml != sso_configuration_record.first().metadata_xml: diff --git a/enterprise/models.py b/enterprise/models.py index 2d2378fb2a..4ad711cee8 100644 --- a/enterprise/models.py +++ b/enterprise/models.py @@ -3,6 +3,7 @@ """ import collections +import datetime import itertools import json from decimal import Decimal @@ -4066,12 +4067,23 @@ def is_pending_configuration(self): Returns True if the configuration has been submitted but not completed configuration. """ if self.submitted_at: - if not self.configured_at: - return True - if self.errored_at and self.errored_at > self.submitted_at: - return False - if self.submitted_at > self.configured_at: - return True + # The configuration times out after 12 hours. If the configuration has not been submitted in the last 12 + # hours then it can be considered unblocked. + sso_config_timeout_hours = getattr(settings, "ENTERPRISE_SSO_ORCHESTRATOR_TIMEOUT_HOURS", 1) + sso_config_timeout_minutes = getattr(settings, "ENTERPRISE_SSO_ORCHESTRATOR_TIMEOUT_MINUTES", 0) + timeout_timedelta = datetime.timedelta(hours=sso_config_timeout_hours, minutes=sso_config_timeout_minutes) + if (self.submitted_at + timeout_timedelta) > localized_utcnow(): + # if we have received an error from the orchestrator after submitting the configuration, it is + # unblocked + if self.errored_at and self.errored_at > self.submitted_at: + return False + # If we have not gotten a response from the orchestrator, it is still configuring + if not self.configured_at: + return True + # If we have gotten a response from the orchestrator, but it's before the submission time, it is still + # configuring + if self.submitted_at > self.configured_at: + return True return False def submit_for_configuration(self, updating_existing_record=False):