From 03427e35a7cfdc8277dfcb3a5cc4083ed2707fb9 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 14 Sep 2021 07:06:35 +0200 Subject: [PATCH] Fix idempotency for non-ASCII string comparisons. (#271) --- changelogs/fragments/271-openssl_csr-utf8.yml | 2 + .../crypto/module_backends/csr.py | 18 ++++---- .../targets/openssl_csr/tasks/impl.yml | 44 +++++++++---------- .../targets/openssl_csr/tests/validate.yml | 12 ++--- 4 files changed, 39 insertions(+), 37 deletions(-) create mode 100644 changelogs/fragments/271-openssl_csr-utf8.yml diff --git a/changelogs/fragments/271-openssl_csr-utf8.yml b/changelogs/fragments/271-openssl_csr-utf8.yml new file mode 100644 index 00000000..c3186d52 --- /dev/null +++ b/changelogs/fragments/271-openssl_csr-utf8.yml @@ -0,0 +1,2 @@ +bugfixes: +- "openssl_csr and openssl_csr_pipe - make sure that Unicode strings are used to compare strings with the cryptography backend. This fixes idempotency problems with non-ASCII letters on Python 2 (https://github.com/ansible-collections/community.crypto/issues/270, https://github.com/ansible-collections/community.crypto/pull/271)." diff --git a/plugins/module_utils/crypto/module_backends/csr.py b/plugins/module_utils/crypto/module_backends/csr.py index 628eeae7..1c11131d 100644 --- a/plugins/module_utils/crypto/module_backends/csr.py +++ b/plugins/module_utils/crypto/module_backends/csr.py @@ -592,7 +592,7 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack def _check_csr(self): """Check whether provided parameters, assuming self.existing_csr and self.privatekey have been populated.""" def _check_subject(csr): - subject = [(cryptography_name_to_oid(entry[0]), entry[1]) for entry in self.subject] + subject = [(cryptography_name_to_oid(entry[0]), to_text(entry[1])) for entry in self.subject] current_subject = [(sub.oid, sub.value) for sub in csr.subject] return set(subject) == set(current_subject) @@ -604,8 +604,8 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack def _check_subjectAltName(extensions): current_altnames_ext = _find_extension(extensions, cryptography.x509.SubjectAlternativeName) - current_altnames = [str(altname) for altname in current_altnames_ext.value] if current_altnames_ext else [] - altnames = [str(cryptography_get_name(altname)) for altname in self.subjectAltName] if self.subjectAltName else [] + current_altnames = [to_text(altname) for altname in current_altnames_ext.value] if current_altnames_ext else [] + altnames = [to_text(cryptography_get_name(altname)) for altname in self.subjectAltName] if self.subjectAltName else [] if set(altnames) != set(current_altnames): return False if altnames: @@ -678,10 +678,10 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack def _check_nameConstraints(extensions): current_nc_ext = _find_extension(extensions, cryptography.x509.NameConstraints) - current_nc_perm = [str(altname) for altname in current_nc_ext.value.permitted_subtrees] if current_nc_ext else [] - current_nc_excl = [str(altname) for altname in current_nc_ext.value.excluded_subtrees] if current_nc_ext else [] - nc_perm = [str(cryptography_get_name(altname, 'name constraints permitted')) for altname in self.name_constraints_permitted] - nc_excl = [str(cryptography_get_name(altname, 'name constraints excluded')) for altname in self.name_constraints_excluded] + current_nc_perm = [to_text(altname) for altname in current_nc_ext.value.permitted_subtrees] if current_nc_ext else [] + current_nc_excl = [to_text(altname) for altname in current_nc_ext.value.excluded_subtrees] if current_nc_ext else [] + nc_perm = [to_text(cryptography_get_name(altname, 'name constraints permitted')) for altname in self.name_constraints_permitted] + nc_excl = [to_text(cryptography_get_name(altname, 'name constraints excluded')) for altname in self.name_constraints_excluded] if set(nc_perm) != set(current_nc_perm) or set(nc_excl) != set(current_nc_excl): return False if nc_perm or nc_excl: @@ -710,9 +710,9 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack aci = None csr_aci = None if self.authority_cert_issuer is not None: - aci = [str(cryptography_get_name(n, 'authority cert issuer')) for n in self.authority_cert_issuer] + aci = [to_text(cryptography_get_name(n, 'authority cert issuer')) for n in self.authority_cert_issuer] if ext.value.authority_cert_issuer is not None: - csr_aci = [str(n) for n in ext.value.authority_cert_issuer] + csr_aci = [to_text(n) for n in ext.value.authority_cert_issuer] return (ext.value.key_identifier == self.authority_key_identifier and csr_aci == aci and ext.value.authority_cert_serial_number == self.authority_cert_serial_number) diff --git a/tests/integration/targets/openssl_csr/tasks/impl.yml b/tests/integration/targets/openssl_csr/tasks/impl.yml index 51a459a8..fc01a5b1 100644 --- a/tests/integration/targets/openssl_csr/tasks/impl.yml +++ b/tests/integration/targets/openssl_csr/tasks/impl.yml @@ -536,14 +536,14 @@ commonName: www.example.com C: de L: Somewhere - ST: Zurich - streetAddress: Welcome Street - O: Ansible - organizationalUnitName: Crypto Department + ST: Zürich + streetAddress: Welcome Street N° 5 + O: Ansiblé + organizationalUnitName: Crÿpto Depârtment ☺ serialNumber: "1234" - SN: Last Name + SN: Last Name Which Happens To Be A Very Løng String With A Lot Of Spaces, Jr. GN: First Name - title: Chief + title: Chïeff pseudonym: test UID: asdf emailAddress: test@example.com @@ -641,17 +641,17 @@ path: '{{ remote_tmp_dir }}/csr_everything.csr' privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem' subject: - commonName: www.example.com - C: de + CN: www.example.com + countryName: de L: Somewhere - ST: Zurich - streetAddress: Welcome Street - O: Ansible - organizationalUnitName: Crypto Department + ST: Zürich + streetAddress: Welcome Street N° 5 + organizationName: Ansiblé + organizationalUnitName: Crÿpto Depârtment ☺ serialNumber: "1234" - SN: Last Name + SN: Last Name Which Happens To Be A Very Løng String With A Lot Of Spaces, Jr. GN: First Name - title: Chief + title: Chïeff pseudonym: test UID: asdf emailAddress: test@example.com @@ -750,17 +750,17 @@ path: '{{ remote_tmp_dir }}/csr_everything.csr' privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem' subject: - commonName: www.example.com - C: de + CN: www.example.com + countryName: de L: Somewhere - ST: Zurich - streetAddress: Welcome Street - O: Ansible - organizationalUnitName: Crypto Department + ST: Zürich + streetAddress: Welcome Street N° 5 + organizationName: Ansiblé + organizationalUnitName: Crÿpto Depârtment ☺ serialNumber: "1234" - SN: Last Name + SN: Last Name Which Happens To Be A Very Løng String With A Lot Of Spaces, Jr. GN: First Name - title: Chief + title: Chïeff pseudonym: test UID: asdf emailAddress: test@example.com diff --git a/tests/integration/targets/openssl_csr/tests/validate.yml b/tests/integration/targets/openssl_csr/tests/validate.yml index 5b2eb49a..56afbe1a 100644 --- a/tests/integration/targets/openssl_csr/tests/validate.yml +++ b/tests/integration/targets/openssl_csr/tests/validate.yml @@ -224,16 +224,16 @@ - everything_info.subject.emailAddress == "test@example.com" - everything_info.subject.givenName == "First Name" - everything_info.subject.localityName == "Somewhere" - - everything_info.subject.organizationName == "Ansible" - - everything_info.subject.organizationalUnitName == "Crypto Department" + - everything_info.subject.organizationName == "Ansiblé" + - everything_info.subject.organizationalUnitName == "Crÿpto Depârtment ☺" - everything_info.subject.postalAddress == "1234 Somewhere" - everything_info.subject.postalCode == "1234" - everything_info.subject.pseudonym == "test" - everything_info.subject.serialNumber == "1234" - - everything_info.subject.stateOrProvinceName == "Zurich" - - everything_info.subject.streetAddress == "Welcome Street" - - everything_info.subject.surname == "Last Name" - - everything_info.subject.title == "Chief" + - everything_info.subject.stateOrProvinceName == "Zürich" + - everything_info.subject.streetAddress == "Welcome Street N° 5" + - everything_info.subject.surname == "Last Name Which Happens To Be A Very Løng String With A Lot Of Spaces, Jr." + - everything_info.subject.title == "Chïeff" - everything_info.subject.userId == "asdf" - everything_info.subject | length == 16 - everything_info.subject_alt_name_critical == false