diff options
author | Johan Lundberg <lundberg@sunet.se> | 2021-04-16 17:14:40 +0200 |
---|---|---|
committer | Johan Lundberg <lundberg@sunet.se> | 2021-04-16 17:14:40 +0200 |
commit | d201dc6802432b29c0362833a538b15281fca247 (patch) | |
tree | 45357e62eb5b6c93fae9fc0fbea8d0bec3a5b65f | |
parent | 4c550f5370862cb3ed3b02dad346ce2fff71aeb3 (diff) | |
download | pysaml2-d201dc6802432b29c0362833a538b15281fca247.tar.gz |
Bandaid for crash when friendlyName is not set in metadata
-rw-r--r-- | src/saml2/assertion.py | 7 | ||||
-rw-r--r-- | tests/entity_no_friendly_name_sp.xml | 93 | ||||
-rw-r--r-- | tests/test_37_entity_categories.py | 47 |
3 files changed, 143 insertions, 4 deletions
diff --git a/src/saml2/assertion.py b/src/saml2/assertion.py index c9ef1b31..d8bc12f9 100644 --- a/src/saml2/assertion.py +++ b/src/saml2/assertion.py @@ -454,7 +454,12 @@ class Policy(object): def post_entity_categories(maps, sp_entity_id=None, mds=None, required=None): restrictions = {} - required = [d['friendly_name'].lower() for d in (required or [])] + if required is not None: + _req = [] + for d in required: + local_name = get_local_name(acs=self.acs, attr=d['name'], name_format=d['name_format']) + _req.append(local_name.lower()) + required = _req if mds: ecs = mds.entity_categories(sp_entity_id) diff --git a/tests/entity_no_friendly_name_sp.xml b/tests/entity_no_friendly_name_sp.xml new file mode 100644 index 00000000..584494c2 --- /dev/null +++ b/tests/entity_no_friendly_name_sp.xml @@ -0,0 +1,93 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ns0:EntityDescriptor xmlns:ns0="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:ns1="http://www.w3.org/2000/09/xmldsig#" xmlns:mdrpi="urn:oasis:names:tc:SAML:metadata:rpi" entityID="https://no-friendly-name.example.edu/saml2/metadata/"> + <ns0:Extensions> + <mdrpi:RegistrationInfo registrationAuthority="http://geant.example.eu/" registrationInstant="2018-05-10T09:45:00Z" /> + <mdattr:EntityAttributes xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute"> + <saml:Attribute xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Name="http://macedir.org/entity-category" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> + <saml:AttributeValue>http://www.geant.net/uri/dataprotection-code-of-conduct/v1</saml:AttributeValue></saml:Attribute> + </mdattr:EntityAttributes></ns0:Extensions> + <ns0:SPSSODescriptor AuthnRequestsSigned="false" WantAssertionsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> + <ns0:KeyDescriptor use="encryption"> + <ns1:KeyInfo> + <ns1:X509Data> + <ns1:X509Certificate>MIIDvDCCAqQCCQDXVjecpE8ibTANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC +U0UxEjAQBgNVBAgMCVN0b2NraG9sbTESMBAGA1UEBwwJU3RvY2tob2xtMQ4wDAYD +VQQKDAVFRFVJRDEaMBgGA1UECwwRZWR1aWQuZXhhbXBsZS5jb20xGjAYBgNVBAMM +EWVkdWlkLmV4YW1wbGUuY29tMSAwHgYJKoZIhvcNAQkBFhFlZHVpZEBleGFtcGxl +LmNvbTAeFw0xMzA2MTIxMTU5NTdaFw0yMzA2MTAxMTU5NTdaMIGfMQswCQYDVQQG +EwJTRTESMBAGA1UECAwJU3RvY2tob2xtMRIwEAYDVQQHDAlTdG9ja2hvbG0xDjAM +BgNVBAoMBUVEVUlEMRowGAYDVQQLDBFlZHVpZC5leGFtcGxlLmNvbTEaMBgGA1UE +AwwRZWR1aWQuZXhhbXBsZS5jb20xIDAeBgkqhkiG9w0BCQEWEWVkdWlkQGV4YW1w +bGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwHzXvBlv+DN1 +0tV9z6M79RFKJEE1HoBpo/vuQzcIP8SZZNhzwQpYxTVTQ9ocagX1onfJn2ZjoWsi +p45tSMnwLM9a9+UETYAV8O/AUq3gNDp+Mu6sS3smNhdykVR4STscIiP/hWMkZbJ4 +4dmJ2ccT3H6VosXR/OIVTjyalanmvMpDb6ZkKqmuQCDvRMii/R0HhbYUCytToDiy +Bxw1tQG946g8pe5RhZxxzmxVwAGwOyDn1dwi+j4wH2eCDyLu8hLanPHNFNiy5hiN +5B40N24V5YixlksgdT0pF46DfkJRrOCsNWHWnMSN+Xvo1oXLRFXEnfsCB1cw0EAp +SMMGX4dhSwIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA8+faeCQVTadTrXpB8jzfE +MJq6+V4oajnWb0LJ5ZZcKSlQZ5sfYJ1385CaXGh60Tg4uhtwTOgpRi1R1cZMLTz9 +ST6WPF+2vDJv7dGPuglzyQLvA2fd6BLnyGV6kLUc2XNOyCmD/tWuMvKvW62j4Y3B +XZvRFZZdHNgay4Wgvs8D6wyozWpkWpawXkQ3LqbXO6GChYC4VLru+uJuMKvvKCd/ +I125dzkP2nf9zkGV0cil3oIVSBPBtSRTF/M+oZhkHTwoM6hhonRvdOLuvobKfZ2Q +wHyaxzYldWmVC5omkgZeAdCGpJ316GQF8Zwg/yDOUzm4cvGeIESf1Q6ZxBwI6zGE +</ns1:X509Certificate> + </ns1:X509Data> + </ns1:KeyInfo> + </ns0:KeyDescriptor> + <ns0:KeyDescriptor use="signing"> + <ns1:KeyInfo> + <ns1:X509Data> + <ns1:X509Certificate>MIIDvDCCAqQCCQDXVjecpE8ibTANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC +U0UxEjAQBgNVBAgMCVN0b2NraG9sbTESMBAGA1UEBwwJU3RvY2tob2xtMQ4wDAYD +VQQKDAVFRFVJRDEaMBgGA1UECwwRZWR1aWQuZXhhbXBsZS5jb20xGjAYBgNVBAMM +EWVkdWlkLmV4YW1wbGUuY29tMSAwHgYJKoZIhvcNAQkBFhFlZHVpZEBleGFtcGxl +LmNvbTAeFw0xMzA2MTIxMTU5NTdaFw0yMzA2MTAxMTU5NTdaMIGfMQswCQYDVQQG +EwJTRTESMBAGA1UECAwJU3RvY2tob2xtMRIwEAYDVQQHDAlTdG9ja2hvbG0xDjAM +BgNVBAoMBUVEVUlEMRowGAYDVQQLDBFlZHVpZC5leGFtcGxlLmNvbTEaMBgGA1UE +AwwRZWR1aWQuZXhhbXBsZS5jb20xIDAeBgkqhkiG9w0BCQEWEWVkdWlkQGV4YW1w +bGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwHzXvBlv+DN1 +0tV9z6M79RFKJEE1HoBpo/vuQzcIP8SZZNhzwQpYxTVTQ9ocagX1onfJn2ZjoWsi +p45tSMnwLM9a9+UETYAV8O/AUq3gNDp+Mu6sS3smNhdykVR4STscIiP/hWMkZbJ4 +4dmJ2ccT3H6VosXR/OIVTjyalanmvMpDb6ZkKqmuQCDvRMii/R0HhbYUCytToDiy +Bxw1tQG946g8pe5RhZxxzmxVwAGwOyDn1dwi+j4wH2eCDyLu8hLanPHNFNiy5hiN +5B40N24V5YixlksgdT0pF46DfkJRrOCsNWHWnMSN+Xvo1oXLRFXEnfsCB1cw0EAp +SMMGX4dhSwIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA8+faeCQVTadTrXpB8jzfE +MJq6+V4oajnWb0LJ5ZZcKSlQZ5sfYJ1385CaXGh60Tg4uhtwTOgpRi1R1cZMLTz9 +ST6WPF+2vDJv7dGPuglzyQLvA2fd6BLnyGV6kLUc2XNOyCmD/tWuMvKvW62j4Y3B +XZvRFZZdHNgay4Wgvs8D6wyozWpkWpawXkQ3LqbXO6GChYC4VLru+uJuMKvvKCd/ +I125dzkP2nf9zkGV0cil3oIVSBPBtSRTF/M+oZhkHTwoM6hhonRvdOLuvobKfZ2Q +wHyaxzYldWmVC5omkgZeAdCGpJ316GQF8Zwg/yDOUzm4cvGeIESf1Q6ZxBwI6zGE +</ns1:X509Certificate> + </ns1:X509Data> + </ns1:KeyInfo> + </ns0:KeyDescriptor> + <ns0:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://no-friendly-name.example.edu/saml2/ls/"/> + <ns0:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://no-friendly-name.example.edu/saml2/acs/" index="1"/> + <!-- Require eduPersonTargetedID --> + <ns0:AttributeConsumingService index="0"> + <ns0:ServiceName xml:lang="en">no-friendlyName-SP</ns0:ServiceName> + <ns0:ServiceDescription xml:lang="en">No friendlyName SP</ns0:ServiceDescription> + <ns0:RequestedAttribute Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true" /> + </ns0:AttributeConsumingService> + </ns0:SPSSODescriptor> + <ns0:Organization> + <ns0:OrganizationName xml:lang="es">Example CO</ns0:OrganizationName> + <ns0:OrganizationName xml:lang="en">Example CO</ns0:OrganizationName> + <ns0:OrganizationDisplayName xml:lang="es">Example</ns0:OrganizationDisplayName> + <ns0:OrganizationDisplayName xml:lang="en">Example</ns0:OrganizationDisplayName> + <ns0:OrganizationURL xml:lang="es">http://www.example.edu</ns0:OrganizationURL> + <ns0:OrganizationURL xml:lang="en">http://www.example.com</ns0:OrganizationURL> + </ns0:Organization> + <ns0:ContactPerson contactType="technical"> + <ns0:Company>Example CO</ns0:Company> + <ns0:GivenName>Sysadmin</ns0:GivenName> + <ns0:SurName/> + <ns0:EmailAddress>sysadmin@example.com</ns0:EmailAddress> + </ns0:ContactPerson> + <ns0:ContactPerson contactType="administrative"> + <ns0:Company>Example CO</ns0:Company> + <ns0:GivenName>Admin</ns0:GivenName> + <ns0:SurName>CEO</ns0:SurName> + <ns0:EmailAddress>admin@example.com</ns0:EmailAddress> + </ns0:ContactPerson> +</ns0:EntityDescriptor> diff --git a/tests/test_37_entity_categories.py b/tests/test_37_entity_categories.py index 4ede68d6..ce6fa295 100644 --- a/tests/test_37_entity_categories.py +++ b/tests/test_37_entity_categories.py @@ -1,13 +1,16 @@ from contextlib import closing -from saml2 import sigver + +from pathutils import full_path from saml2 import config +from saml2 import sigver from saml2.assertion import Policy from saml2.attribute_converter import ac_factory -from pathutils import full_path +from saml2.extension import mdattr +from saml2.mdie import to_dict from saml2.mdstore import MetadataStore +from saml2.saml import Attribute, NAME_FORMAT_URI from saml2.server import Server - ATTRCONV = ac_factory(full_path("attributemaps")) sec_config = config.Config() sec_config.xmlsec_binary = sigver.get_xmlsec_binary(["/opt/local/bin"]) @@ -228,3 +231,41 @@ def test_entity_category_import_from_path(): "sn" ] ) + + +def test_filter_ava_required_attributes_with_no_friendly_name(): + mds = MetadataStore(ATTRCONV, sec_config, disable_ssl_certificate_validation=True) + mds.imp( + [ + { + "class": "saml2.mdstore.MetaDataFile", + "metadata": [(full_path("entity_no_friendly_name_sp.xml"),)] + } + ] + ) + + policy_conf = { + "default": { + "lifetime": {"minutes": 15}, + "entity_categories": ["swamid"] + } + } + + policy = Policy(policy_conf, mds) + + ava = { + "givenName": ["Derek"], + "sn": ["Jeter"], + "mail": ["derek@nyy.mlb.com"], + "c": ["USA"], + "eduPersonTargetedID": "foo!bar!xyz", + "norEduPersonNIN": "19800101134" + } + + # Require attribute eduPersonTargetedID but leave out friendlyName in attribute creation + edu_person_targeted_id_oid = 'urn:oid:1.3.6.1.4.1.5923.1.1.1.10' + edu_person_targeted_id = to_dict( + Attribute(name=edu_person_targeted_id_oid, + name_format=NAME_FORMAT_URI), onts=[mdattr]) + ava = policy.filter(ava, "https://no-friendly-name.example.edu/saml2/metadata/", required=[edu_person_targeted_id]) + assert _eq(list(ava.keys()), ["eduPersonTargetedID"]) |