diff options
author | Felix Fontein <felix@fontein.de> | 2019-03-04 16:34:14 +0100 |
---|---|---|
committer | Toshio Kuratomi <a.badger@gmail.com> | 2019-03-04 07:34:14 -0800 |
commit | 597db1dc287f39329ff0e9689080e471a91726ec (patch) | |
tree | d388cdab30d602e7d465b545c22f63607b4c080f | |
parent | 59beb460d82103ace61f9a3b64f1ec964739e4fb (diff) | |
download | ansible-597db1dc287f39329ff0e9689080e471a91726ec.tar.gz |
[2.7] openssl_certificate, fixed has_expired to check the cert expiration date (#53203)
* Type error in openssl_certificate (#47508)
* Fixed #47505: Type error in openssl_certificate
* Use to_bytes instead of str.encode in SelfSignedCertificate. Updates #47508
* Use to_bytes instead of str.encode in OwnCACertificate
* Added integration tests for openssl_certificate: selfsigned_not_before/after and ownca_not_before/after
(cherry picked from commit 5b1c68579d3e8ecc28a6b85383a85c1f279da63c)
* openssl_certificate, fixed has_expired to check the cert expiration date (#53168)
(cherry picked from commit d5d92e4a70d87eda4cbdd160f6bb6459ee05cea7)
* Use fixed timestamp in past instead of relative time (relative times are a feature of devel).
* Add changelog for #47508.
9 files changed, 132 insertions, 12 deletions
diff --git a/changelogs/fragments/47508-openssl_certificate-fix-not-before-after.yml b/changelogs/fragments/47508-openssl_certificate-fix-not-before-after.yml new file mode 100644 index 0000000000..524c58b74b --- /dev/null +++ b/changelogs/fragments/47508-openssl_certificate-fix-not-before-after.yml @@ -0,0 +1,2 @@ +bugfixes: +- "openssl_certificate - fix Python 3 string/bytes problems for `notBefore`/`notAfter` for self-signed and ownCA providers." diff --git a/changelogs/fragments/openssl_certificate_fix_has_expired.yml b/changelogs/fragments/openssl_certificate_fix_has_expired.yml new file mode 100644 index 0000000000..b33b2da9d4 --- /dev/null +++ b/changelogs/fragments/openssl_certificate_fix_has_expired.yml @@ -0,0 +1,2 @@ +bugfixes: + - openssl_certificate - ``has_expired`` correctly checks if the certificate is expired or not diff --git a/lib/ansible/modules/crypto/openssl_certificate.py b/lib/ansible/modules/crypto/openssl_certificate.py index 32db6e4017..3db7405ea7 100644 --- a/lib/ansible/modules/crypto/openssl_certificate.py +++ b/lib/ansible/modules/crypto/openssl_certificate.py @@ -179,10 +179,11 @@ options: version_added: "2.5" has_expired: - default: False - type: bool description: - - Checks if the certificate is expired/not expired at the time the module is executed. + - Checks if the certificate is expired/not expired at the time the module is executed. This only applies to + the C(assertonly) provider. + type: bool + default: no version: description: @@ -521,11 +522,11 @@ class SelfSignedCertificate(Certificate): cert = crypto.X509() cert.set_serial_number(self.serial_number) if self.notBefore: - cert.set_notBefore(self.notBefore) + cert.set_notBefore(to_bytes(self.notBefore)) else: cert.gmtime_adj_notBefore(0) if self.notAfter: - cert.set_notAfter(self.notAfter) + cert.set_notAfter(to_bytes(self.notAfter)) else: # If no NotAfter specified, expire in # 10 years. 315360000 is 10 years in seconds. @@ -618,11 +619,11 @@ class OwnCACertificate(Certificate): cert = crypto.X509() cert.set_serial_number(self.serial_number) if self.notBefore: - cert.set_notBefore(self.notBefore.encode()) + cert.set_notBefore(to_bytes(self.notBefore)) else: cert.gmtime_adj_notBefore(0) if self.notAfter: - cert.set_notAfter(self.notAfter.encode()) + cert.set_notAfter(to_bytes(self.notAfter)) else: # If no NotAfter specified, expire in # 10 years. 315360000 is 10 years in seconds. @@ -763,11 +764,18 @@ class AssertOnlyCertificate(Certificate): ) def _validate_has_expired(): - if self.has_expired: - if self.has_expired != self.cert.has_expired(): - self.message.append( - 'Certificate expiration check failed (certificate expiration is %s, expected %s)' % (self.cert.has_expired(), self.has_expired) - ) + # The following 3 lines are the same as the current PyOpenSSL code for cert.has_expired(). + # Older version of PyOpenSSL have a buggy implementation, + # to avoid issues with those we added the code from a more recent release here. + + time_string = to_native(self.cert.get_notAfter()) + not_after = datetime.datetime.strptime(time_string, "%Y%m%d%H%M%SZ") + cert_expired = not_after < datetime.datetime.utcnow() + + if self.has_expired != cert_expired: + self.message.append( + 'Certificate expiration check failed (certificate expiration is %s, expected %s)' % (cert_expired, self.has_expired) + ) def _validate_version(): if self.version: diff --git a/test/integration/targets/openssl_certificate/tasks/expired.yml b/test/integration/targets/openssl_certificate/tasks/expired.yml new file mode 100644 index 0000000000..34ae359ee8 --- /dev/null +++ b/test/integration/targets/openssl_certificate/tasks/expired.yml @@ -0,0 +1,39 @@ +--- +- name: Generate privatekey + openssl_privatekey: + path: '{{ output_dir }}/has_expired_privatekey.pem' + +- name: Generate CSR + openssl_csr: + path: '{{ output_dir }}/has_expired_csr.csr' + privatekey_path: '{{ output_dir }}/has_expired_privatekey.pem' + subject: + commonName: www.example.com + +- name: Generate expired selfsigned certificate + openssl_certificate: + path: '{{ output_dir }}/has_expired_cert.pem' + csr_path: '{{ output_dir }}/has_expired_csr.csr' + privatekey_path: '{{ output_dir }}/has_expired_privatekey.pem' + provider: selfsigned + selfsigned_digest: sha256 + selfsigned_not_after: "20181231000000Z" + +- name: "Check task fails because cert is expired (has_expired: false)" + openssl_certificate: + provider: assertonly + path: "{{ output_dir }}/has_expired_cert.pem" + has_expired: false + ignore_errors: true + register: expired_cert_check + +- name: Ensure previous task failed + assert: + that: expired_cert_check is failed + +- name: "Check expired cert check is ignored (has_expired: true)" + openssl_certificate: + provider: assertonly + path: "{{ output_dir }}/has_expired_cert.pem" + has_expired: true + register: expired_cert_skip diff --git a/test/integration/targets/openssl_certificate/tasks/main.yml b/test/integration/targets/openssl_certificate/tasks/main.yml index a452f23495..1fdc1a674d 100644 --- a/test/integration/targets/openssl_certificate/tasks/main.yml +++ b/test/integration/targets/openssl_certificate/tasks/main.yml @@ -1,5 +1,7 @@ - block: + - import_tasks: expired.yml + - import_tasks: selfsigned.yml - import_tasks: ownca.yml diff --git a/test/integration/targets/openssl_certificate/tasks/ownca.yml b/test/integration/targets/openssl_certificate/tasks/ownca.yml index 9f7dbbff5c..63edbd2610 100644 --- a/test/integration/targets/openssl_certificate/tasks/ownca.yml +++ b/test/integration/targets/openssl_certificate/tasks/ownca.yml @@ -116,4 +116,15 @@ issuer: commonName: Example CA +- name: Create ownca certificate with notBefore and notAfter + openssl_certificate: + provider: ownca + ownca_not_before: 20181023133742Z + ownca_not_after: 20191023133742Z + path: "{{ output_dir }}/ownca_cert3.pem" + csr_path: "{{ output_dir }}/csr.csr" + privatekey_path: "{{ output_dir }}/privatekey3.pem" + ownca_path: '{{ output_dir }}/ca_cert.pem' + ownca_privatekey_path: '{{ output_dir }}/ca_privatekey.pem' + - import_tasks: ../tests/validate_ownca.yml diff --git a/test/integration/targets/openssl_certificate/tasks/selfsigned.yml b/test/integration/targets/openssl_certificate/tasks/selfsigned.yml index 82b290dbe0..b57a11f196 100644 --- a/test/integration/targets/openssl_certificate/tasks/selfsigned.yml +++ b/test/integration/targets/openssl_certificate/tasks/selfsigned.yml @@ -114,4 +114,24 @@ - ipsecUser - biometricInfo +- name: Create private key 3 + openssl_privatekey: + path: "{{ output_dir }}/privatekey3.pem" + +- name: Create CSR 3 + openssl_csr: + subject: + CN: www.example.com + privatekey_path: "{{ output_dir }}/privatekey3.pem" + path: "{{ output_dir }}/csr3.pem" + +- name: Create certificate3 with notBefore and notAfter + openssl_certificate: + provider: selfsigned + selfsigned_not_before: 20181023133742Z + selfsigned_not_after: 20191023133742Z + path: "{{ output_dir }}/cert3.pem" + csr_path: "{{ output_dir }}/csr3.pem" + privatekey_path: "{{ output_dir }}/privatekey3.pem" + - import_tasks: ../tests/validate_selfsigned.yml diff --git a/test/integration/targets/openssl_certificate/tests/validate_ownca.yml b/test/integration/targets/openssl_certificate/tests/validate_ownca.yml index 779452fb18..d54287ecd9 100644 --- a/test/integration/targets/openssl_certificate/tests/validate_ownca.yml +++ b/test/integration/targets/openssl_certificate/tests/validate_ownca.yml @@ -47,3 +47,21 @@ assert: that: - ownca_cert2_modulus.stdout == privatekey2_modulus.stdout + +- name: Validate owncal certificate3 (test - notBefore) + shell: 'openssl x509 -noout -in {{ output_dir }}/ownca_cert3.pem -text | grep "Not Before" | sed "s/.*: \(.*\) .*/\1/g"' + register: ownca_cert3_notBefore + +- name: Validate ownca certificate3 (test - notAfter) + shell: 'openssl x509 -noout -in {{ output_dir }}/ownca_cert3.pem -text | grep "Not After" | sed "s/.*: \(.*\) .*/\1/g"' + register: ownca_cert3_notAfter + +- name: Validate ownca certificate3 (assert - notBefore) + assert: + that: + - ownca_cert3_notBefore.stdout == 'Oct 23 13:37:42 2018' + +- name: Validate ownca certificate3 (assert - notAfter) + assert: + that: + - ownca_cert3_notAfter.stdout == 'Oct 23 13:37:42 2019' diff --git a/test/integration/targets/openssl_certificate/tests/validate_selfsigned.yml b/test/integration/targets/openssl_certificate/tests/validate_selfsigned.yml index de37106945..f98d6f191e 100644 --- a/test/integration/targets/openssl_certificate/tests/validate_selfsigned.yml +++ b/test/integration/targets/openssl_certificate/tests/validate_selfsigned.yml @@ -50,3 +50,21 @@ assert: that: - cert2_modulus.stdout == privatekey2_modulus.stdout + +- name: Validate certificate3 (test - notBefore) + shell: 'openssl x509 -noout -in {{ output_dir }}/cert3.pem -text | grep "Not Before" | sed "s/.*: \(.*\) .*/\1/g"' + register: cert3_notBefore + +- name: Validate certificate3 (test - notAfter) + shell: 'openssl x509 -noout -in {{ output_dir }}/cert3.pem -text | grep "Not After" | sed "s/.*: \(.*\) .*/\1/g"' + register: cert3_notAfter + +- name: Validate certificate3 (assert - notBefore) + assert: + that: + - cert3_notBefore.stdout == 'Oct 23 13:37:42 2018' + +- name: Validate certificate3 (assert - notAfter) + assert: + that: + - cert3_notAfter.stdout == 'Oct 23 13:37:42 2019' |