diff --git a/src/open_inwoner/configurations/tests/bootstrap/files/digid-metadata.xml b/src/open_inwoner/configurations/tests/bootstrap/files/digid-metadata.xml new file mode 100644 index 0000000000..728d152fde --- /dev/null +++ b/src/open_inwoner/configurations/tests/bootstrap/files/digid-metadata.xml @@ -0,0 +1,82 @@ + +NoOIwQlJT+i8sPfoZAqpxlGTh7hqWVGeVHcu9vhQ+xA=ixScWp/yrGs4LRQHqnF9Zr/Jn1MOIS5TwiWwiUc3d5sv+jMbVFGSw4fHE0Yu6yp5kOajK3wCY8TbfcIb++na5XWlHDfMD3MhiNBTdr2vIw6tdqetSCng02r5BQN1wug1qH1RY8FRH39X0opOVbs/V9HsCoquRvVRxjidz9L5Q3PNx/VPGHWkW4iclJKsJT4UPqTR6ZQww3Krd7XzUA3pnTx97WxJegfwmg70H/WQiasV1eI4tWm3PFHhhS2TuVshxoWxa2Qzz6HHYsOX+jWVnL9M3YF/RXuoMdt3cOtde7/EX6Cw2r50hAODnClQgRoxuPMBhdTXAyq6NirmPR9dKg==7593b799e735055fcd479caa35d44d455576cefc7593b799e735055fcd479caa35d44d455576cefcMIIG+zCCBOOgAwIBAgIUJmQio80TiqOX3LMrbzeG1dh0ngEwDQYJKoZIhvcN +AQELBQAwgYAxCzAJBgNVBAYTAk5MMSAwHgYDVQQKDBdRdW9WYWRpcyBUcnVz +dGxpbmsgQi5WLjEXMBUGA1UEYQwOTlRSTkwtMzAyMzc0NTkxNjA0BgNVBAMM +LVF1b1ZhZGlzIFBLSW92ZXJoZWlkIFByaXZhdGUgU2VydmljZXMgQ0EgLSBH +MTAeFw0yMzA5MjExOTEyNTlaFw0yNjA5MjExOTA3MDBaMF4xCzAJBgNVBAYT +Ak5MMQ8wDQYDVQQKDAZMb2dpdXMxHTAbBgNVBAUTFDAwMDAwMDA0MTY2OTA5 +OTEzMDAwMR8wHQYDVQQDDBZzYW1sLXNpZ24ucHAxLmRpZ2lkLm5sMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5r8GtcRfX3UN3f7I8Iobhy/N +U0Y+MV6DEXTmDRvRDZjwjr6ammB/cd1fsDz7D5CU+eax205aDRH69mMZk11x +cIKDjISvtBFLQVxwWXgTGpUSBogFHfp70/yfvcC7vq8gE7zjRN9gNzZCC0Ak +D7ZwAfFBbwI9nBSiMby9MY41MjS/W10uik1I6s5Ok2u/WfUe6FjcnaoU1O7O +tpJGAkW/yDC5HWypqeTG1fSPee/0GjvU8FH+Bu73fAFHa86KSO15eaCUR6Ea +7qCjpLsfPizweP9Adehlal1blfxsfJdFunq/jnO8NhYnQ7DC0aBd6ET8Wo/O +1ZacGsYmJWq9dqeleQIDAQABo4ICjDCCAogwHwYDVR0jBBgwFoAUuWymE7q7 +LzRjgzEu+X5JHd8A9WMwfQYIKwYBBQUHAQEEcTBvMD4GCCsGAQUFBzAChjJo +dHRwOi8vdHJ1c3QucXVvdmFkaXNnbG9iYWwuY29tL3BraW9wcml2c2Vydmcx +LmNydDAtBggrBgEFBQcwAYYhaHR0cDovL3NsLm9jc3AucXVvdmFkaXNnbG9i +YWwuY29tMCEGA1UdEQQaMBiCFnNhbWwtc2lnbi5wcDEuZGlnaWQubmwwggEw +BgNVHSAEggEnMIIBIzCCAR8GCmCEEAGHawECCAYwggEPMDQGCCsGAQUFBwIB +FihodHRwOi8vd3d3LnF1b3ZhZGlzZ2xvYmFsLmNvbS9yZXBvc2l0b3J5MIHW +BggrBgEFBQcCAjCByQyBxlJlbGlhbmNlIG9uIHRoaXMgY2VydGlmaWNhdGUg +YnkgYW55IHBhcnR5IGFzc3VtZXMgYWNjZXB0YW5jZSBvZiB0aGUgcmVsZXZh +bnQgUXVvVmFkaXMgQ2VydGlmaWNhdGlvbiBQcmFjdGljZSBTdGF0ZW1lbnQg +YW5kIG90aGVyIGRvY3VtZW50cyBpbiB0aGUgUXVvVmFkaXMgcmVwb3NpdG9y +eSAoaHR0cDovL3d3dy5xdW92YWRpc2dsb2JhbC5jb20pLjAdBgNVHSUEFjAU +BggrBgEFBQcDAgYIKwYBBQUHAwEwQQYDVR0fBDowODA2oDSgMoYwaHR0cDov +L2NybC5xdW92YWRpc2dsb2JhbC5jb20vcGtpb3ByaXZzZXJ2ZzEuY3JsMB0G +A1UdDgQWBBRZAjjqOD74qry7CXrnZUyjOI33CzAOBgNVHQ8BAf8EBAMCBaAw +DQYJKoZIhvcNAQELBQADggIBABiPLzZxV8YAFV0OIvK35Qh11zDZYPEp09RN +9NDsb+kOvShIBQirgejYA1SVZ73vMzFUmVNW/LyKoflH/N3ziU5NoMHK/31G +yP3W5Ffeezo42wLqqv1Ttfod3Tg56LC/jZb0a7R4LoosfFuEvHwWM8vJO8oy +IFuNSclSXOR0UArdeUl6fXsYExFOkdKgsrjcDBH+DOs/LlDPwL9qL3aK6vOG +WMXlfaFfRVhmcqs1ZVXLc+ylyT2DKf96oQSXE/pIB/yCcl3MuG3Xb0mp4MEq +AcAvEa4bIW0c1ULmlmxfw7F8rR2pVWN3wl8fqsxYxg6SNp3+ZKjOvX5GVGz+ +2nGWC+W2szqpRL/uvNWquSZaFHRiFkbJLtZNMy9HF7F0P62ler7BuZ4resb1 +l5d+rRRUocPwBv6GrBv6WE6QXpKkYZyuElkl7u3W+/L5UGaz+rAaMYJ1DdQL +XgAdq4KIuh9VR/YsFpttXUz2ieRBm1s2t0otk/sr0zFT23mt22lVVSaHmfCB +X8xCL9z8Y+XlbhPWhoXf8hvKI9KLcpf+e9OiS84+MYq4xJxoESNoq31oYirM +I1g9TNGKXAKrXIv9laeinsIJnn7zhSFu0LWz8XuvjuxPXtPzi9mOh98wIp6H ++AbyNMBwYTQKpOAd8jsD6+2d1gK5WHtwce5cWxgVdo1czCvY +7593b799e735055fcd479caa35d44d455576cefcMIIG+zCCBOOgAwIBAgIUJmQio80TiqOX3LMrbzeG1dh0ngEwDQYJKoZIhvcN +AQELBQAwgYAxCzAJBgNVBAYTAk5MMSAwHgYDVQQKDBdRdW9WYWRpcyBUcnVz +dGxpbmsgQi5WLjEXMBUGA1UEYQwOTlRSTkwtMzAyMzc0NTkxNjA0BgNVBAMM +LVF1b1ZhZGlzIFBLSW92ZXJoZWlkIFByaXZhdGUgU2VydmljZXMgQ0EgLSBH +MTAeFw0yMzA5MjExOTEyNTlaFw0yNjA5MjExOTA3MDBaMF4xCzAJBgNVBAYT +Ak5MMQ8wDQYDVQQKDAZMb2dpdXMxHTAbBgNVBAUTFDAwMDAwMDA0MTY2OTA5 +OTEzMDAwMR8wHQYDVQQDDBZzYW1sLXNpZ24ucHAxLmRpZ2lkLm5sMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5r8GtcRfX3UN3f7I8Iobhy/N +U0Y+MV6DEXTmDRvRDZjwjr6ammB/cd1fsDz7D5CU+eax205aDRH69mMZk11x +cIKDjISvtBFLQVxwWXgTGpUSBogFHfp70/yfvcC7vq8gE7zjRN9gNzZCC0Ak +D7ZwAfFBbwI9nBSiMby9MY41MjS/W10uik1I6s5Ok2u/WfUe6FjcnaoU1O7O +tpJGAkW/yDC5HWypqeTG1fSPee/0GjvU8FH+Bu73fAFHa86KSO15eaCUR6Ea +7qCjpLsfPizweP9Adehlal1blfxsfJdFunq/jnO8NhYnQ7DC0aBd6ET8Wo/O +1ZacGsYmJWq9dqeleQIDAQABo4ICjDCCAogwHwYDVR0jBBgwFoAUuWymE7q7 +LzRjgzEu+X5JHd8A9WMwfQYIKwYBBQUHAQEEcTBvMD4GCCsGAQUFBzAChjJo +dHRwOi8vdHJ1c3QucXVvdmFkaXNnbG9iYWwuY29tL3BraW9wcml2c2Vydmcx +LmNydDAtBggrBgEFBQcwAYYhaHR0cDovL3NsLm9jc3AucXVvdmFkaXNnbG9i +YWwuY29tMCEGA1UdEQQaMBiCFnNhbWwtc2lnbi5wcDEuZGlnaWQubmwwggEw +BgNVHSAEggEnMIIBIzCCAR8GCmCEEAGHawECCAYwggEPMDQGCCsGAQUFBwIB +FihodHRwOi8vd3d3LnF1b3ZhZGlzZ2xvYmFsLmNvbS9yZXBvc2l0b3J5MIHW +BggrBgEFBQcCAjCByQyBxlJlbGlhbmNlIG9uIHRoaXMgY2VydGlmaWNhdGUg +YnkgYW55IHBhcnR5IGFzc3VtZXMgYWNjZXB0YW5jZSBvZiB0aGUgcmVsZXZh +bnQgUXVvVmFkaXMgQ2VydGlmaWNhdGlvbiBQcmFjdGljZSBTdGF0ZW1lbnQg +YW5kIG90aGVyIGRvY3VtZW50cyBpbiB0aGUgUXVvVmFkaXMgcmVwb3NpdG9y +eSAoaHR0cDovL3d3dy5xdW92YWRpc2dsb2JhbC5jb20pLjAdBgNVHSUEFjAU +BggrBgEFBQcDAgYIKwYBBQUHAwEwQQYDVR0fBDowODA2oDSgMoYwaHR0cDov +L2NybC5xdW92YWRpc2dsb2JhbC5jb20vcGtpb3ByaXZzZXJ2ZzEuY3JsMB0G +A1UdDgQWBBRZAjjqOD74qry7CXrnZUyjOI33CzAOBgNVHQ8BAf8EBAMCBaAw +DQYJKoZIhvcNAQELBQADggIBABiPLzZxV8YAFV0OIvK35Qh11zDZYPEp09RN +9NDsb+kOvShIBQirgejYA1SVZ73vMzFUmVNW/LyKoflH/N3ziU5NoMHK/31G +yP3W5Ffeezo42wLqqv1Ttfod3Tg56LC/jZb0a7R4LoosfFuEvHwWM8vJO8oy +IFuNSclSXOR0UArdeUl6fXsYExFOkdKgsrjcDBH+DOs/LlDPwL9qL3aK6vOG +WMXlfaFfRVhmcqs1ZVXLc+ylyT2DKf96oQSXE/pIB/yCcl3MuG3Xb0mp4MEq +AcAvEa4bIW0c1ULmlmxfw7F8rR2pVWN3wl8fqsxYxg6SNp3+ZKjOvX5GVGz+ +2nGWC+W2szqpRL/uvNWquSZaFHRiFkbJLtZNMy9HF7F0P62ler7BuZ4resb1 +l5d+rRRUocPwBv6GrBv6WE6QXpKkYZyuElkl7u3W+/L5UGaz+rAaMYJ1DdQL +XgAdq4KIuh9VR/YsFpttXUz2ieRBm1s2t0otk/sr0zFT23mt22lVVSaHmfCB +X8xCL9z8Y+XlbhPWhoXf8hvKI9KLcpf+e9OiS84+MYq4xJxoESNoq31oYirM +I1g9TNGKXAKrXIv9laeinsIJnn7zhSFu0LWz8XuvjuxPXtPzi9mOh98wIp6H ++AbyNMBwYTQKpOAd8jsD6+2d1gK5WHtwce5cWxgVdo1czCvY + diff --git a/src/open_inwoner/configurations/tests/bootstrap/test_setup_auth_config.py b/src/open_inwoner/configurations/tests/bootstrap/test_setup_auth_config.py index 603db4d29d..20d19df3ae 100644 --- a/src/open_inwoner/configurations/tests/bootstrap/test_setup_auth_config.py +++ b/src/open_inwoner/configurations/tests/bootstrap/test_setup_auth_config.py @@ -1,14 +1,23 @@ +import urllib.error from unittest import skip +from unittest.mock import patch from django.test import TestCase, override_settings import requests import requests_mock +from digid_eherkenning.choices import ( + DigestAlgorithms, + SignatureAlgorithms, + XMLContentTypes, +) +from digid_eherkenning.models import DigidConfiguration from django_setup_configuration.exceptions import ConfigurationRunFailed from mozilla_django_oidc_db.models import ( OpenIDConnectConfig, UserInformationClaimsSources, ) +from simple_certmanager.constants import CertificateTypes from digid_eherkenning_oidc_generics.models import ( OpenIDConnectDigiDConfig, @@ -17,6 +26,7 @@ from ...bootstrap.auth import ( AdminOIDCConfigurationStep, + DigiDConfigurationStep, DigiDOIDCConfigurationStep, eHerkenningOIDCConfigurationStep, ) @@ -33,6 +43,10 @@ "jwks_uri": f"{IDENTITY_PROVIDER}protocol/openid-connect/certs", } +DIGID_XML_METADATA_PATH = ( + "src/open_inwoner/configurations/tests/bootstrap/files/digid-metadata.xml" +) + @override_settings( DIGID_OIDC_OIDC_RP_CLIENT_ID="client-id", @@ -656,3 +670,147 @@ def test_is_configured(self): config.configure() self.assertTrue(config.is_configured()) + + +@override_settings( + DIGID_CERTIFICATE_LABEL="DigiD certificate", + DIGID_CERTIFICATE_TYPE=CertificateTypes.key_pair, + DIGID_CERTIFICATE_PUBLIC_CERTIFICATE="/tmp/certificate.crt", + DIGID_CERTIFICATE_PRIVATE_KEY="/tmp/key.key", + DIGID_METADATA_FILE_SOURCE="http://metadata.local/file.xml", + DIGID_ENTITY_ID="1234", + DIGID_BASE_URL="http://digid.local", + DIGID_SERVICE_NAME="OIP", + DIGID_SERVICE_DESCRIPTION="Open Inwoner", + DIGID_WANT_ASSERTIONS_SIGNED=False, + DIGID_WANT_ASSERTIONS_ENCRYPTED=True, + DIGID_ARTIFACT_RESOLVE_CONTENT_TYPE=XMLContentTypes.text_xml, + DIGID_KEY_PASSPHRASE="foo", + DIGID_SIGNATURE_ALGORITHM=SignatureAlgorithms.dsa_sha1, + DIGID_DIGEST_ALGORITHM=DigestAlgorithms.sha512, + DIGID_TECHNICAL_CONTACT_PERSON_TELEPHONE="0612345678", + DIGID_TECHNICAL_CONTACT_PERSON_EMAIL="foo@bar.org", + DIGID_ORGANIZATION_URL="http://open-inwoner.local", + DIGID_ORGANIZATION_NAME="Open Inwoner", + DIGID_ATTRIBUTE_CONSUMING_SERVICE_INDEX="2", + DIGID_REQUESTED_ATTRIBUTES=[ + {"name": "bsn", "required": True}, + {"name": "email", "required": False}, + ], + DIGID_SLO=False, +) +class DigiDConfigurationTests(TestCase): + def test_configure(self): + with open(DIGID_XML_METADATA_PATH) as f: + with patch( + "onelogin.saml2.idp_metadata_parser.urllib2.urlopen", return_value=f + ): + DigiDConfigurationStep().configure() + + config = DigidConfiguration.get_solo() + + self.assertEqual(config.certificate.label, "DigiD certificate") + self.assertEqual(config.certificate.type, CertificateTypes.key_pair) + self.assertEqual(config.certificate.public_certificate, "/tmp/certificate.crt") + self.assertEqual(config.certificate.private_key, "/tmp/key.key") + self.assertEqual(config.key_passphrase, "foo") + self.assertEqual(config.metadata_file_source, "http://metadata.local/file.xml") + self.assertEqual( + config.idp_service_entity_id, + "https://was-preprod1.digid.nl/saml/idp/metadata", + ) + self.assertTrue(config.idp_metadata_file.path.endswith(".xml")) + self.assertEqual(config.entity_id, "1234") + self.assertEqual(config.base_url, "http://digid.local") + self.assertEqual(config.service_name, "OIP") + self.assertEqual(config.service_description, "Open Inwoner") + self.assertEqual(config.want_assertions_signed, False) + self.assertEqual(config.want_assertions_encrypted, True) + self.assertEqual(config.artifact_resolve_content_type, XMLContentTypes.text_xml) + self.assertEqual(config.signature_algorithm, SignatureAlgorithms.dsa_sha1) + self.assertEqual(config.digest_algorithm, DigestAlgorithms.sha512) + self.assertEqual(config.technical_contact_person_telephone, "0612345678") + self.assertEqual(config.technical_contact_person_email, "foo@bar.org") + self.assertEqual(config.organization_url, "http://open-inwoner.local") + self.assertEqual(config.organization_name, "Open Inwoner") + self.assertEqual(config.attribute_consuming_service_index, "2") + self.assertEqual( + config.requested_attributes, + [{"name": "bsn", "required": True}, {"name": "email", "required": False}], + ) + self.assertEqual(config.slo, False) + + # TODO asserts + + @override_settings( + DIGID_WANT_ASSERTIONS_SIGNED=None, + DIGID_WANT_ASSERTIONS_ENCRYPTED=None, + DIGID_ARTIFACT_RESOLVE_CONTENT_TYPE=None, + DIGID_KEY_PASSPHRASE=None, + DIGID_SIGNATURE_ALGORITHM=None, + DIGID_DIGEST_ALGORITHM=None, + DIGID_ATTRIBUTE_CONSUMING_SERVICE_INDEX=None, + DIGID_REQUESTED_ATTRIBUTES=None, + DIGID_SLO=None, + ) + def test_configure_use_defaults(self): + with open(DIGID_XML_METADATA_PATH) as f: + with patch( + "onelogin.saml2.idp_metadata_parser.urllib2.urlopen", return_value=f + ): + DigiDConfigurationStep().configure() + + config = DigidConfiguration.get_solo() + + self.assertEqual(config.key_passphrase, "") + self.assertEqual(config.want_assertions_signed, True) + self.assertEqual(config.want_assertions_encrypted, False) + self.assertEqual(config.artifact_resolve_content_type, XMLContentTypes.soap_xml) + self.assertEqual(config.signature_algorithm, SignatureAlgorithms.rsa_sha1) + self.assertEqual(config.digest_algorithm, DigestAlgorithms.sha1) + self.assertEqual(config.attribute_consuming_service_index, "1") + self.assertEqual( + config.requested_attributes, + [{"name": "bsn", "required": True}], + ) + self.assertEqual(config.slo, True) + + # TODO asserts + + def test_configure_failure(self): + exceptions = (urllib.error.HTTPError, urllib.error.URLError) + for exception in exceptions: + with self.subTest(exception=exception): + with patch( + "onelogin.saml2.idp_metadata_parser.urllib2.urlopen", + side_effect=exception, + ): + with self.assertRaises(ConfigurationRunFailed): + DigiDConfigurationStep().configure() + + config = DigidConfiguration.get_solo() + + self.assertFalse(config.certificate, None) + + @skip("Testing config for DigiD OIDC is not implemented yet") + @requests_mock.Mocker() + def test_configuration_check_ok(self, m): + raise NotImplementedError + + @skip("Testing config for DigiD OIDC is not implemented yet") + @requests_mock.Mocker() + def test_configuration_check_failures(self, m): + raise NotImplementedError + + def test_is_configured(self): + config = DigiDConfigurationStep() + + self.assertFalse(config.is_configured()) + + with open(DIGID_XML_METADATA_PATH) as f: + with patch( + "onelogin.saml2.idp_metadata_parser.urllib2.urlopen", return_value=f + ): + config.configure() + + self.assertTrue(config.is_configured())