From 7eb6b6323a9aeeb821108a67cc866e328f6ab918 Mon Sep 17 00:00:00 2001 From: Sergei Maertens Date: Fri, 4 Oct 2024 09:38:43 +0200 Subject: [PATCH] :sparkles: [#403] Support cafile and capath parameters (#415) When retrieving the IDP metadata, you can now optionally specify the the capath or cafile to use for certificate verification, rather than just enabling/disabling it. This allows TLS verification of server certificates that are not in the system root store (such as when using private CAs). --- src/onelogin/saml2/idp_metadata_parser.py | 33 ++++++++++++------- .../saml2_tests/idp_metadata_parser_test.py | 5 +-- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/onelogin/saml2/idp_metadata_parser.py b/src/onelogin/saml2/idp_metadata_parser.py index 6710ff1f..b3b3d9be 100644 --- a/src/onelogin/saml2/idp_metadata_parser.py +++ b/src/onelogin/saml2/idp_metadata_parser.py @@ -6,11 +6,7 @@ from copy import deepcopy - -try: - import urllib.request as urllib2 -except ImportError: - import urllib2 +from urllib.request import Request, urlopen import ssl @@ -27,7 +23,15 @@ class OneLogin_Saml2_IdPMetadataParser(object): """ @classmethod - def get_metadata(cls, url, validate_cert=True, timeout=None, headers=None): + def get_metadata( + cls, + url, + validate_cert=True, + cafile=None, + capath=None, + timeout=None, + headers=None, + ): """ Gets the metadata XML from the provided URL :param url: Url where the XML of the Identity Provider Metadata is published. @@ -46,15 +50,20 @@ def get_metadata(cls, url, validate_cert=True, timeout=None, headers=None): """ valid = False - request = urllib2.Request(url, headers=headers or {}) - - if validate_cert: - response = urllib2.urlopen(request, timeout=timeout) - else: + # Respect the no-TLS-certificate validation option + ctx = None + if not validate_cert: + if cafile or capath: + raise ValueError( + "Specifying 'cafile' or 'capath' while disabling certificate " + "validation is contradictory." + ) ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE - response = urllib2.urlopen(request, context=ctx, timeout=timeout) + + request = Request(url, headers=headers or {}) + response = urlopen(request, timeout=timeout, cafile=cafile, capath=capath, context=ctx) xml = response.read() if xml: diff --git a/tests/src/OneLogin/saml2_tests/idp_metadata_parser_test.py b/tests/src/OneLogin/saml2_tests/idp_metadata_parser_test.py index cff9418b..4f352f69 100644 --- a/tests/src/OneLogin/saml2_tests/idp_metadata_parser_test.py +++ b/tests/src/OneLogin/saml2_tests/idp_metadata_parser_test.py @@ -1,10 +1,7 @@ # -*- coding: utf-8 -*- -try: - from urllib.error import URLError -except ImportError: - from urllib2 import URLError +from urllib.error import URLError from copy import deepcopy import json