Remove more traces of PyOpenSSL, including from EE dependencies (#874)

* Remove PyOpenSSL backends.

* Remove EOL ansible-core's from EE builds.

* Update Pythons in EEs.

* Remove pyopenssl tests.
This commit is contained in:
Felix Fontein
2025-04-29 09:33:21 +02:00
committed by GitHub
parent 718021b714
commit 266082db72
8 changed files with 29 additions and 172 deletions

View File

@@ -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

View File

@@ -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)."

View File

@@ -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]

View File

@@ -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(

View File

@@ -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",

View File

@@ -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) }}"

View File

@@ -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))

View File

@@ -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",
),
],
)
)