diff --git a/changelogs/fragments/51473-openssl_csr-idempotence.yaml b/changelogs/fragments/51473-openssl_csr-idempotence.yaml new file mode 100644 index 00000000000..ed636b4a8f6 --- /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 cba9e068122..32a21c22b5f 100644 --- a/lib/ansible/modules/crypto/openssl_csr.py +++ b/lib/ansible/modules/crypto/openssl_csr.py @@ -431,7 +431,7 @@ class CertificateSigningRequest(crypto_utils.OpenSSLObject): 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() 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] diff --git a/test/integration/targets/openssl_csr/tasks/main.yml b/test/integration/targets/openssl_csr/tasks/main.yml index 5c394ee503f..9cbe27058a0 100644 --- a/test/integration/targets/openssl_csr/tasks/main.yml +++ b/test/integration/targets/openssl_csr/tasks/main.yml @@ -37,6 +37,32 @@ 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' + 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' + register: generate_csr_nosan + + - name: Generate CSR without SAN (idempotent) + openssl_csr: + path: '{{ output_dir }}/csr-nosan.csr' + privatekey_path: '{{ output_dir }}/privatekey.pem' + 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' + 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 747a1b3c31a..68293b91e12 100644 --- a/test/integration/targets/openssl_csr/tests/validate.yml +++ b/test/integration/targets/openssl_csr/tests/validate.yml @@ -24,6 +24,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: