diff options
-rw-r--r-- | changelogs/fragments/75015-ca-path-bundle.yml | 3 | ||||
-rw-r--r-- | lib/ansible/module_utils/urls.py | 28 | ||||
-rw-r--r-- | test/integration/targets/uri/tasks/main.yml | 19 |
3 files changed, 42 insertions, 8 deletions
diff --git a/changelogs/fragments/75015-ca-path-bundle.yml b/changelogs/fragments/75015-ca-path-bundle.yml new file mode 100644 index 0000000000..574f5aa96b --- /dev/null +++ b/changelogs/fragments/75015-ca-path-bundle.yml @@ -0,0 +1,3 @@ +bugfixes: +- urls - Allow ``ca_path`` to point to a bundle containing multiple PEM certs + (https://github.com/ansible/ansible/issues/75015) diff --git a/lib/ansible/module_utils/urls.py b/lib/ansible/module_utils/urls.py index 5ba945931d..c6b194d680 100644 --- a/lib/ansible/module_utils/urls.py +++ b/lib/ansible/module_utils/urls.py @@ -475,6 +475,11 @@ zKPZsZ2miVGclicJHzm5q080b1p/sZtuKIEZk6vZqEg= -----END CERTIFICATE----- """ +b_PEM_CERT_RE = re.compile( + br'^-----BEGIN CERTIFICATE-----\n.+?-----END CERTIFICATE-----$', + flags=re.M | re.S +) + # # Exceptions # @@ -745,6 +750,11 @@ def generic_urlparse(parts): return generic_parts +def extract_pem_certs(b_data): + for match in b_PEM_CERT_RE.finditer(b_data): + yield match.group(0) + + class RequestWithMethod(urllib_request.Request): ''' Workaround for using DELETE/PUT/etc with urllib2 @@ -918,11 +928,12 @@ class SSLValidationHandler(urllib_request.BaseHandler): paths_checked = [self.ca_path] with open(to_bytes(self.ca_path, errors='surrogate_or_strict'), 'rb') as f: if HAS_SSLCONTEXT: - cadata.extend( - ssl.PEM_cert_to_DER_cert( - to_native(f.read(), errors='surrogate_or_strict') + for b_pem in extract_pem_certs(f.read()): + cadata.extend( + ssl.PEM_cert_to_DER_cert( + to_native(b_pem, errors='surrogate_or_strict') + ) ) - ) return self.ca_path, cadata, paths_checked if not HAS_SSLCONTEXT: @@ -981,11 +992,12 @@ class SSLValidationHandler(urllib_request.BaseHandler): b_cert = cert_file.read() if HAS_SSLCONTEXT: try: - cadata.extend( - ssl.PEM_cert_to_DER_cert( - to_native(b_cert, errors='surrogate_or_strict') + for b_pem in extract_pem_certs(b_cert): + cadata.extend( + ssl.PEM_cert_to_DER_cert( + to_native(b_pem, errors='surrogate_or_strict') + ) ) - ) except Exception: continue else: diff --git a/test/integration/targets/uri/tasks/main.yml b/test/integration/targets/uri/tasks/main.yml index 700e7f1017..a91c425db7 100644 --- a/test/integration/targets/uri/tasks/main.yml +++ b/test/integration/targets/uri/tasks/main.yml @@ -173,6 +173,25 @@ - result is failed - "'certificate verify failed' in result.msg" +- name: Locate ca-bundle + stat: + path: '{{ item }}' + loop: + - /etc/ssl/certs/ca-bundle.crt + - /etc/ssl/certs/ca-certificates.crt + - /var/lib/ca-certificates/ca-bundle.pem + - /usr/local/share/certs/ca-root-nss.crt + - '{{ macos_cafile.stdout_lines|default(["/_i_dont_exist_ca.pem"])|first }}' + - /etc/ssl/cert.pem + register: ca_bundle_candidates + +- name: Test that ca_path can be a full bundle + uri: + url: "https://{{ httpbin_host }}/get" + ca_path: '{{ ca_bundle }}' + vars: + ca_bundle: '{{ ca_bundle_candidates.results|selectattr("stat.exists")|map(attribute="item")|first }}' + - name: test redirect without follow_redirects uri: url: 'https://{{ httpbin_host }}/redirect/2' |