From fed267df033bb762887cc4b164ed745ab3774f55 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 30 Oct 2019 21:36:36 +0100 Subject: [PATCH] openssl_csr and openssl_certificate: fix support for Ed25519 and Ed448 private keys (#63984) * Move X25519, X448, Ed25519 and Ed448 feature tests to module_utils. * Correctly sign with Ed25519 and Ed448 keys. * Fix public key comparison. Ed25519 and Ed448 do not have public_numbers(). * Add tests. * Add changelog. * Give better errors for cryptography 2.6.x and 2.7.x. * Test for new errors. * Forgot one. * Used wrong private key. * Use private key password for CA key. Add more stuff to its certificate. --- .../fragments/63984-openssl-ed25519-ed448.yml | 4 + lib/ansible/module_utils/crypto.py | 74 +++++++++- .../modules/crypto/openssl_certificate.py | 53 ++++--- lib/ansible/modules/crypto/openssl_csr.py | 35 +++-- .../modules/crypto/openssl_privatekey.py | 34 ++--- .../openssl_certificate/tasks/ownca.yml | 130 +++++++++++++++++- .../openssl_certificate/tasks/selfsigned.yml | 52 +++++++ .../tests/validate_ownca.yml | 38 ++++- .../tests/validate_selfsigned.yml | 26 +++- .../targets/openssl_csr/tasks/impl.yml | 38 +++++ .../targets/openssl_csr/tests/validate.yml | 22 +++ 11 files changed, 441 insertions(+), 65 deletions(-) create mode 100644 changelogs/fragments/63984-openssl-ed25519-ed448.yml diff --git a/changelogs/fragments/63984-openssl-ed25519-ed448.yml b/changelogs/fragments/63984-openssl-ed25519-ed448.yml new file mode 100644 index 00000000000..ee7ad5505ad --- /dev/null +++ b/changelogs/fragments/63984-openssl-ed25519-ed448.yml @@ -0,0 +1,4 @@ +bugfixes: +- "openssl_certificate and openssl_csr - fix Ed25519 and Ed448 private key support for ``cryptography`` backend. + This probably needs at least cryptography 2.8, since older versions have problems with signing certificates + or CSRs with such keys. (https://github.com/ansible/ansible/issues/59039, PR https://github.com/ansible/ansible/pull/63984)" diff --git a/lib/ansible/module_utils/crypto.py b/lib/ansible/module_utils/crypto.py index 88774c676af..df5eea096ca 100644 --- a/lib/ansible/module_utils/crypto.py +++ b/lib/ansible/module_utils/crypto.py @@ -47,6 +47,7 @@ try: from cryptography.hazmat.backends import default_backend as cryptography_backend from cryptography.hazmat.primitives.serialization import load_pem_private_key from cryptography.hazmat.primitives import hashes + from cryptography.hazmat.primitives import serialization import ipaddress # Older versions of cryptography (< 2.1) do not have __hash__ functions for @@ -79,9 +80,42 @@ try: # https://github.com/pyca/cryptography/commit/d1b5681f6db2bde7a14625538bd7907b08dfb486 x509.RFC822Name.__hash__ = simple_hash x509.UniformResourceIdentifier.__hash__ = simple_hash + + # Test whether we have support for X25519, X448, Ed25519 and/or Ed448 + try: + import cryptography.hazmat.primitives.asymmetric.x25519 + CRYPTOGRAPHY_HAS_X25519 = True + try: + cryptography.hazmat.primitives.asymmetric.x25519.X25519PrivateKey.private_bytes + CRYPTOGRAPHY_HAS_X25519_FULL = True + except AttributeError: + CRYPTOGRAPHY_HAS_X25519_FULL = False + except ImportError: + CRYPTOGRAPHY_HAS_X25519 = False + CRYPTOGRAPHY_HAS_X25519_FULL = False + try: + import cryptography.hazmat.primitives.asymmetric.x448 + CRYPTOGRAPHY_HAS_X448 = True + except ImportError: + CRYPTOGRAPHY_HAS_X448 = False + try: + import cryptography.hazmat.primitives.asymmetric.ed25519 + CRYPTOGRAPHY_HAS_ED25519 = True + except ImportError: + CRYPTOGRAPHY_HAS_ED25519 = False + try: + import cryptography.hazmat.primitives.asymmetric.ed448 + CRYPTOGRAPHY_HAS_ED448 = True + except ImportError: + CRYPTOGRAPHY_HAS_ED448 = False + except ImportError: # Error handled in the calling module. - pass + CRYPTOGRAPHY_HAS_X25519 = False + CRYPTOGRAPHY_HAS_X25519_FULL = False + CRYPTOGRAPHY_HAS_X448 = False + CRYPTOGRAPHY_HAS_ED25519 = False + CRYPTOGRAPHY_HAS_ED448 = False import abc @@ -1929,3 +1963,41 @@ def identify_private_key_format(content): except UnicodeDecodeError: pass return 'raw' + + +def cryptography_key_needs_digest_for_signing(key): + '''Tests whether the given private key requires a digest algorithm for signing. + + Ed25519 and Ed448 keys do not; they need None to be passed as the digest algorithm. + ''' + if CRYPTOGRAPHY_HAS_ED25519 and isinstance(key, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey): + return False + if CRYPTOGRAPHY_HAS_ED448 and isinstance(key, cryptography.hazmat.primitives.asymmetric.ed448.Ed448PrivateKey): + return False + return True + + +def cryptography_compare_public_keys(key1, key2): + '''Tests whether two public keys are the same. + + Needs special logic for Ed25519 and Ed448 keys, since they do not have public_numbers(). + ''' + if CRYPTOGRAPHY_HAS_ED25519: + a = isinstance(key1, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey) + b = isinstance(key2, cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PublicKey) + if a or b: + if not a or not b: + return False + a = key1.public_bytes(serialization.Encoding.Raw, serialization.PublicFormat.Raw) + b = key2.public_bytes(serialization.Encoding.Raw, serialization.PublicFormat.Raw) + return a == b + if CRYPTOGRAPHY_HAS_ED448: + a = isinstance(key1, cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey) + b = isinstance(key2, cryptography.hazmat.primitives.asymmetric.ed448.Ed448PublicKey) + if a or b: + if not a or not b: + return False + a = key1.public_bytes(serialization.Encoding.Raw, serialization.PublicFormat.Raw) + b = key2.public_bytes(serialization.Encoding.Raw, serialization.PublicFormat.Raw) + return a == b + return key1.public_numbers() == key2.public_numbers() diff --git a/lib/ansible/modules/crypto/openssl_certificate.py b/lib/ansible/modules/crypto/openssl_certificate.py index b46ff58d871..5096759a2f7 100644 --- a/lib/ansible/modules/crypto/openssl_certificate.py +++ b/lib/ansible/modules/crypto/openssl_certificate.py @@ -939,7 +939,7 @@ class Certificate(crypto_utils.OpenSSLObject): except OpenSSL.SSL.Error: return False elif self.backend == 'cryptography': - return self.cert.public_key().public_numbers() == self.privatekey.public_key().public_numbers() + return crypto_utils.cryptography_compare_public_keys(self.cert.public_key(), self.privatekey.public_key()) def _validate_csr(self): if self.backend == 'pyopenssl': @@ -966,7 +966,7 @@ class Certificate(crypto_utils.OpenSSLObject): # Verify that CSR is signed by certificate's private key if not self.csr.is_signature_valid: return False - if self.csr.public_key().public_numbers() != self.cert.public_key().public_numbers(): + if not crypto_utils.cryptography_compare_public_keys(self.csr.public_key(), self.cert.public_key()): return False # Check subject if self.csr.subject != self.cert.subject: @@ -1106,10 +1106,13 @@ class SelfSignedCertificateCryptography(Certificate): except crypto_utils.OpenSSLBadPassphraseError as exc: module.fail_json(msg=to_native(exc)) - if self.digest is None: - raise CertificateError( - 'The digest %s is not supported with the cryptography backend' % module.params['selfsigned_digest'] - ) + if crypto_utils.cryptography_key_needs_digest_for_signing(self.privatekey): + if self.digest is None: + raise CertificateError( + 'The digest %s is not supported with the cryptography backend' % module.params['selfsigned_digest'] + ) + else: + self.digest = None def generate(self, module): if not os.path.exists(self.privatekey_path): @@ -1144,10 +1147,15 @@ class SelfSignedCertificateCryptography(Certificate): except ValueError as e: raise CertificateError(str(e)) - certificate = cert_builder.sign( - private_key=self.privatekey, algorithm=self.digest, - backend=default_backend() - ) + try: + certificate = cert_builder.sign( + private_key=self.privatekey, algorithm=self.digest, + backend=default_backend() + ) + except TypeError as e: + if str(e) == 'Algorithm must be a registered hash algorithm.' and self.digest is None: + module.fail_json(msg='Signing with Ed25519 and Ed448 keys requires cryptography 2.8 or newer.') + raise self.cert = certificate @@ -1318,6 +1326,14 @@ class OwnCACertificateCryptography(Certificate): except crypto_utils.OpenSSLBadPassphraseError as exc: module.fail_json(msg=str(exc)) + if crypto_utils.cryptography_key_needs_digest_for_signing(self.ca_private_key): + if self.digest is None: + raise CertificateError( + 'The digest %s is not supported with the cryptography backend' % module.params['ownca_digest'] + ) + else: + self.digest = None + def generate(self, module): if not os.path.exists(self.ca_cert_path): @@ -1372,10 +1388,15 @@ class OwnCACertificateCryptography(Certificate): critical=False ) - certificate = cert_builder.sign( - private_key=self.ca_private_key, algorithm=self.digest, - backend=default_backend() - ) + try: + certificate = cert_builder.sign( + private_key=self.ca_private_key, algorithm=self.digest, + backend=default_backend() + ) + except TypeError as e: + if str(e) == 'Algorithm must be a registered hash algorithm.' and self.digest is None: + module.fail_json(msg='Signing with Ed25519 and Ed448 keys requires cryptography 2.8 or newer.') + raise self.cert = certificate @@ -1856,12 +1877,12 @@ class AssertOnlyCertificateCryptography(AssertOnlyCertificateBase): super(AssertOnlyCertificateCryptography, self).__init__(module, 'cryptography') def _validate_privatekey(self): - return self.cert.public_key().public_numbers() == self.privatekey.public_key().public_numbers() + return crypto_utils.cryptography_compare_public_keys(self.cert.public_key(), self.privatekey.public_key()) def _validate_csr_signature(self): if not self.csr.is_signature_valid: return False - return self.csr.public_key().public_numbers() == self.cert.public_key().public_numbers() + return crypto_utils.cryptography_compare_public_keys(self.csr.public_key(), self.cert.public_key()) def _validate_csr_subject(self): return self.csr.subject == self.cert.subject diff --git a/lib/ansible/modules/crypto/openssl_csr.py b/lib/ansible/modules/crypto/openssl_csr.py index 07488117cab..9655c953fc9 100644 --- a/lib/ansible/modules/crypto/openssl_csr.py +++ b/lib/ansible/modules/crypto/openssl_csr.py @@ -758,6 +758,7 @@ class CertificateSigningRequestCryptography(CertificateSigningRequestBase): def __init__(self, module): super(CertificateSigningRequestCryptography, self).__init__(module) self.cryptography_backend = cryptography.hazmat.backends.default_backend() + self.module = module if self.version != 1: module.warn('The cryptography backend only supports version 1. (The only valid value according to RFC 2986.)') @@ -816,20 +817,26 @@ class CertificateSigningRequestCryptography(CertificateSigningRequestBase): ) digest = None - if self.digest == 'sha256': - digest = cryptography.hazmat.primitives.hashes.SHA256() - elif self.digest == 'sha384': - digest = cryptography.hazmat.primitives.hashes.SHA384() - elif self.digest == 'sha512': - digest = cryptography.hazmat.primitives.hashes.SHA512() - elif self.digest == 'sha1': - digest = cryptography.hazmat.primitives.hashes.SHA1() - elif self.digest == 'md5': - digest = cryptography.hazmat.primitives.hashes.MD5() - # FIXME - else: - raise CertificateSigningRequestError('Unsupported digest "{0}"'.format(self.digest)) - self.request = csr.sign(self.privatekey, digest, self.cryptography_backend) + if crypto_utils.cryptography_key_needs_digest_for_signing(self.privatekey): + if self.digest == 'sha256': + digest = cryptography.hazmat.primitives.hashes.SHA256() + elif self.digest == 'sha384': + digest = cryptography.hazmat.primitives.hashes.SHA384() + elif self.digest == 'sha512': + digest = cryptography.hazmat.primitives.hashes.SHA512() + elif self.digest == 'sha1': + digest = cryptography.hazmat.primitives.hashes.SHA1() + elif self.digest == 'md5': + digest = cryptography.hazmat.primitives.hashes.MD5() + # FIXME + else: + raise CertificateSigningRequestError('Unsupported digest "{0}"'.format(self.digest)) + try: + self.request = csr.sign(self.privatekey, digest, self.cryptography_backend) + except TypeError as e: + if str(e) == 'Algorithm must be a registered hash algorithm.' and digest is None: + self.module.fail_json(msg='Signing with Ed25519 and Ed448 keys requires cryptography 2.8 or newer.') + raise return self.request.public_bytes(cryptography.hazmat.primitives.serialization.Encoding.PEM) diff --git a/lib/ansible/modules/crypto/openssl_privatekey.py b/lib/ansible/modules/crypto/openssl_privatekey.py index 06d03f54155..ba3d334b6c3 100644 --- a/lib/ansible/modules/crypto/openssl_privatekey.py +++ b/lib/ansible/modules/crypto/openssl_privatekey.py @@ -269,32 +269,14 @@ except ImportError: CRYPTOGRAPHY_FOUND = False else: CRYPTOGRAPHY_FOUND = True - try: - import cryptography.hazmat.primitives.asymmetric.x25519 - CRYPTOGRAPHY_HAS_X25519 = True - try: - cryptography.hazmat.primitives.asymmetric.x25519.X25519PrivateKey.private_bytes - CRYPTOGRAPHY_HAS_X25519_FULL = True - except AttributeError: - CRYPTOGRAPHY_HAS_X25519_FULL = False - except ImportError: - CRYPTOGRAPHY_HAS_X25519 = False - CRYPTOGRAPHY_HAS_X25519_FULL = False - try: - import cryptography.hazmat.primitives.asymmetric.x448 - CRYPTOGRAPHY_HAS_X448 = True - except ImportError: - CRYPTOGRAPHY_HAS_X448 = False - try: - import cryptography.hazmat.primitives.asymmetric.ed25519 - CRYPTOGRAPHY_HAS_ED25519 = True - except ImportError: - CRYPTOGRAPHY_HAS_ED25519 = False - try: - import cryptography.hazmat.primitives.asymmetric.ed448 - CRYPTOGRAPHY_HAS_ED448 = True - except ImportError: - CRYPTOGRAPHY_HAS_ED448 = False + +from ansible.module_utils.crypto import ( + CRYPTOGRAPHY_HAS_X25519, + CRYPTOGRAPHY_HAS_X25519_FULL, + CRYPTOGRAPHY_HAS_X448, + CRYPTOGRAPHY_HAS_ED25519, + CRYPTOGRAPHY_HAS_ED448, +) from ansible.module_utils import crypto as crypto_utils from ansible.module_utils._text import to_native, to_bytes diff --git a/test/integration/targets/openssl_certificate/tasks/ownca.yml b/test/integration/targets/openssl_certificate/tasks/ownca.yml index 8bd9829cdb1..99214b44075 100644 --- a/test/integration/targets/openssl_certificate/tasks/ownca.yml +++ b/test/integration/targets/openssl_certificate/tasks/ownca.yml @@ -64,7 +64,7 @@ select_crypto_backend: '{{ select_crypto_backend }}' register: ownca_certificate -- name: (OwnCA, {{select_crypto_backend}}) Generate ownca certificate +- name: (OwnCA, {{select_crypto_backend}}) Generate ownca certificate (idempotent) openssl_certificate: path: '{{ output_dir }}/ownca_cert.pem' csr_path: '{{ output_dir }}/csr.csr' @@ -438,4 +438,132 @@ when: select_crypto_backend != 'pyopenssl' register: ownca_authority_key_identifier_5 +- name: (OwnCA, {{select_crypto_backend}}) Ed25519 and Ed448 tests (for cryptography >= 2.6) + block: + - name: (OwnCA, {{select_crypto_backend}}) Generate privatekeys + openssl_privatekey: + path: '{{ output_dir }}/privatekey_{{ item }}.pem' + type: '{{ item }}' + loop: + - Ed25519 + - Ed448 + + - name: (OwnCA, {{select_crypto_backend}}) Generate CSR + openssl_csr: + path: '{{ output_dir }}/csr_{{ item }}.csr' + privatekey_path: '{{ output_dir }}/privatekey_{{ item }}.pem' + subject: + commonName: www.ansible.com + select_crypto_backend: '{{ select_crypto_backend }}' + loop: + - Ed25519 + - Ed448 + ignore_errors: yes + + - name: (OwnCA, {{select_crypto_backend}}) Generate ownca certificate + openssl_certificate: + path: '{{ output_dir }}/ownca_cert_{{ item }}.pem' + csr_path: '{{ output_dir }}/csr_{{ item }}.csr' + ownca_path: '{{ output_dir }}/ca_cert.pem' + ownca_privatekey_path: '{{ output_dir }}/ca_privatekey.pem' + provider: ownca + ownca_digest: sha256 + select_crypto_backend: '{{ select_crypto_backend }}' + loop: + - Ed25519 + - Ed448 + register: ownca_certificate_ed25519_ed448 + ignore_errors: yes + + - name: (OwnCA, {{select_crypto_backend}}) Generate ownca certificate (idempotent) + openssl_certificate: + path: '{{ output_dir }}/ownca_cert_{{ item }}.pem' + csr_path: '{{ output_dir }}/csr_{{ item }}.csr' + ownca_path: '{{ output_dir }}/ca_cert.pem' + ownca_privatekey_path: '{{ output_dir }}/ca_privatekey.pem' + provider: ownca + ownca_digest: sha256 + select_crypto_backend: '{{ select_crypto_backend }}' + loop: + - Ed25519 + - Ed448 + register: ownca_certificate_ed25519_ed448_idempotence + ignore_errors: yes + + - name: (OwnCA, {{select_crypto_backend}}) Generate CA privatekey + openssl_privatekey: + path: '{{ output_dir }}/ca_privatekey_{{ item }}.pem' + type: '{{ item }}' + cipher: auto + passphrase: Test123 + loop: + - Ed25519 + - Ed448 + + - name: (OwnCA, {{select_crypto_backend}}) Generate CA CSR + openssl_csr: + path: '{{ output_dir }}/ca_csr_{{ item }}.csr' + privatekey_path: '{{ output_dir }}/ca_privatekey_{{ item }}.pem' + privatekey_passphrase: Test123 + subject: + commonName: Example CA + useCommonNameForSAN: no + basic_constraints: + - 'CA:TRUE' + basic_constraints_critical: yes + key_usage: + - cRLSign + - keyCertSign + loop: + - Ed25519 + - Ed448 + ignore_errors: yes + + - name: (OwnCA, {{select_crypto_backend}}) Generate selfsigned CA certificate + openssl_certificate: + path: '{{ output_dir }}/ca_cert_{{ item }}.pem' + csr_path: '{{ output_dir }}/ca_csr_{{ item }}.csr' + privatekey_path: '{{ output_dir }}/ca_privatekey_{{ item }}.pem' + privatekey_passphrase: Test123 + provider: selfsigned + select_crypto_backend: '{{ select_crypto_backend }}' + loop: + - Ed25519 + - Ed448 + ignore_errors: yes + + - name: (OwnCA, {{select_crypto_backend}}) Generate ownca certificate + openssl_certificate: + path: '{{ output_dir }}/ownca_cert_{{ item }}_2.pem' + csr_path: '{{ output_dir }}/csr.csr' + ownca_path: '{{ output_dir }}/ca_cert_{{ item }}.pem' + ownca_privatekey_path: '{{ output_dir }}/ca_privatekey_{{ item }}.pem' + ownca_privatekey_passphrase: Test123 + provider: ownca + ownca_digest: sha256 + select_crypto_backend: '{{ select_crypto_backend }}' + loop: + - Ed25519 + - Ed448 + register: ownca_certificate_ed25519_ed448_2 + ignore_errors: yes + + - name: (OwnCA, {{select_crypto_backend}}) Generate ownca certificate (idempotent) + openssl_certificate: + path: '{{ output_dir }}/ownca_cert_{{ item }}_2.pem' + csr_path: '{{ output_dir }}/csr.csr' + ownca_path: '{{ output_dir }}/ca_cert_{{ item }}.pem' + ownca_privatekey_path: '{{ output_dir }}/ca_privatekey_{{ item }}.pem' + ownca_privatekey_passphrase: Test123 + provider: ownca + ownca_digest: sha256 + select_crypto_backend: '{{ select_crypto_backend }}' + loop: + - Ed25519 + - Ed448 + register: ownca_certificate_ed25519_ed448_2_idempotence + ignore_errors: yes + + when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.6', '>=') + - 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 74ba851511f..c370bede7d9 100644 --- a/test/integration/targets/openssl_certificate/tasks/selfsigned.yml +++ b/test/integration/targets/openssl_certificate/tasks/selfsigned.yml @@ -368,4 +368,56 @@ when: select_crypto_backend != 'pyopenssl' register: selfsigned_subject_key_identifier_5 +- name: (Selfsigned, {{select_crypto_backend}}) Ed25519 and Ed448 tests (for cryptography >= 2.6) + block: + - name: (Selfsigned, {{select_crypto_backend}}) Generate privatekeys + openssl_privatekey: + path: '{{ output_dir }}/privatekey_{{ item }}.pem' + type: '{{ item }}' + loop: + - Ed25519 + - Ed448 + + - name: (Selfsigned, {{select_crypto_backend}}) Generate CSR + openssl_csr: + path: '{{ output_dir }}/csr_{{ item }}.csr' + privatekey_path: '{{ output_dir }}/privatekey_{{ item }}.pem' + subject: + commonName: www.ansible.com + select_crypto_backend: '{{ select_crypto_backend }}' + loop: + - Ed25519 + - Ed448 + ignore_errors: yes + + - name: (Selfsigned, {{select_crypto_backend}}) Generate selfsigned certificate + openssl_certificate: + path: '{{ output_dir }}/cert_{{ item }}.pem' + csr_path: '{{ output_dir }}/csr_{{ item }}.csr' + privatekey_path: '{{ output_dir }}/privatekey_{{ item }}.pem' + provider: selfsigned + selfsigned_digest: sha256 + select_crypto_backend: '{{ select_crypto_backend }}' + loop: + - Ed25519 + - Ed448 + register: selfsigned_certificate_ed25519_ed448 + ignore_errors: yes + + - name: (Selfsigned, {{select_crypto_backend}}) Generate selfsigned certificate - idempotency + openssl_certificate: + path: '{{ output_dir }}/cert_{{ item }}.pem' + csr_path: '{{ output_dir }}/csr_{{ item }}.csr' + privatekey_path: '{{ output_dir }}/privatekey_{{ item }}.pem' + provider: selfsigned + selfsigned_digest: sha256 + select_crypto_backend: '{{ select_crypto_backend }}' + loop: + - Ed25519 + - Ed448 + register: selfsigned_certificate_ed25519_ed448_idempotence + ignore_errors: yes + + when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.6', '>=') + - 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 a8c6114034b..72375c741b8 100644 --- a/test/integration/targets/openssl_certificate/tests/validate_ownca.yml +++ b/test/integration/targets/openssl_certificate/tests/validate_ownca.yml @@ -102,12 +102,12 @@ - passphrase_error_3 is failed - "'assphrase' in passphrase_error_3.msg or 'assword' in passphrase_error_3.msg or 'serializ' in passphrase_error_3.msg" -- name: Verify that broken certificate will be regenerated +- name: (OwnCA validation, {{select_crypto_backend}})Verify that broken certificate will be regenerated assert: that: - ownca_broken is changed -- name: Check backup +- name: (OwnCA validation, {{select_crypto_backend}}) Check backup assert: that: - ownca_backup_1 is changed @@ -121,7 +121,7 @@ - ownca_backup_5 is not changed - ownca_backup_5.backup_file is undefined -- name: Check create subject key identifier +- name: (OwnCA validation, {{select_crypto_backend}}) Check create subject key identifier assert: that: - ownca_subject_key_identifier_1 is changed @@ -131,7 +131,7 @@ - ownca_subject_key_identifier_5 is changed when: select_crypto_backend != 'pyopenssl' -- name: Check create authority key identifier +- name: (OwnCA validation, {{select_crypto_backend}}) Check create authority key identifier assert: that: - ownca_authority_key_identifier_1 is changed @@ -140,3 +140,33 @@ - ownca_authority_key_identifier_4 is not changed - ownca_authority_key_identifier_5 is changed when: select_crypto_backend != 'pyopenssl' + +- name: (OwnCA validation, {{select_crypto_backend}}) Verify Ed25519 and Ed448 tests (for cryptography >= 2.6, < 2.8) + assert: + that: + - ownca_certificate_ed25519_ed448.results[0] is failed + - ownca_certificate_ed25519_ed448.results[1] is failed + - ownca_certificate_ed25519_ed448_idempotence.results[0] is failed + - ownca_certificate_ed25519_ed448_idempotence.results[1] is failed + - ownca_certificate_ed25519_ed448_2.results[0] is failed + - ownca_certificate_ed25519_ed448_2.results[1] is failed + - ownca_certificate_ed25519_ed448_2_idempotence.results[0] is failed + - ownca_certificate_ed25519_ed448_2_idempotence.results[1] is failed + when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.6', '>=') and cryptography_version.stdout is version('2.8', '<') + +- name: (OwnCA validation, {{select_crypto_backend}}) Verify Ed25519 and Ed448 tests (for cryptography >= 2.8) + assert: + that: + - ownca_certificate_ed25519_ed448 is succeeded + - ownca_certificate_ed25519_ed448.results[0] is changed + - ownca_certificate_ed25519_ed448.results[1] is changed + - ownca_certificate_ed25519_ed448_idempotence is succeeded + - ownca_certificate_ed25519_ed448_idempotence.results[0] is not changed + - ownca_certificate_ed25519_ed448_idempotence.results[1] is not changed + - ownca_certificate_ed25519_ed448_2 is succeeded + - ownca_certificate_ed25519_ed448_2.results[0] is changed + - ownca_certificate_ed25519_ed448_2.results[1] is changed + - ownca_certificate_ed25519_ed448_2_idempotence is succeeded + - ownca_certificate_ed25519_ed448_2_idempotence.results[0] is not changed + - ownca_certificate_ed25519_ed448_2_idempotence.results[1] is not changed + when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.8', '>=') diff --git a/test/integration/targets/openssl_certificate/tests/validate_selfsigned.yml b/test/integration/targets/openssl_certificate/tests/validate_selfsigned.yml index 432a2d8d089..5143b01eb80 100644 --- a/test/integration/targets/openssl_certificate/tests/validate_selfsigned.yml +++ b/test/integration/targets/openssl_certificate/tests/validate_selfsigned.yml @@ -108,12 +108,12 @@ - passphrase_error_3 is failed - "'assphrase' in passphrase_error_3.msg or 'assword' in passphrase_error_3.msg or 'serializ' in passphrase_error_3.msg" -- name: Verify that broken certificate will be regenerated +- name: (Selfsigned validation, {{select_crypto_backend}}) Verify that broken certificate will be regenerated assert: that: - selfsigned_broken is changed -- name: Check backup +- name: (Selfsigned validation, {{select_crypto_backend}}) Check backup assert: that: - selfsigned_backup_1 is changed @@ -127,7 +127,7 @@ - selfsigned_backup_5 is not changed - selfsigned_backup_5.backup_file is undefined -- name: Check create subject key identifier +- name: (Selfsigned validation, {{select_crypto_backend}}) Check create subject key identifier assert: that: - selfsigned_subject_key_identifier_1 is changed @@ -136,3 +136,23 @@ - selfsigned_subject_key_identifier_4 is not changed - selfsigned_subject_key_identifier_5 is changed when: select_crypto_backend != 'pyopenssl' + +- name: (Selfsigned validation, {{select_crypto_backend}}) Verify Ed25519 and Ed448 tests (for cryptography >= 2.6, < 2.8) + assert: + that: + - selfsigned_certificate_ed25519_ed448.results[0] is failed + - selfsigned_certificate_ed25519_ed448.results[1] is failed + - selfsigned_certificate_ed25519_ed448_idempotence.results[0] is failed + - selfsigned_certificate_ed25519_ed448_idempotence.results[1] is failed + when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.6', '>=') and cryptography_version.stdout is version('2.8', '<') + +- name: (Selfsigned validation, {{select_crypto_backend}}) Verify Ed25519 and Ed448 tests (for cryptography >= 2.8) + assert: + that: + - selfsigned_certificate_ed25519_ed448 is succeeded + - selfsigned_certificate_ed25519_ed448.results[0] is changed + - selfsigned_certificate_ed25519_ed448.results[1] is changed + - selfsigned_certificate_ed25519_ed448_idempotence is succeeded + - selfsigned_certificate_ed25519_ed448_idempotence.results[0] is not changed + - selfsigned_certificate_ed25519_ed448_idempotence.results[1] is not changed + when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.8', '>=') diff --git a/test/integration/targets/openssl_csr/tasks/impl.yml b/test/integration/targets/openssl_csr/tasks/impl.yml index fe6f4db94e7..20f8d516bcb 100644 --- a/test/integration/targets/openssl_csr/tasks/impl.yml +++ b/test/integration/targets/openssl_csr/tasks/impl.yml @@ -716,3 +716,41 @@ - "DNS:ca.example.org" - "IP:1.2.3.4" register: everything_3 + +- name: Ed25519 and Ed448 tests (for cryptography >= 2.6) + block: + - name: Generate privatekeys + openssl_privatekey: + path: '{{ output_dir }}/privatekey_{{ item }}.pem' + type: '{{ item }}' + loop: + - Ed25519 + - Ed448 + + - name: Generate CSR + openssl_csr: + path: '{{ output_dir }}/csr_{{ item }}.csr' + privatekey_path: '{{ output_dir }}/privatekey_{{ item }}.pem' + subject: + commonName: www.ansible.com + select_crypto_backend: '{{ select_crypto_backend }}' + loop: + - Ed25519 + - Ed448 + register: generate_csr_ed25519_ed448 + ignore_errors: yes + + - name: Generate CSR (idempotent) + openssl_csr: + path: '{{ output_dir }}/csr_{{ item }}.csr' + privatekey_path: '{{ output_dir }}/privatekey_{{ item }}.pem' + subject: + commonName: www.ansible.com + select_crypto_backend: '{{ select_crypto_backend }}' + loop: + - Ed25519 + - Ed448 + register: generate_csr_ed25519_ed448_idempotent + ignore_errors: yes + + when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.6', '>=') diff --git a/test/integration/targets/openssl_csr/tests/validate.yml b/test/integration/targets/openssl_csr/tests/validate.yml index 9b3aae113af..28458ba8984 100644 --- a/test/integration/targets/openssl_csr/tests/validate.yml +++ b/test/integration/targets/openssl_csr/tests/validate.yml @@ -175,3 +175,25 @@ - everything_1 is changed - everything_2 is not changed - everything_3 is not changed + +- name: Verify Ed25519 and Ed448 tests (for cryptography >= 2.6, < 2.8) + assert: + that: + - generate_csr_ed25519_ed448.results[0] is failed + - generate_csr_ed25519_ed448.results[1] is failed + - generate_csr_ed25519_ed448.results[0].msg == 'Signing with Ed25519 and Ed448 keys requires cryptography 2.8 or newer.' + - generate_csr_ed25519_ed448.results[1].msg == 'Signing with Ed25519 and Ed448 keys requires cryptography 2.8 or newer.' + - generate_csr_ed25519_ed448_idempotent.results[0] is failed + - generate_csr_ed25519_ed448_idempotent.results[1] is failed + when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.6', '>=') and cryptography_version.stdout is version('2.8', '<') + +- name: Verify Ed25519 and Ed448 tests (for cryptography >= 2.8) + assert: + that: + - generate_csr_ed25519_ed448 is succeeded + - generate_csr_ed25519_ed448.results[0] is changed + - generate_csr_ed25519_ed448.results[1] is changed + - generate_csr_ed25519_ed448_idempotent is succeeded + - generate_csr_ed25519_ed448_idempotent.results[0] is not changed + - generate_csr_ed25519_ed448_idempotent.results[1] is not changed + when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.8', '>=')