diff --git a/changelogs/fragments/51473-openssl_csr-idempotence.yaml b/changelogs/fragments/51473-openssl_csr-idempotence.yaml new file mode 100644 index 0000000000..ed636b4a8f --- /dev/null +++ b/changelogs/fragments/51473-openssl_csr-idempotence.yaml @@ -0,0 +1,2 @@ +bugfixes: +- "openssl_csr - fixes idempotence problem with PyOpenSSL backend when no Subject Alternative Names were specified." diff --git a/lib/ansible/modules/crypto/openssl_csr.py b/lib/ansible/modules/crypto/openssl_csr.py index 1ed86269ea..07e7eef639 100644 --- a/lib/ansible/modules/crypto/openssl_csr.py +++ b/lib/ansible/modules/crypto/openssl_csr.py @@ -534,7 +534,7 @@ class CertificateSigningRequestPyOpenSSL(CertificateSigningRequestBase): def _check_subjectAltName(extensions): altnames_ext = next((ext for ext in extensions if ext.get_short_name() == b'subjectAltName'), '') - altnames = [altname.strip() for altname in str(altnames_ext).split(',')] + altnames = [altname.strip() for altname in str(altnames_ext).split(',') if altname.strip()] # apperently openssl returns 'IP address' not 'IP' as specifier when converting the subjectAltName to string # although it won't accept this specifier when generating the CSR. (https://github.com/openssl/openssl/issues/4004) altnames = [name if not name.startswith('IP Address:') else "IP:" + name.split(':', 1)[1] for name in altnames] @@ -840,7 +840,7 @@ class CertificateSigningRequestCryptography(CertificateSigningRequestBase): 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(self._get_san(altname)) for altname in self.subjectAltName] + altnames = [str(self._get_san(altname)) for altname in self.subjectAltName] if self.subjectAltName else [] if set(altnames) != set(current_altnames): return False if altnames: diff --git a/test/integration/targets/openssl_csr/tasks/impl.yml b/test/integration/targets/openssl_csr/tasks/impl.yml index 79c2cd43b8..6d7461270f 100644 --- a/test/integration/targets/openssl_csr/tasks/impl.yml +++ b/test/integration/targets/openssl_csr/tasks/impl.yml @@ -41,6 +41,48 @@ check_mode: yes register: generate_csr_check_idempotent_check +- name: Generate CSR without SAN (check mode) + openssl_csr: + path: '{{ output_dir }}/csr-nosan.csr' + privatekey_path: '{{ output_dir }}/privatekey.pem' + subject: + commonName: www.ansible.com + useCommonNameForSAN: no + select_crypto_backend: '{{ select_crypto_backend }}' + check_mode: yes + register: generate_csr_nosan_check + +- name: Generate CSR without SAN + openssl_csr: + path: '{{ output_dir }}/csr-nosan.csr' + privatekey_path: '{{ output_dir }}/privatekey.pem' + subject: + commonName: www.ansible.com + useCommonNameForSAN: no + select_crypto_backend: '{{ select_crypto_backend }}' + register: generate_csr_nosan + +- name: Generate CSR without SAN (idempotent) + openssl_csr: + path: '{{ output_dir }}/csr-nosan.csr' + privatekey_path: '{{ output_dir }}/privatekey.pem' + subject: + commonName: www.ansible.com + useCommonNameForSAN: no + select_crypto_backend: '{{ select_crypto_backend }}' + register: generate_csr_nosan_check_idempotent + +- name: Generate CSR without SAN (idempotent, check mode) + openssl_csr: + path: '{{ output_dir }}/csr-nosan.csr' + privatekey_path: '{{ output_dir }}/privatekey.pem' + subject: + commonName: www.ansible.com + useCommonNameForSAN: no + select_crypto_backend: '{{ select_crypto_backend }}' + check_mode: yes + register: generate_csr_nosan_check_idempotent_check + # keyUsage longname and shortname should be able to be used # interchangeably. Hence the long name is specified here # but the short name is used to test idempotency for ipsecuser diff --git a/test/integration/targets/openssl_csr/tests/validate.yml b/test/integration/targets/openssl_csr/tests/validate.yml index 818b988d08..755b2d301e 100644 --- a/test/integration/targets/openssl_csr/tests/validate.yml +++ b/test/integration/targets/openssl_csr/tests/validate.yml @@ -25,6 +25,14 @@ - generate_csr_check_idempotent is not changed - generate_csr_check_idempotent_check is not changed +- name: Validate CSR without SAN (check mode, idempotency) + assert: + that: + - generate_csr_nosan_check is changed + - generate_csr_nosan is changed + - generate_csr_nosan_check_idempotent is not changed + - generate_csr_nosan_check_idempotent_check is not changed + - name: Validate CSR_KU_XKU (assert idempotency, change) assert: that: