diff --git a/changelogs/fragments/324-acme_certificate-fullchain.yml b/changelogs/fragments/324-acme_certificate-fullchain.yml new file mode 100644 index 000000000..10f5eb36d --- /dev/null +++ b/changelogs/fragments/324-acme_certificate-fullchain.yml @@ -0,0 +1,2 @@ +bugfixes: + - "acme_certificate - avoid passing multiple certificates to ``cryptography``'s X.509 certificate loader when ``fullchain_dest`` is used. Doing so potentially produces an error when cryptography 36.0.0 is used (https://github.com/ansible-collections/community.crypto/pull/324)." diff --git a/plugins/module_utils/acme/backend_cryptography.py b/plugins/module_utils/acme/backend_cryptography.py index ed1cf9a45..8f0a35dcb 100644 --- a/plugins/module_utils/acme/backend_cryptography.py +++ b/plugins/module_utils/acme/backend_cryptography.py @@ -14,7 +14,7 @@ import os import sys -from ansible.module_utils.common.text.converters import to_bytes, to_native +from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text from ansible_collections.community.crypto.plugins.module_utils.acme.backends import ( CryptoBackend, @@ -41,6 +41,10 @@ cryptography_name_to_oid, ) +from ansible_collections.community.crypto.plugins.module_utils.crypto.pem import ( + extract_first_pem, +) + try: import cryptography import cryptography.hazmat.backends @@ -357,6 +361,9 @@ def get_cert_days(self, cert_filename=None, cert_content=None, now=None): if cert_content is None: return -1 + # Make sure we have at most one PEM. Otherwise cryptography 36.0.0 will barf. + cert_content = to_bytes(extract_first_pem(to_text(cert_content)) or '') + try: cert = cryptography.x509.load_pem_x509_certificate(cert_content, _cryptography_backend) except Exception as e: diff --git a/plugins/module_utils/crypto/pem.py b/plugins/module_utils/crypto/pem.py index a59f710a4..ffa0df068 100644 --- a/plugins/module_utils/crypto/pem.py +++ b/plugins/module_utils/crypto/pem.py @@ -72,3 +72,13 @@ def split_pem_list(text, keep_inbetween=False): result.append(''.join(current)) current = [] if keep_inbetween else None return result + + +def extract_first_pem(text): + ''' + Given one PEM or multiple concatenated PEM objects, return only the first one, or None if there is none. + ''' + all_pems = split_pem_list(text) + if not all_pems: + return None + return all_pems[0]