Commit 6b9b3488 by Jesse Shapiro Committed by GitHub

Merge pull request #13537 from open-craft/haikuginger/adjust-saml-expiration-type

[ENT-23] Convert SAML cache expiration to timezone-aware datetime.datetime
parents 4360c50d 45bca67f
...@@ -6,6 +6,7 @@ Code to manage fetching and storing the metadata of IdPs. ...@@ -6,6 +6,7 @@ Code to manage fetching and storing the metadata of IdPs.
from celery.task import task from celery.task import task
import datetime import datetime
import dateutil.parser import dateutil.parser
import pytz
import logging import logging
from lxml import etree from lxml import etree
import requests import requests
...@@ -106,6 +107,7 @@ def _parse_metadata_xml(xml, entity_id): ...@@ -106,6 +107,7 @@ def _parse_metadata_xml(xml, entity_id):
expires_at = dateutil.parser.parse(xml.attrib["validUntil"]) expires_at = dateutil.parser.parse(xml.attrib["validUntil"])
if "cacheDuration" in xml.attrib: if "cacheDuration" in xml.attrib:
cache_expires = OneLogin_Saml2_Utils.parse_duration(xml.attrib["cacheDuration"]) cache_expires = OneLogin_Saml2_Utils.parse_duration(xml.attrib["cacheDuration"])
cache_expires = datetime.datetime.fromtimestamp(cache_expires, tz=pytz.utc)
if expires_at is None or cache_expires < expires_at: if expires_at is None or cache_expires < expires_at:
expires_at = cache_expires expires_at = cache_expires
......
...@@ -16,6 +16,7 @@ from .base import IntegrationTestMixin ...@@ -16,6 +16,7 @@ from .base import IntegrationTestMixin
TESTSHIB_ENTITY_ID = 'https://idp.testshib.org/idp/shibboleth' TESTSHIB_ENTITY_ID = 'https://idp.testshib.org/idp/shibboleth'
TESTSHIB_METADATA_URL = 'https://mock.testshib.org/metadata/testshib-providers.xml' TESTSHIB_METADATA_URL = 'https://mock.testshib.org/metadata/testshib-providers.xml'
TESTSHIB_METADATA_URL_WITH_CACHE_DURATION = 'https://mock.testshib.org/metadata/testshib-providers-cache.xml'
TESTSHIB_SSO_URL = 'https://idp.testshib.org/idp/profile/SAML2/Redirect/SSO' TESTSHIB_SSO_URL = 'https://idp.testshib.org/idp/profile/SAML2/Redirect/SSO'
...@@ -47,7 +48,19 @@ class TestShibIntegrationTest(IntegrationTestMixin, testutil.SAMLTestCase): ...@@ -47,7 +48,19 @@ class TestShibIntegrationTest(IntegrationTestMixin, testutil.SAMLTestCase):
def metadata_callback(_request, _uri, headers): def metadata_callback(_request, _uri, headers):
""" Return a cached copy of TestShib's metadata by reading it from disk """ """ Return a cached copy of TestShib's metadata by reading it from disk """
return (200, headers, self.read_data_file('testshib_metadata.xml')) return (200, headers, self.read_data_file('testshib_metadata.xml'))
httpretty.register_uri(httpretty.GET, TESTSHIB_METADATA_URL, content_type='text/xml', body=metadata_callback) httpretty.register_uri(httpretty.GET, TESTSHIB_METADATA_URL, content_type='text/xml', body=metadata_callback)
def cache_duration_metadata_callback(_request, _uri, headers):
"""Return a cached copy of TestShib's metadata with a cacheDuration attribute"""
return (200, headers, self.read_data_file('testshib_metadata_with_cache_duration.xml'))
httpretty.register_uri(
httpretty.GET,
TESTSHIB_METADATA_URL_WITH_CACHE_DURATION,
content_type='text/xml',
body=cache_duration_metadata_callback
)
self.addCleanup(httpretty.disable) self.addCleanup(httpretty.disable)
self.addCleanup(httpretty.reset) self.addCleanup(httpretty.reset)
...@@ -123,6 +136,24 @@ class TestShibIntegrationTest(IntegrationTestMixin, testutil.SAMLTestCase): ...@@ -123,6 +136,24 @@ class TestShibIntegrationTest(IntegrationTestMixin, testutil.SAMLTestCase):
else: else:
self.assertFalse(mock_log.called) self.assertFalse(mock_log.called)
def test_configure_testshib_provider_with_cache_duration(self):
""" Enable and configure the TestShib SAML IdP as a third_party_auth provider """
kwargs = {}
kwargs.setdefault('name', self.PROVIDER_NAME)
kwargs.setdefault('enabled', True)
kwargs.setdefault('visible', True)
kwargs.setdefault('idp_slug', self.PROVIDER_IDP_SLUG)
kwargs.setdefault('entity_id', TESTSHIB_ENTITY_ID)
kwargs.setdefault('metadata_source', TESTSHIB_METADATA_URL_WITH_CACHE_DURATION)
kwargs.setdefault('icon_class', 'fa-university')
kwargs.setdefault('attr_email', 'urn:oid:1.3.6.1.4.1.5923.1.1.1.6') # eduPersonPrincipalName
self.configure_saml_provider(**kwargs)
self.assertTrue(httpretty.is_enabled())
num_changed, num_failed, num_total = fetch_saml_metadata()
self.assertEqual(num_failed, 0)
self.assertEqual(num_changed, 1)
self.assertEqual(num_total, 1)
def _freeze_time(self, timestamp): def _freeze_time(self, timestamp):
""" Mock the current time for SAML, so we can replay canned requests/responses """ """ Mock the current time for SAML, so we can replay canned requests/responses """
now_patch = patch('onelogin.saml2.utils.OneLogin_Saml2_Utils.now', return_value=timestamp) now_patch = patch('onelogin.saml2.utils.OneLogin_Saml2_Utils.now', return_value=timestamp)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment