From b61b113fb9e3fcfcb25f4a8aaabad618e3209ce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc?= Date: Thu, 21 Jun 2018 09:11:00 +0200 Subject: [PATCH] new provider: ownca (#35840) --- .../modules/crypto/openssl_certificate.py | 194 +++++++++++++++++- .../openssl_certificate/tasks/main.yml | 117 +---------- .../openssl_certificate/tasks/ownca.yml | 116 +++++++++++ .../openssl_certificate/tasks/selfsigned.yml | 117 +++++++++++ .../tests/validate_ownca.yml | 48 +++++ .../{validate.yml => validate_selfsigned.yml} | 0 6 files changed, 473 insertions(+), 119 deletions(-) create mode 100644 test/integration/targets/openssl_certificate/tasks/ownca.yml create mode 100644 test/integration/targets/openssl_certificate/tasks/selfsigned.yml create mode 100644 test/integration/targets/openssl_certificate/tests/validate_ownca.yml rename test/integration/targets/openssl_certificate/tests/{validate.yml => validate_selfsigned.yml} (100%) diff --git a/lib/ansible/modules/crypto/openssl_certificate.py b/lib/ansible/modules/crypto/openssl_certificate.py index 7492024e34f..18ac31b742f 100644 --- a/lib/ansible/modules/crypto/openssl_certificate.py +++ b/lib/ansible/modules/crypto/openssl_certificate.py @@ -24,9 +24,11 @@ version_added: "2.4" short_description: Generate and/or check OpenSSL certificates description: - "This module allows one to (re)generate OpenSSL certificates. It implements a notion - of provider (ie. C(selfsigned), C(acme), C(assertonly)) for your certificate. + of provider (ie. C(selfsigned), C(ownca), C(acme), C(assertonly)) for your certificate. The 'assertonly' provider is intended for use cases where one is only interested in checking properties of a supplied certificate. + The 'ownca' provider is intended for generate OpenSSL certificate signed with your own + CA (Certificate Authority) certificate (self-signed certificate). Many properties that can be specified in this module are for validation of an existing or newly generated certificate. The proper place to specify them, if you want to receive a certificate with these properties is a CSR (Certificate Signing Request). @@ -48,7 +50,7 @@ options: provider: required: true - choices: [ 'selfsigned', 'assertonly', 'acme' ] + choices: [ 'selfsigned', 'ownca', 'assertonly', 'acme' ] description: - Name of the provider to use to generate/retrieve the OpenSSL certificate. The C(assertonly) provider will not generate files and fail if the certificate file is missing. @@ -94,6 +96,45 @@ options: If this value is not specified, certificate will stop being valid 10 years from now. aliases: [ selfsigned_notAfter ] + ownca_path: + description: + - Remote absolute path of the CA (Certificate Authority) certificate. + version_added: "2.7" + + ownca_privatekey_path: + description: + - Path to the CA (Certificate Authority) private key to use when signing the certificate. + version_added: "2.7" + + ownca_privatekey_passphrase: + description: + - The passphrase for the I(ownca_privatekey_path). + version_added: "2.7" + + ownca_digest: + default: "sha256" + description: + - Digest algorithm to be used for the C(ownca) certificate. + version_added: "2.7" + + ownca_version: + default: 3 + description: + - Version of the C(ownca) certificate. Nowadays it should almost always be C(3). + version_added: "2.7" + + ownca_not_before: + description: + - The timestamp at which the certificate starts being valid. The timestamp is formatted as an ASN.1 TIME. + If this value is not specified, certificate will start being valid from now. + version_added: "2.7" + + ownca_not_after: + description: + - The timestamp at which the certificate stops being valid. The timestamp is formatted as an ASN.1 TIME. + If this value is not specified, certificate will stop being valid 10 years from now. + version_added: "2.7" + acme_accountkey_path: description: - Path to the accountkey for the C(acme) provider @@ -209,6 +250,9 @@ extends_documentation_fragment: files notes: - All ASN.1 TIME values should be specified following the YYYYMMDDHHMMSSZ pattern. Date specified should be UTC. Minutes and seconds are mandatory. + - For security reason, when you use C(ownca) provider, you should NOT run M(openssl_certificate) on + a target machine, but on a dedicated CA machine. It is recommended not to store the CA private key + on the target machine. Once signed, the certificate can be moved to the target machine. ''' @@ -220,6 +264,14 @@ EXAMPLES = ''' csr_path: /etc/ssl/csr/ansible.com.csr provider: selfsigned +- name: Generate an OpenSSL certificate signed with your own CA certificate + openssl_certificate: + path: /etc/ssl/crt/ansible.com.crt + csr_path: /etc/ssl/csr/ansible.com.csr + ownca_path: /etc/ssl/crt/ansible_CA.crt + ownca_privatekey_path: /etc/ssl/private/ansible_CA.pem + provider: ownca + - name: Generate a Let's Encrypt Certificate openssl_certificate: path: /etc/ssl/crt/ansible.com.crt @@ -381,6 +433,7 @@ class Certificate(crypto_utils.OpenSSLObject): self.csr_path = module.params['csr_path'] self.cert = None self.privatekey = None + self.csr = None self.module = module def check(self, module, perms_required=True): @@ -399,6 +452,24 @@ class Certificate(crypto_utils.OpenSSLObject): except OpenSSL.SSL.Error: return False + def _validate_csr(): + try: + self.csr.verify(self.cert.get_pubkey()) + except OpenSSL.crypto.Error: + return False + if self.csr.get_subject() != self.cert.get_subject(): + return False + csr_extensions = self.csr.get_extensions() + cert_extension_count = self.cert.get_extension_count() + if len(csr_extensions) != cert_extension_count: + return False + for extension_number in range(0, cert_extension_count): + cert_extension = self.cert.get_extension(extension_number) + csr_extension = filter(lambda extension: extension.get_short_name() == cert_extension.get_short_name(), csr_extensions) + if cert_extension.get_data() != list(csr_extension)[0].get_data(): + return False + return True + if not state_and_perms: return False @@ -411,6 +482,11 @@ class Certificate(crypto_utils.OpenSSLObject): ) return _validate_privatekey() + if self.csr_path: + self.csr = crypto_utils.load_certificate_request(self.csr_path) + if not _validate_csr(): + return False + return True @@ -502,6 +578,105 @@ class SelfSignedCertificate(Certificate): return result +class OwnCACertificate(Certificate): + """Generate the own CA certificate.""" + + def __init__(self, module): + super(OwnCACertificate, self).__init__(module) + self.notBefore = module.params['ownca_not_before'] + self.notAfter = module.params['ownca_not_after'] + self.digest = module.params['ownca_digest'] + self.version = module.params['ownca_version'] + self.serial_number = randint(1000, 99999) + self.ca_cert_path = module.params['ownca_path'] + self.ca_privatekey_path = module.params['ownca_privatekey_path'] + self.ca_privatekey_passphrase = module.params['ownca_privatekey_passphrase'] + self.csr = crypto_utils.load_certificate_request(self.csr_path) + self.ca_cert = crypto_utils.load_certificate(self.ca_cert_path) + self.ca_privatekey = crypto_utils.load_privatekey( + self.ca_privatekey_path, self.ca_privatekey_passphrase + ) + + def generate(self, module): + + if not os.path.exists(self.ca_cert_path): + raise CertificateError( + 'The CA certificate %s does not exist' % self.ca_cert_path + ) + + if not os.path.exists(self.ca_privatekey_path): + raise CertificateError( + 'The CA private key %s does not exist' % self.ca_privatekey_path + ) + + if not os.path.exists(self.csr_path): + raise CertificateError( + 'The certificate signing request file %s does not exist' % self.csr_path + ) + + if not self.check(module, perms_required=False) or self.force: + cert = crypto.X509() + cert.set_serial_number(self.serial_number) + if self.notBefore: + cert.set_notBefore(self.notBefore.encode()) + else: + cert.gmtime_adj_notBefore(0) + if self.notAfter: + cert.set_notAfter(self.notAfter.encode()) + else: + # If no NotAfter specified, expire in + # 10 years. 315360000 is 10 years in seconds. + cert.gmtime_adj_notAfter(315360000) + cert.set_subject(self.csr.get_subject()) + cert.set_issuer(self.ca_cert.get_subject()) + cert.set_version(self.version - 1) + cert.set_pubkey(self.csr.get_pubkey()) + cert.add_extensions(self.csr.get_extensions()) + + cert.sign(self.ca_privatekey, self.digest) + self.cert = cert + + try: + with open(self.path, 'wb') as cert_file: + cert_file.write(crypto.dump_certificate(crypto.FILETYPE_PEM, self.cert)) + except EnvironmentError as exc: + raise CertificateError(exc) + + self.changed = True + + file_args = module.load_file_common_arguments(module.params) + if module.set_fs_attributes_if_different(file_args, False): + self.changed = True + + def dump(self, check_mode=False): + + result = { + 'changed': self.changed, + 'filename': self.path, + 'privatekey': self.privatekey_path, + 'csr': self.csr_path, + 'ca_cert': self.ca_cert_path, + 'ca_privatekey': self.ca_privatekey_path + } + + if check_mode: + now = datetime.datetime.utcnow() + ten = now.replace(now.year + 10) + result.update({ + 'notBefore': self.notBefore if self.notBefore else now.strftime("%Y%m%d%H%M%SZ"), + 'notAfter': self.notAfter if self.notAfter else ten.strftime("%Y%m%d%H%M%SZ"), + 'serial_number': self.serial_number, + }) + else: + result.update({ + 'notBefore': self.cert.get_notBefore(), + 'notAfter': self.cert.get_notAfter(), + 'serial_number': self.cert.get_serial_number(), + }) + + return result + + class AssertOnlyCertificate(Certificate): """validate the supplied certificate.""" @@ -805,7 +980,7 @@ def main(): argument_spec=dict( state=dict(type='str', choices=['present', 'absent'], default='present'), path=dict(type='path', required=True), - provider=dict(type='str', choices=['selfsigned', 'assertonly', 'acme']), + provider=dict(type='str', choices=['selfsigned', 'ownca', 'assertonly', 'acme']), force=dict(type='bool', default=False,), csr_path=dict(type='path'), @@ -837,6 +1012,15 @@ def main(): selfsigned_notBefore=dict(type='str', aliases=['selfsigned_not_before']), selfsigned_notAfter=dict(type='str', aliases=['selfsigned_not_after']), + # provider: ownca + ownca_path=dict(type='path'), + ownca_privatekey_path=dict(type='path'), + ownca_privatekey_passphrase=dict(type='path', no_log=True), + ownca_digest=dict(type='str', default='sha256'), + ownca_version=dict(type='int', default='3'), + ownca_not_before=dict(type='str'), + ownca_not_after=dict(type='str'), + # provider: acme acme_accountkey_path=dict(type='path'), acme_challenge_path=dict(type='path'), @@ -848,7 +1032,7 @@ def main(): if not pyopenssl_found: module.fail_json(msg='The python pyOpenSSL library is required') - if module.params['provider'] in ['selfsigned', 'assertonly']: + if module.params['provider'] in ['selfsigned', 'ownca', 'assertonly']: try: getattr(crypto.X509Req, 'get_extensions') except AttributeError: @@ -867,6 +1051,8 @@ def main(): certificate = SelfSignedCertificate(module) elif provider == 'acme': certificate = AcmeCertificate(module) + elif provider == 'ownca': + certificate = OwnCACertificate(module) else: certificate = AssertOnlyCertificate(module) diff --git a/test/integration/targets/openssl_certificate/tasks/main.yml b/test/integration/targets/openssl_certificate/tasks/main.yml index c8b4cc60f60..a452f23495e 100644 --- a/test/integration/targets/openssl_certificate/tasks/main.yml +++ b/test/integration/targets/openssl_certificate/tasks/main.yml @@ -1,120 +1,7 @@ - block: - - name: Generate privatekey - openssl_privatekey: - path: '{{ output_dir }}/privatekey.pem' - - name: Generate CSR - openssl_csr: - path: '{{ output_dir }}/csr.csr' - privatekey_path: '{{ output_dir }}/privatekey.pem' - subject: - commonName: www.example.com + - import_tasks: selfsigned.yml - - name: Generate selfsigned certificate - openssl_certificate: - path: '{{ output_dir }}/cert.pem' - csr_path: '{{ output_dir }}/csr.csr' - privatekey_path: '{{ output_dir }}/privatekey.pem' - provider: selfsigned - selfsigned_digest: sha256 - register: selfsigned_certificate - - - name: Generate selfsigned certificate - openssl_certificate: - path: '{{ output_dir }}/cert.pem' - csr_path: '{{ output_dir }}/csr.csr' - privatekey_path: '{{ output_dir }}/privatekey.pem' - provider: selfsigned - selfsigned_digest: sha256 - register: selfsigned_certificate_idempotence - - - name: Generate selfsigned certificate (check mode) - openssl_certificate: - path: '{{ output_dir }}/cert.pem' - csr_path: '{{ output_dir }}/csr.csr' - privatekey_path: '{{ output_dir }}/privatekey.pem' - provider: selfsigned - selfsigned_digest: sha256 - check_mode: yes - - - name: Check selfsigned certificate - openssl_certificate: - path: '{{ output_dir }}/cert.pem' - privatekey_path: '{{ output_dir }}/privatekey.pem' - provider: assertonly - has_expired: False - version: 3 - signature_algorithms: - - sha256WithRSAEncryption - - sha256WithECDSAEncryption - subject: - commonName: www.example.com - - - name: Generate selfsigned v2 certificate - openssl_certificate: - path: '{{ output_dir }}/cert_v2.pem' - csr_path: '{{ output_dir }}/csr.csr' - privatekey_path: '{{ output_dir }}/privatekey.pem' - provider: selfsigned - selfsigned_digest: sha256 - selfsigned_version: 2 - - - name: Generate privatekey2 - openssl_privatekey: - path: '{{ output_dir }}/privatekey2.pem' - - - name: Generate CSR2 - openssl_csr: - subject: - CN: www.example.com - C: US - ST: California - L: Los Angeles - O: ACME Inc. - OU: - - Roadrunner pest control - - Pyrotechnics - path: '{{ output_dir }}/csr2.csr' - privatekey_path: '{{ output_dir }}/privatekey2.pem' - keyUsage: - - digitalSignature - extendedKeyUsage: - - ipsecUser - - biometricInfo - - - name: Generate selfsigned certificate2 - openssl_certificate: - path: '{{ output_dir }}/cert2.pem' - csr_path: '{{ output_dir }}/csr2.csr' - privatekey_path: '{{ output_dir }}/privatekey2.pem' - provider: selfsigned - selfsigned_digest: sha256 - - - name: Check selfsigned certificate2 - openssl_certificate: - path: '{{ output_dir }}/cert2.pem' - privatekey_path: '{{ output_dir }}/privatekey2.pem' - provider: assertonly - has_expired: False - version: 3 - signature_algorithms: - - sha256WithRSAEncryption - - sha256WithECDSAEncryption - subject: - commonName: www.example.com - C: US - ST: California - L: Los Angeles - O: ACME Inc. - OU: - - Roadrunner pest control - - Pyrotechnics - keyUsage: - - digitalSignature - extendedKeyUsage: - - ipsecUser - - biometricInfo - - - import_tasks: ../tests/validate.yml + - import_tasks: ownca.yml when: pyopenssl_version.stdout is version('0.15', '>=') diff --git a/test/integration/targets/openssl_certificate/tasks/ownca.yml b/test/integration/targets/openssl_certificate/tasks/ownca.yml new file mode 100644 index 00000000000..6ee075a3bd9 --- /dev/null +++ b/test/integration/targets/openssl_certificate/tasks/ownca.yml @@ -0,0 +1,116 @@ +- name: Generate CA privatekey + openssl_privatekey: + path: '{{ output_dir }}/ca_privatekey.pem' + +- name: Generate CA CSR + openssl_csr: + path: '{{ output_dir }}/ca_csr.csr' + privatekey_path: '{{ output_dir }}/ca_privatekey.pem' + subject: + commonName: Example CA + +- name: Generate selfsigned CA certificate + openssl_certificate: + path: '{{ output_dir }}/ca_cert.pem' + csr_path: '{{ output_dir }}/ca_csr.csr' + privatekey_path: '{{ output_dir }}/ca_privatekey.pem' + provider: selfsigned + selfsigned_digest: sha256 + +- name: Generate ownca certificate + openssl_certificate: + path: '{{ output_dir }}/ownca_cert.pem' + csr_path: '{{ output_dir }}/csr.csr' + privatekey_path: '{{ output_dir }}/privatekey.pem' + ownca_path: '{{ output_dir }}/ca_cert.pem' + ownca_privatekey_path: '{{ output_dir }}/ca_privatekey.pem' + provider: ownca + ownca_digest: sha256 + register: ownca_certificate + +- name: Generate ownca certificate + openssl_certificate: + path: '{{ output_dir }}/ownca_cert.pem' + csr_path: '{{ output_dir }}/csr.csr' + privatekey_path: '{{ output_dir }}/privatekey.pem' + ownca_path: '{{ output_dir }}/ca_cert.pem' + ownca_privatekey_path: '{{ output_dir }}/ca_privatekey.pem' + provider: ownca + ownca_digest: sha256 + register: ownca_certificate_idempotence + +- name: Generate ownca certificate (check mode) + openssl_certificate: + path: '{{ output_dir }}/ownca_cert.pem' + csr_path: '{{ output_dir }}/csr.csr' + privatekey_path: '{{ output_dir }}/privatekey.pem' + ownca_path: '{{ output_dir }}/ca_cert.pem' + ownca_privatekey_path: '{{ output_dir }}/ca_privatekey.pem' + provider: ownca + ownca_digest: sha256 + check_mode: yes + +- name: Check ownca certificate + openssl_certificate: + path: '{{ output_dir }}/ownca_cert.pem' + privatekey_path: '{{ output_dir }}/privatekey.pem' + provider: assertonly + has_expired: False + version: 3 + signature_algorithms: + - sha256WithRSAEncryption + - sha256WithECDSAEncryption + subject: + commonName: www.example.com + issuer: + commonName: Example CA + +- name: Generate ownca v2 certificate + openssl_certificate: + path: '{{ output_dir }}/ownca_cert_v2.pem' + csr_path: '{{ output_dir }}/csr.csr' + privatekey_path: '{{ output_dir }}/privatekey.pem' + ownca_path: '{{ output_dir }}/ca_cert.pem' + ownca_privatekey_path: '{{ output_dir }}/ca_privatekey.pem' + provider: ownca + ownca_digest: sha256 + ownca_version: 2 + +- name: Generate ownca certificate2 + openssl_certificate: + path: '{{ output_dir }}/ownca_cert2.pem' + csr_path: '{{ output_dir }}/csr2.csr' + privatekey_path: '{{ output_dir }}/privatekey2.pem' + ownca_path: '{{ output_dir }}/ca_cert.pem' + ownca_privatekey_path: '{{ output_dir }}/ca_privatekey.pem' + provider: ownca + ownca_digest: sha256 + +- name: Check ownca certificate2 + openssl_certificate: + path: '{{ output_dir }}/ownca_cert2.pem' + privatekey_path: '{{ output_dir }}/privatekey2.pem' + provider: assertonly + has_expired: False + version: 3 + signature_algorithms: + - sha256WithRSAEncryption + - sha256WithECDSAEncryption + subject: + commonName: www.example.com + C: US + ST: California + L: Los Angeles + O: ACME Inc. + OU: + - Roadrunner pest control + - Pyrotechnics + keyUsage: + - digitalSignature + extendedKeyUsage: + - ipsecUser + - biometricInfo + issuer: + commonName: Example CA + +- 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 new file mode 100644 index 00000000000..82b290dbe0f --- /dev/null +++ b/test/integration/targets/openssl_certificate/tasks/selfsigned.yml @@ -0,0 +1,117 @@ +- name: Generate privatekey + openssl_privatekey: + path: '{{ output_dir }}/privatekey.pem' + +- name: Generate CSR + openssl_csr: + path: '{{ output_dir }}/csr.csr' + privatekey_path: '{{ output_dir }}/privatekey.pem' + subject: + commonName: www.example.com + +- name: Generate selfsigned certificate + openssl_certificate: + path: '{{ output_dir }}/cert.pem' + csr_path: '{{ output_dir }}/csr.csr' + privatekey_path: '{{ output_dir }}/privatekey.pem' + provider: selfsigned + selfsigned_digest: sha256 + register: selfsigned_certificate + +- name: Generate selfsigned certificate + openssl_certificate: + path: '{{ output_dir }}/cert.pem' + csr_path: '{{ output_dir }}/csr.csr' + privatekey_path: '{{ output_dir }}/privatekey.pem' + provider: selfsigned + selfsigned_digest: sha256 + register: selfsigned_certificate_idempotence + +- name: Generate selfsigned certificate (check mode) + openssl_certificate: + path: '{{ output_dir }}/cert.pem' + csr_path: '{{ output_dir }}/csr.csr' + privatekey_path: '{{ output_dir }}/privatekey.pem' + provider: selfsigned + selfsigned_digest: sha256 + check_mode: yes + +- name: Check selfsigned certificate + openssl_certificate: + path: '{{ output_dir }}/cert.pem' + privatekey_path: '{{ output_dir }}/privatekey.pem' + provider: assertonly + has_expired: False + version: 3 + signature_algorithms: + - sha256WithRSAEncryption + - sha256WithECDSAEncryption + subject: + commonName: www.example.com + +- name: Generate selfsigned v2 certificate + openssl_certificate: + path: '{{ output_dir }}/cert_v2.pem' + csr_path: '{{ output_dir }}/csr.csr' + privatekey_path: '{{ output_dir }}/privatekey.pem' + provider: selfsigned + selfsigned_digest: sha256 + selfsigned_version: 2 + +- name: Generate privatekey2 + openssl_privatekey: + path: '{{ output_dir }}/privatekey2.pem' + +- name: Generate CSR2 + openssl_csr: + subject: + CN: www.example.com + C: US + ST: California + L: Los Angeles + O: ACME Inc. + OU: + - Roadrunner pest control + - Pyrotechnics + path: '{{ output_dir }}/csr2.csr' + privatekey_path: '{{ output_dir }}/privatekey2.pem' + keyUsage: + - digitalSignature + extendedKeyUsage: + - ipsecUser + - biometricInfo + +- name: Generate selfsigned certificate2 + openssl_certificate: + path: '{{ output_dir }}/cert2.pem' + csr_path: '{{ output_dir }}/csr2.csr' + privatekey_path: '{{ output_dir }}/privatekey2.pem' + provider: selfsigned + selfsigned_digest: sha256 + +- name: Check selfsigned certificate2 + openssl_certificate: + path: '{{ output_dir }}/cert2.pem' + privatekey_path: '{{ output_dir }}/privatekey2.pem' + provider: assertonly + has_expired: False + version: 3 + signature_algorithms: + - sha256WithRSAEncryption + - sha256WithECDSAEncryption + subject: + commonName: www.example.com + C: US + ST: California + L: Los Angeles + O: ACME Inc. + OU: + - Roadrunner pest control + - Pyrotechnics + keyUsage: + - digitalSignature + extendedKeyUsage: + - ipsecUser + - biometricInfo + +- 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 new file mode 100644 index 00000000000..5066d80f356 --- /dev/null +++ b/test/integration/targets/openssl_certificate/tests/validate_ownca.yml @@ -0,0 +1,48 @@ +- name: Validate ownca certificate (test - verify CA) + shell: 'openssl verify -CAfile {{ output_dir }}/ca_cert.pem {{ output_dir }}/ownca_cert.pem | sed "s/.*: \(.*\)/\1/g"' + register: ownca_verify_ca + +- name: Validate ownca certificate (test - ownca certificate modulus) + shell: 'openssl x509 -noout -modulus -in {{ output_dir }}/ownca_cert.pem' + register: ownca_cert_modulus + +- name: Validate ownca certificate (test - ownca issuer value) + shell: 'openssl x509 -noout -in {{ output_dir}}/ownca_cert.pem -text | grep "Issuer" | sed "s/.*: \(.*\)/\1/g"' + register: ownca_cert_issuer + +- name: Validate ownca certificate (test - ownca certficate version == default == 3) + shell: 'openssl x509 -noout -in {{ output_dir}}/ownca_cert.pem -text | grep "Version" | sed "s/.*: \(.*\) .*/\1/g"' + register: ownca_cert_version + +- name: Validate ownca certificate (assert) + assert: + that: + - ownca_verify_ca.stdout == 'OK' + - ownca_cert_modulus.stdout == privatekey_modulus.stdout + - ownca_cert_version.stdout == '3' + - ownca_cert_issuer.stdout == 'CN=Example CA' + +- name: Validate ownca certificate idempotence + assert: + that: + - ownca_certificate.serial_number == ownca_certificate_idempotence.serial_number + - ownca_certificate.notBefore == ownca_certificate_idempotence.notBefore + - ownca_certificate.notAfter == ownca_certificate_idempotence.notAfter + +- name: Validate ownca certificate v2 (test - ownca certificate version == 2) + shell: 'openssl x509 -noout -in {{ output_dir}}/ownca_cert_v2.pem -text | grep "Version" | sed "s/.*: \(.*\) .*/\1/g"' + register: ownca_cert_v2_version + +- name: Validate ownca certificate version 2 (assert) + assert: + that: + - ownca_cert_v2_version.stdout == '2' + +- name: Validate ownca certificate2 (test - ownca certificate modulus) + shell: 'openssl x509 -noout -modulus -in {{ output_dir }}/ownca_cert2.pem' + register: ownca_cert2_modulus + +- name: Validate ownca certificate2 (assert) + assert: + that: + - ownca_cert2_modulus.stdout == privatekey2_modulus.stdout diff --git a/test/integration/targets/openssl_certificate/tests/validate.yml b/test/integration/targets/openssl_certificate/tests/validate_selfsigned.yml similarity index 100% rename from test/integration/targets/openssl_certificate/tests/validate.yml rename to test/integration/targets/openssl_certificate/tests/validate_selfsigned.yml