diff --git a/.github/workflows/ee.yml b/.github/workflows/ee.yml index 73e58dc9..7b4bd7bf 100644 --- a/.github/workflows/ee.yml +++ b/.github/workflows/ee.yml @@ -48,36 +48,28 @@ jobs: ansible_runner: ansible-runner other_deps: |2 python_interpreter: - package_system: python3.11 python3.11-pip python3.11-wheel python3.11-cryptography - python_path: "/usr/bin/python3.11" + package_system: python3.12 python3.12-pip python3.12-wheel python3.12-cryptography + python_path: "/usr/bin/python3.12" base_image: docker.io/redhat/ubi9:latest pre_base: '"#"' - # For some reason ansible-builder will not install EPEL dependencies on RHEL - extra_vars: -e has_no_pyopenssl=true - - name: ansible-core 2.15 @ Rocky Linux 9 - ansible_core: https://github.com/ansible/ansible/archive/stable-2.15.tar.gz - ansible_runner: ansible-runner - base_image: quay.io/rockylinux/rockylinux:9 - pre_base: RUN dnf install -y epel-release - # For some reason ansible-builder will not install EPEL dependencies on Rocky Linux - extra_vars: -e has_no_pyopenssl=true - - name: ansible-core 2.14 @ CentOS Stream 9 - ansible_core: https://github.com/ansible/ansible/archive/stable-2.14.tar.gz - ansible_runner: ansible-runner - base_image: quay.io/centos/centos:stream9 - pre_base: RUN dnf install -y epel-release epel-next-release - # For some reason, PyOpenSSL is **broken** on CentOS Stream 9 / EPEL - extra_vars: -e has_no_pyopenssl=true - - name: ansible-core 2.13 @ RHEL UBI 8 - ansible_core: https://github.com/ansible/ansible/archive/stable-2.13.tar.gz + - name: ansible-core 2.17 @ Rocky Linux 9 + ansible_core: https://github.com/ansible/ansible/archive/stable-2.17.tar.gz ansible_runner: ansible-runner other_deps: |2 python_interpreter: - package_system: python39 python39-pip python39-wheel python39-cryptography - base_image: docker.io/redhat/ubi8:latest + package_system: python3.11 python3.11-pip python3.11-wheel python3.11-cryptography + python_path: "/usr/bin/python3.11" + base_image: quay.io/rockylinux/rockylinux:9 + pre_base: RUN dnf install -y epel-release + - name: ansible-core 2.18 @ CentOS Stream 9 + ansible_core: https://github.com/ansible/ansible/archive/stable-2.18.tar.gz + ansible_runner: ansible-runner + other_deps: |2 + python_interpreter: + package_system: python3.11 python3.11-pip python3.11-wheel python3.11-cryptography + python_path: "/usr/bin/python3.11" + base_image: quay.io/centos/centos:stream9 pre_base: '"#"' - # We don't have PyOpenSSL for Python 3.9 - extra_vars: -e has_no_pyopenssl=true runs-on: ubuntu-latest steps: - name: Check out code diff --git a/changelogs/fragments/874-pyopenssl.yml b/changelogs/fragments/874-pyopenssl.yml new file mode 100644 index 00000000..28978456 --- /dev/null +++ b/changelogs/fragments/874-pyopenssl.yml @@ -0,0 +1,4 @@ +removed_features: + - "crypto.support module utils - remove ``pyopenssl`` backend (https://github.com/ansible-collections/community.crypto/pull/874)." + - "time module utils - remove ``pyopenssl`` backend (https://github.com/ansible-collections/community.crypto/pull/874)." + - "execution environment dependencies - remove PyOpenSSL dependency (https://github.com/ansible-collections/community.crypto/pull/874)." diff --git a/meta/ee-bindep.txt b/meta/ee-bindep.txt index b448d540..ca4dc697 100644 --- a/meta/ee-bindep.txt +++ b/meta/ee-bindep.txt @@ -11,11 +11,3 @@ openssl [platform:rpm] python3-cryptography [platform:dpkg] python3-cryptography [platform:rpm] python3-openssl [platform:dpkg] -# On RHEL 9+, CentOS Stream 9+, and Rocky Linux 9+, python3-pyOpenSSL is part of EPEL -python3-pyOpenSSL [platform:rpm !platform:rhel !platform:centos !platform:rocky] -python3-pyOpenSSL [platform:rhel-8] -python3-pyOpenSSL [platform:rhel !platform:rhel-6 !platform:rhel-7 !platform:rhel-8 epel] -python3-pyOpenSSL [platform:centos-8] -python3-pyOpenSSL [platform:centos !platform:centos-6 !platform:centos-7 !platform:centos-8 epel] -python3-pyOpenSSL [platform:rocky-8] -python3-pyOpenSSL [platform:rocky !platform:rocky-8 epel] diff --git a/plugins/module_utils/crypto/support.py b/plugins/module_utils/crypto/support.py index 931113c3..b22935e0 100644 --- a/plugins/module_utils/crypto/support.py +++ b/plugins/module_utils/crypto/support.py @@ -30,14 +30,6 @@ from ansible_collections.community.crypto.plugins.module_utils.time import ( # ) -try: - from OpenSSL import crypto - - HAS_PYOPENSSL = True -except (ImportError, AttributeError): - # Error handled in the calling module. - HAS_PYOPENSSL = False - try: from cryptography import x509 from cryptography.hazmat.backends import default_backend as cryptography_backend @@ -160,53 +152,7 @@ def load_privatekey( except (IOError, OSError) as exc: raise OpenSSLObjectError(exc) - if backend == "pyopenssl": - - # First try: try to load with real passphrase (resp. empty string) - # Will work if this is the correct passphrase, or the key is not - # password-protected. - try: - result = crypto.load_privatekey( - crypto.FILETYPE_PEM, priv_key_detail, to_bytes(passphrase or "") - ) - except crypto.Error as e: - if len(e.args) > 0 and len(e.args[0]) > 0: - if e.args[0][0][2] in ("bad decrypt", "bad password read"): - # This happens in case we have the wrong passphrase. - if passphrase is not None: - raise OpenSSLBadPassphraseError( - "Wrong passphrase provided for private key!" - ) - else: - raise OpenSSLBadPassphraseError( - "No passphrase provided, but private key is password-protected!" - ) - raise OpenSSLObjectError("Error while deserializing key: {0}".format(e)) - if check_passphrase: - # Next we want to make sure that the key is actually protected by - # a passphrase (in case we did try the empty string before, make - # sure that the key is not protected by the empty string) - try: - crypto.load_privatekey( - crypto.FILETYPE_PEM, - priv_key_detail, - to_bytes("y" if passphrase == "x" else "x"), - ) - if passphrase is not None: - # Since we can load the key without an exception, the - # key is not password-protected - raise OpenSSLBadPassphraseError( - "Passphrase provided, but private key is not password-protected!" - ) - except crypto.Error as e: - if passphrase is None and len(e.args) > 0 and len(e.args[0]) > 0: - if e.args[0][0][2] in ("bad decrypt", "bad password read"): - # The key is obviously protected by the empty string. - # Do not do this at home (if it is possible at all)... - raise OpenSSLBadPassphraseError( - "No passphrase provided, but private key is password-protected!" - ) - elif backend == "cryptography": + if backend == "cryptography": try: result = load_pem_private_key( priv_key_detail, @@ -255,14 +201,7 @@ def load_certificate( cert_content = content except (IOError, OSError) as exc: raise OpenSSLObjectError(exc) - if backend == "pyopenssl": - if der_support_enabled is False or identify_pem_format(cert_content): - return crypto.load_certificate(crypto.FILETYPE_PEM, cert_content) - elif der_support_enabled: - raise OpenSSLObjectError( - "Certificate in DER format is not supported by the pyopenssl backend." - ) - elif backend == "cryptography": + if backend == "cryptography": if der_support_enabled is False or identify_pem_format(cert_content): try: return x509.load_pem_x509_certificate( diff --git a/plugins/module_utils/time.py b/plugins/module_utils/time.py index bc9e8e63..e2b0418d 100644 --- a/plugins/module_utils/time.py +++ b/plugins/module_utils/time.py @@ -143,11 +143,12 @@ def convert_relative_to_datetime(relative_time_string, with_timezone=False, now= def get_relative_time_option( input_string, input_name, backend="cryptography", with_timezone=False, now=None ): - """Return an absolute timespec if a relative timespec or an ASN1 formatted + """ + Return an absolute timespec if a relative timespec or an ASN1 formatted string is provided. - The return value will be a datetime object for the cryptography backend, - and a ASN1 formatted string for the pyopenssl backend.""" + The return value will be a datetime object for the cryptography backend. + """ result = to_native(input_string) if result is None: raise OpenSSLObjectError( @@ -158,14 +159,10 @@ def get_relative_time_option( result_datetime = convert_relative_to_datetime( result, with_timezone=with_timezone, now=now ) - if backend == "pyopenssl": - return result_datetime.strftime("%Y%m%d%H%M%SZ") - elif backend == "cryptography": + if backend == "cryptography": return result_datetime # Absolute time - if backend == "pyopenssl": - return input_string - elif backend == "cryptography": + if backend == "cryptography": for date_fmt, length in [ ( "%Y%m%d%H%M%SZ", diff --git a/tests/ee/all.yml b/tests/ee/all.yml index a8f1f666..962b24a7 100644 --- a/tests/ee/all.yml +++ b/tests/ee/all.yml @@ -13,11 +13,6 @@ command: "{{ ansible_python.executable }} -c 'import cryptography; print(cryptography.__version__)'" register: cryptography_version - - name: Register pyOpenSSL version - command: "{{ ansible_python.executable }} -c 'import OpenSSL; print(OpenSSL.__version__)'" - ignore_errors: true - register: pyopenssl_version - - name: Determine output directory set_fact: output_path: "{{ 'output-%0x' % ((2**32) | random) }}" diff --git a/tests/ee/roles/openssl_pkcs12/tasks/main.yml b/tests/ee/roles/openssl_pkcs12/tasks/main.yml index 2fd8edac..6b080875 100644 --- a/tests/ee/roles/openssl_pkcs12/tasks/main.yml +++ b/tests/ee/roles/openssl_pkcs12/tasks/main.yml @@ -21,7 +21,7 @@ privatekey_path: "{{ output_path }}/pkcs12-cert.key" provider: selfsigned -- name: Create PKCS#12 with cryptography backend +- name: Create PKCS#12 community.crypto.openssl_pkcs12: action: export path: "{{ output_path }}/pkcs12-1.p12" @@ -30,17 +30,3 @@ privatekey_path: "{{ output_path }}/pkcs12-cert.key" certificate_path: "{{ output_path }}/pkcs12-cert.pem" state: present - select_crypto_backend: cryptography - when: cryptography_version.stdout is ansible.builtin.version('3.0', '>=') - -- name: Create PKCS#12 with PyOpenSSL backend - community.crypto.openssl_pkcs12: - action: export - path: "{{ output_path }}/pkcs12-2.p12" - mode: '0644' - friendly_name: foo - privatekey_path: "{{ output_path }}/pkcs12-cert.key" - certificate_path: "{{ output_path }}/pkcs12-cert.pem" - state: present - select_crypto_backend: pyopenssl - when: not (has_no_pyopenssl | default(false)) diff --git a/tests/unit/plugins/module_utils/test_time.py b/tests/unit/plugins/module_utils/test_time.py index 3bf33813..e7a47440 100644 --- a/tests/unit/plugins/module_utils/test_time.py +++ b/tests/unit/plugins/module_utils/test_time.py @@ -225,38 +225,6 @@ TEST_GET_RELATIVE_TIME_OPTION = cartesian_product( datetime.datetime(2024, 1, 1, 0, 0, 0), datetime.datetime(2024, 1, 2, 4, 5, 0, tzinfo=UTC), ), - ( - "+1d2h3m4s", - "foo", - "pyopenssl", - False, - datetime.datetime(2024, 1, 1, 0, 0, 0), - "20240102020304Z", - ), - ( - "-1w10d24h", - "foo", - "pyopenssl", - False, - datetime.datetime(2024, 1, 1, 0, 0, 0), - "20231214000000Z", - ), - ( - "20240102040506Z", - "foo", - "pyopenssl", - False, - datetime.datetime(2024, 1, 1, 0, 0, 0), - "20240102040506Z", - ), - ( - "202401020405Z", - "foo", - "pyopenssl", - False, - datetime.datetime(2024, 1, 1, 0, 0, 0), - "202401020405Z", - ), ], ) @@ -333,22 +301,6 @@ if sys.version_info >= (3, 5): datetime.datetime(2024, 1, 1, 0, 0, 0), datetime.datetime(2024, 1, 2, 3, 5, 0, tzinfo=UTC), ), - ( - "20240102040506+0100", - "foo", - "pyopenssl", - False, - datetime.datetime(2024, 1, 1, 0, 0, 0), - "20240102040506+0100", - ), - ( - "202401020405+0100", - "foo", - "pyopenssl", - False, - datetime.datetime(2024, 1, 1, 0, 0, 0), - "202401020405+0100", - ), ], ) )