From 1363226697c24105347e38d015fbf4c6723229eb Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Fri, 13 May 2022 17:40:18 +0200 Subject: [PATCH] providers/saml: make SAML metadata generation consistent Signed-off-by: Jens Langhammer --- .../providers/saml/processors/metadata.py | 4 ++-- .../providers/saml/tests/test_metadata.py | 23 +++++++++++++++++-- authentik/sources/saml/tests/test_metadata.py | 13 +++++++++++ 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/authentik/providers/saml/processors/metadata.py b/authentik/providers/saml/processors/metadata.py index 653299a57..ef5afc0f9 100644 --- a/authentik/providers/saml/processors/metadata.py +++ b/authentik/providers/saml/processors/metadata.py @@ -1,4 +1,5 @@ """SAML Identity Provider Metadata Processor""" +from hashlib import sha256 from typing import Iterator, Optional import xmlsec # nosec @@ -7,7 +8,6 @@ from django.urls import reverse from lxml.etree import Element, SubElement, tostring # nosec from authentik.providers.saml.models import SAMLProvider -from authentik.providers.saml.utils import get_random_id from authentik.providers.saml.utils.encoding import strip_pem_header from authentik.sources.saml.processors.constants import ( DIGEST_ALGORITHM_TRANSLATION_MAP, @@ -35,7 +35,7 @@ class MetadataProcessor: self.provider = provider self.http_request = request self.force_binding = None - self.xml_id = get_random_id() + self.xml_id = sha256(f"{provider.name}-{provider.pk}".encode("ascii")).hexdigest() def get_signing_key_descriptor(self) -> Optional[Element]: """Get Signing KeyDescriptor, if enabled for the provider""" diff --git a/authentik/providers/saml/tests/test_metadata.py b/authentik/providers/saml/tests/test_metadata.py index 6f6531de6..b7cf21536 100644 --- a/authentik/providers/saml/tests/test_metadata.py +++ b/authentik/providers/saml/tests/test_metadata.py @@ -1,10 +1,12 @@ """Test Service-Provider Metadata Parser""" # flake8: noqa -from django.test import TestCase +from django.test import RequestFactory, TestCase +from authentik.core.models import Application from authentik.core.tests.utils import create_test_cert, create_test_flow -from authentik.providers.saml.models import SAMLBindings, SAMLPropertyMapping +from authentik.providers.saml.models import SAMLBindings, SAMLPropertyMapping, SAMLProvider +from authentik.providers.saml.processors.metadata import MetadataProcessor from authentik.providers.saml.processors.metadata_parser import ServiceProviderMetadataParser METADATA_SIMPLE = """ @@ -66,6 +68,23 @@ class TestServiceProviderMetadataParser(TestCase): def setUp(self) -> None: self.flow = create_test_flow() + self.factory = RequestFactory() + + def test_consistent(self): + """Test that metadata generation is consistent""" + provider = SAMLProvider.objects.create( + name="test", + authorization_flow=self.flow, + ) + Application.objects.create( + name="test", + slug="test", + provider=provider, + ) + request = self.factory.get("/") + metadata_a = MetadataProcessor(provider, request).build_entity_descriptor() + metadata_b = MetadataProcessor(provider, request).build_entity_descriptor() + self.assertEqual(metadata_a, metadata_b) def test_simple(self): """Test simple metadata without Signing""" diff --git a/authentik/sources/saml/tests/test_metadata.py b/authentik/sources/saml/tests/test_metadata.py index 0ad74df89..1f2034f40 100644 --- a/authentik/sources/saml/tests/test_metadata.py +++ b/authentik/sources/saml/tests/test_metadata.py @@ -29,6 +29,19 @@ class TestMetadataProcessor(TestCase): schema = etree.XMLSchema(etree.parse("xml/saml-schema-metadata-2.0.xsd")) # nosec self.assertTrue(schema.validate(metadata)) + def test_metadata_consistent(self): + """Test Metadata generation being consistent (xml stays the same)""" + source = SAMLSource.objects.create( + slug="provider", + issuer="authentik", + signing_kp=create_test_cert(), + pre_authentication_flow=create_test_flow(), + ) + request = self.factory.get("/") + xml_a = MetadataProcessor(source, request).build_entity_descriptor() + xml_b = MetadataProcessor(source, request).build_entity_descriptor() + self.assertEqual(xml_a, xml_b) + def test_metadata(self): """Test Metadata generation being valid""" source = SAMLSource.objects.create(