openssl_* modules: allow direct input and output for some files (#65400)

* Allow to return generated object.

* Use slurp module instead of file lookup + b64encode.

* Rename return_xxx_content -> return_content.
This commit is contained in:
Felix Fontein 2020-02-02 12:42:52 +01:00 committed by GitHub
parent 4d345813ea
commit d6fb9da8ed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 346 additions and 4 deletions

View file

@ -0,0 +1,7 @@
minor_changes:
- "openssl_certificate - allow to return the existing/generated certificate directly as ``certificate`` by setting ``return_content`` to ``yes``."
- "openssl_csr - allow to return the existing/generated CSR directly as ``csr`` by setting ``return_content`` to ``yes``."
- "openssl_dhparam - allow to return the existing/generated DH params directly as ``dhparams`` by setting ``return_content`` to ``yes``."
- "openssl_pkcs12 - allow to return the existing/generated PKCS#12 directly as ``pkcs12`` by setting ``return_content`` to ``yes``."
- "openssl_privatekey - allow to return the existing/generated private key directly as ``privatekey`` by setting ``return_content`` to ``yes``."
- "openssl_publickey - allow to return the existing/generated public key directly as ``publickey`` by setting ``return_content`` to ``yes``."

View file

@ -187,6 +187,26 @@ def get_fingerprint(path, passphrase=None, content=None):
return get_fingerprint_of_bytes(publickey)
def load_file_if_exists(path, module=None, ignore_errors=False):
try:
with open(path, 'rb') as f:
return f.read()
except EnvironmentError as exc:
if exc.errno == errno.ENOENT:
return None
if ignore_errors:
return None
if module is None:
raise
module.fail_json('Error while loading {0} - {1}'.format(path, str(exc)))
except Exception as exc:
if ignore_errors:
return None
if module is None:
raise
module.fail_json('Error while loading {0} - {1}'.format(path, str(exc)))
def load_privatekey(path, passphrase=None, check_passphrase=True, content=None, backend='pyopenssl'):
"""Load the specified OpenSSL private key.

View file

@ -590,6 +590,13 @@ options:
default: https://cloud.entrust.net/EntrustCloud/documentation/cms-api-2.1.0.yaml
version_added: "2.9"
return_content:
description:
- If set to C(yes), will return the (current or generated) certificate's content as I(certificate).
type: bool
default: no
version_added: "2.10"
extends_documentation_fragment: files
notes:
- All ASN.1 TIME values should be specified following the YYYYMMDDHHMMSSZ pattern.
@ -852,6 +859,11 @@ backup_file:
returned: changed and if I(backup) is C(yes)
type: str
sample: /path/to/www.ansible.com.crt.2019-03-09@11:22~
certificate:
description: The (current or generated) certificate's content.
returned: if I(state) is C(present) and I(return_content) is C(yes)
type: str
version_added: "2.10"
'''
@ -929,6 +941,7 @@ class Certificate(crypto_utils.OpenSSLObject):
self.csr = None
self.backend = backend
self.module = module
self.return_content = module.params['return_content']
# The following are default values which make sure check() works as
# before if providers do not explicitly change these properties.
@ -1115,6 +1128,8 @@ class CertificateAbsent(Certificate):
}
if self.backup_file:
result['backup_file'] = self.backup_file
if self.return_content:
result['certificate'] = None
return result
@ -1230,6 +1245,9 @@ class SelfSignedCertificateCryptography(Certificate):
}
if self.backup_file:
result['backup_file'] = self.backup_file
if self.return_content:
content = crypto_utils.load_file_if_exists(self.path, ignore_errors=True)
result['certificate'] = content.decode('utf-8') if content else None
if check_mode:
result.update({
@ -1327,6 +1345,9 @@ class SelfSignedCertificate(Certificate):
}
if self.backup_file:
result['backup_file'] = self.backup_file
if self.return_content:
content = crypto_utils.load_file_if_exists(self.path, ignore_errors=True)
result['certificate'] = content.decode('utf-8') if content else None
if check_mode:
result.update({
@ -1521,6 +1542,9 @@ class OwnCACertificateCryptography(Certificate):
}
if self.backup_file:
result['backup_file'] = self.backup_file
if self.return_content:
content = crypto_utils.load_file_if_exists(self.path, ignore_errors=True)
result['certificate'] = content.decode('utf-8') if content else None
if check_mode:
result.update({
@ -1644,6 +1668,9 @@ class OwnCACertificate(Certificate):
}
if self.backup_file:
result['backup_file'] = self.backup_file
if self.return_content:
content = crypto_utils.load_file_if_exists(self.path, ignore_errors=True)
result['certificate'] = content.decode('utf-8') if content else None
if check_mode:
result.update({
@ -1959,6 +1986,9 @@ class AssertOnlyCertificateBase(Certificate):
'privatekey': self.privatekey_path,
'csr': self.csr_path,
}
if self.return_content:
content = crypto_utils.load_file_if_exists(self.path, ignore_errors=True)
result['certificate'] = content.decode('utf-8') if content else None
return result
@ -2424,6 +2454,9 @@ class EntrustCertificate(Certificate):
if self.backup_file:
result['backup_file'] = self.backup_file
if self.return_content:
content = crypto_utils.load_file_if_exists(self.path, ignore_errors=True)
result['certificate'] = content.decode('utf-8') if content else None
result.update(self._get_cert_details())
@ -2511,6 +2544,9 @@ class AcmeCertificate(Certificate):
}
if self.backup_file:
result['backup_file'] = self.backup_file
if self.return_content:
content = crypto_utils.load_file_if_exists(self.path, ignore_errors=True)
result['certificate'] = content.decode('utf-8') if content else None
return result
@ -2526,6 +2562,7 @@ def main():
csr_content=dict(type='str'),
backup=dict(type='bool', default=False),
select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'cryptography', 'pyopenssl']),
return_content=dict(type='bool', default=False),
# General properties of a certificate
privatekey_path=dict(type='path'),

View file

@ -280,6 +280,12 @@ options:
I(authority_cert_issuer) and I(authority_cert_serial_number) is specified.
type: int
version_added: "2.9"
return_content:
description:
- If set to C(yes), will return the (current or generated) CSR's content as I(csr).
type: bool
default: no
version_added: "2.10"
extends_documentation_fragment:
- files
notes:
@ -419,6 +425,11 @@ backup_file:
returned: changed and if I(backup) is C(yes)
type: str
sample: /path/to/www.ansible.com.csr.2019-03-09@11:22~
csr:
description: The (current or generated) CSR's content.
returned: if I(state) is C(present) and I(return_content) is C(yes)
type: str
version_added: "2.10"
'''
import abc
@ -510,6 +521,8 @@ class CertificateSigningRequestBase(crypto_utils.OpenSSLObject):
self.authority_cert_serial_number = module.params['authority_cert_serial_number']
self.request = None
self.privatekey = None
self.csr_bytes = None
self.return_content = module.params['return_content']
if self.create_subject_key_identifier and self.subject_key_identifier is not None:
module.fail_json(msg='subject_key_identifier cannot be specified if create_subject_key_identifier is true')
@ -559,6 +572,8 @@ class CertificateSigningRequestBase(crypto_utils.OpenSSLObject):
result = self._generate_csr()
if self.backup:
self.backup_file = module.backup_local(self.path)
if self.return_content:
self.csr_bytes = result
crypto_utils.write_file(module, result)
self.changed = True
@ -606,6 +621,10 @@ class CertificateSigningRequestBase(crypto_utils.OpenSSLObject):
}
if self.backup_file:
result['backup_file'] = self.backup_file
if self.return_content:
if self.csr_bytes is None:
self.csr_bytes = crypto_utils.load_file_if_exists(self.path, ignore_errors=True)
result['csr'] = self.csr_bytes.decode('utf-8') if self.csr_bytes else None
return result
@ -1059,6 +1078,7 @@ def main():
authority_cert_issuer=dict(type='list', elements='str'),
authority_cert_serial_number=dict(type='int'),
select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'cryptography', 'pyopenssl']),
return_content=dict(type='bool', default=False),
),
required_together=[('authority_cert_issuer', 'authority_cert_serial_number')],
required_if=[('state', 'present', ['privatekey_path', 'privatekey_content'], True)],

View file

@ -70,6 +70,12 @@ options:
default: auto
choices: [ auto, cryptography, openssl ]
version_added: '2.10'
return_content:
description:
- If set to C(yes), will return the (current or generated) DH params' content as I(dhparams).
type: bool
default: no
version_added: "2.10"
extends_documentation_fragment:
- files
seealso:
@ -112,6 +118,11 @@ backup_file:
returned: changed and if I(backup) is C(yes)
type: str
sample: /path/to/dhparams.pem.2019-03-09@11:22~
dhparams:
description: The (current or generated) DH params' content.
returned: if I(state) is C(present) and I(return_content) is C(yes)
type: str
version_added: "2.10"
'''
import abc
@ -155,6 +166,7 @@ class DHParameterBase(object):
self.size = module.params['size']
self.force = module.params['force']
self.changed = False
self.return_content = module.params['return_content']
self.backup = module.params['backup']
self.backup_file = None
@ -218,6 +230,9 @@ class DHParameterBase(object):
}
if self.backup_file:
result['backup_file'] = self.backup_file
if self.return_content:
content = crypto_utils.load_file_if_exists(self.path, ignore_errors=True)
result['dhparams'] = content.decode('utf-8') if content else None
return result
@ -332,6 +347,7 @@ def main():
path=dict(type='path', required=True),
backup=dict(type='bool', default=False),
select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'cryptography', 'openssl']),
return_content=dict(type='bool', default=False),
),
supports_check_mode=True,
add_file_common_args=True,

View file

@ -95,6 +95,12 @@ options:
type: bool
default: no
version_added: "2.8"
return_content:
description:
- If set to C(yes), will return the (current or generated) PKCS#12's content as I(pkcs12).
type: bool
default: no
version_added: "2.10"
extends_documentation_fragment:
- files
seealso:
@ -169,8 +175,14 @@ backup_file:
returned: changed and if I(backup) is C(yes)
type: str
sample: /path/to/ansible.com.pem.2019-03-09@11:22~
pkcs12:
description: The (current or generated) PKCS#12's content Base64 encoded.
returned: if I(state) is C(present) and I(return_content) is C(yes)
type: str
version_added: "2.10"
'''
import base64
import stat
import os
import traceback
@ -212,6 +224,8 @@ class Pkcs(crypto_utils.OpenSSLObject):
self.pkcs12 = None
self.privatekey_passphrase = module.params['privatekey_passphrase']
self.privatekey_path = module.params['privatekey_path']
self.pkcs12_bytes = None
self.return_content = module.params['return_content']
self.src = module.params['src']
if module.params['mode'] is None:
@ -294,6 +308,10 @@ class Pkcs(crypto_utils.OpenSSLObject):
result['privatekey_path'] = self.privatekey_path
if self.backup_file:
result['backup_file'] = self.backup_file
if self.return_content:
if self.pkcs12_bytes is None:
self.pkcs12_bytes = crypto_utils.load_file_if_exists(self.path, ignore_errors=True)
result['pkcs12'] = base64.b64encode(self.pkcs12_bytes) if self.pkcs12_bytes else None
return result
@ -358,6 +376,8 @@ class Pkcs(crypto_utils.OpenSSLObject):
if self.backup:
self.backup_file = module.backup_local(self.path)
crypto_utils.write_file(module, content, mode)
if self.return_content:
self.pkcs12_bytes = content
def main():
@ -376,6 +396,7 @@ def main():
state=dict(type='str', default='present', choices=['absent', 'present']),
src=dict(type='path'),
backup=dict(type='bool', default=False),
return_content=dict(type='bool', default=False),
)
required_if = [

View file

@ -156,6 +156,14 @@ options:
type: bool
default: no
version_added: "2.8"
return_content:
description:
- If set to C(yes), will return the (current or generated) private key's content as I(privatekey).
- Note that especially if the private key is not encrypted, you have to make sure that the returned
value is treated appropriately and not accidentally written to logs etc.! Use with care!
type: bool
default: no
version_added: "2.10"
extends_documentation_fragment:
- files
seealso:
@ -232,9 +240,17 @@ backup_file:
returned: changed and if I(backup) is C(yes)
type: str
sample: /path/to/privatekey.pem.2019-03-09@11:22~
privatekey:
description:
- The (current or generated) private key's content.
- Will be Base64-encoded if the key is in raw format.
returned: if I(state) is C(present) and I(return_content) is C(yes)
type: str
version_added: "2.10"
'''
import abc
import base64
import os
import traceback
from distutils.version import LooseVersion
@ -303,6 +319,8 @@ class PrivateKeyBase(crypto_utils.OpenSSLObject):
self.fingerprint = {}
self.format = module.params['format']
self.format_mismatch = module.params['format_mismatch']
self.privatekey_bytes = None
self.return_content = module.params['return_content']
self.backup = module.params['backup']
self.backup_file = None
@ -333,6 +351,8 @@ class PrivateKeyBase(crypto_utils.OpenSSLObject):
self.backup_file = module.backup_local(self.path)
self._generate_private_key()
privatekey_data = self._get_private_key_data()
if self.return_content:
self.privatekey_bytes = privatekey_data
crypto_utils.write_file(module, privatekey_data, 0o600)
self.changed = True
elif not self.check(module, perms_required=False, ignore_conversion=False):
@ -340,6 +360,8 @@ class PrivateKeyBase(crypto_utils.OpenSSLObject):
if self.backup:
self.backup_file = module.backup_local(self.path)
privatekey_data = self._get_private_key_data()
if self.return_content:
self.privatekey_bytes = privatekey_data
crypto_utils.write_file(module, privatekey_data, 0o600)
self.changed = True
@ -393,6 +415,16 @@ class PrivateKeyBase(crypto_utils.OpenSSLObject):
}
if self.backup_file:
result['backup_file'] = self.backup_file
if self.return_content:
if self.privatekey_bytes is None:
self.privatekey_bytes = crypto_utils.load_file_if_exists(self.path, ignore_errors=True)
if self.privatekey_bytes:
if crypto_utils.identify_private_key_format(self.privatekey_bytes) == 'raw':
result['privatekey'] = base64.b64encode(self.privatekey_bytes)
else:
result['privatekey'] = self.privatekey_bytes.decode('utf-8')
else:
result['privatekey'] = None
return result
@ -744,6 +776,7 @@ def main():
format=dict(type='str', default='auto_ignore', choices=['pkcs1', 'pkcs8', 'raw', 'auto', 'auto_ignore']),
format_mismatch=dict(type='str', default='regenerate', choices=['regenerate', 'convert']),
select_crypto_backend=dict(type='str', choices=['auto', 'pyopenssl', 'cryptography'], default='auto'),
return_content=dict(type='bool', default=False),
),
supports_check_mode=True,
add_file_common_args=True,

View file

@ -90,6 +90,12 @@ options:
default: auto
choices: [ auto, cryptography, pyopenssl ]
version_added: "2.9"
return_content:
description:
- If set to C(yes), will return the (current or generated) public key's content as I(publickey).
type: bool
default: no
version_added: "2.10"
extends_documentation_fragment:
- files
seealso:
@ -171,6 +177,11 @@ backup_file:
returned: changed and if I(backup) is C(yes)
type: str
sample: /path/to/publickey.pem.2019-03-09@11:22~
publickey:
description: The (current or generated) public key's content.
returned: if I(state) is C(present) and I(return_content) is C(yes)
type: str
version_added: "2.10"
'''
import os
@ -229,6 +240,8 @@ class PublicKey(crypto_utils.OpenSSLObject):
self.privatekey_content = self.privatekey_content.encode('utf-8')
self.privatekey_passphrase = module.params['privatekey_passphrase']
self.privatekey = None
self.publickey_bytes = None
self.return_content = module.params['return_content']
self.fingerprint = {}
self.backend = backend
@ -270,6 +283,8 @@ class PublicKey(crypto_utils.OpenSSLObject):
if not self.check(module, perms_required=False) or self.force:
try:
publickey_content = self._create_publickey(module)
if self.return_content:
self.publickey_bytes = publickey_content
if self.backup:
self.backup_file = module.backup_local(self.path)
@ -302,6 +317,8 @@ class PublicKey(crypto_utils.OpenSSLObject):
try:
with open(self.path, 'rb') as public_key_fh:
publickey_content = public_key_fh.read()
if self.return_content:
self.publickey_bytes = publickey_content
if self.backend == 'cryptography':
if self.format == 'OpenSSH':
# Read and dump public key. Makes sure that the comment is stripped off.
@ -353,6 +370,10 @@ class PublicKey(crypto_utils.OpenSSLObject):
}
if self.backup_file:
result['backup_file'] = self.backup_file
if self.return_content:
if self.publickey_bytes is None:
self.publickey_bytes = crypto_utils.load_file_if_exists(self.path, ignore_errors=True)
result['publickey'] = self.publickey_bytes.decode('utf-8') if self.publickey_bytes else None
return result
@ -370,6 +391,7 @@ def main():
privatekey_passphrase=dict(type='str', no_log=True),
backup=dict(type='bool', default=False),
select_crypto_backend=dict(type='str', choices=['auto', 'pyopenssl', 'cryptography'], default='auto'),
return_content=dict(type='bool', default=False),
),
supports_check_mode=True,
add_file_common_args=True,

View file

@ -62,6 +62,7 @@
provider: ownca
ownca_digest: sha256
select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: ownca_certificate
- name: (OwnCA, {{select_crypto_backend}}) Generate ownca certificate (idempotent)
@ -74,6 +75,7 @@
provider: ownca
ownca_digest: sha256
select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: ownca_certificate_idempotence
- name: (OwnCA, {{select_crypto_backend}}) Generate ownca certificate (check mode)

View file

@ -27,6 +27,7 @@
path: "{{ output_dir }}/removal_cert.pem"
state: absent
select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: removal_1
- name: "(Removal, {{select_crypto_backend}}) Check that file is gone"
@ -48,3 +49,4 @@
- removal_1 is changed
- not removal_1_poststat.stat.exists
- removal_2 is not changed
- removal_1.certificate is none

View file

@ -32,6 +32,7 @@
provider: selfsigned
selfsigned_digest: sha256
select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: selfsigned_certificate
- name: (Selfsigned, {{select_crypto_backend}}) Generate selfsigned certificate - idempotency
@ -42,6 +43,7 @@
provider: selfsigned
selfsigned_digest: sha256
select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: selfsigned_certificate_idempotence
- name: (Selfsigned, {{select_crypto_backend}}) Generate selfsigned certificate (check mode)

View file

@ -31,6 +31,12 @@
- ownca_certificate.notBefore == ownca_certificate_idempotence.notBefore
- ownca_certificate.notAfter == ownca_certificate_idempotence.notAfter
- name: (OwnCA validation, {{select_crypto_backend}}) Validate ownca data return
assert:
that:
- ownca_certificate.certificate == lookup('file', output_dir ~ '/ownca_cert.pem', rstrip=False)
- ownca_certificate.certificate == ownca_certificate_idempotence.certificate
- block:
- name: (OwnCA validation, {{select_crypto_backend}}) 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"'

View file

@ -30,6 +30,12 @@
- selfsigned_certificate.notBefore == selfsigned_certificate_idempotence.notBefore
- selfsigned_certificate.notAfter == selfsigned_certificate_idempotence.notAfter
- name: (Selfsigned validation, {{select_crypto_backend}}) Validate data retrieval
assert:
that:
- selfsigned_certificate.certificate == lookup('file', output_dir ~ '/cert.pem', rstrip=False)
- selfsigned_certificate.certificate == selfsigned_certificate_idempotence.certificate
- name: Make sure that changes in CSR are detected even if private key is specified
assert:
that:

View file

@ -10,6 +10,7 @@
subject:
commonName: www.ansible.com
select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
check_mode: yes
register: generate_csr_check
@ -20,6 +21,7 @@
subject:
commonName: www.ansible.com
select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: generate_csr
- name: Generate CSR (idempotent)
@ -29,7 +31,8 @@
subject:
commonName: www.ansible.com
select_crypto_backend: '{{ select_crypto_backend }}'
register: generate_csr_check_idempotent
return_content: yes
register: generate_csr_idempotent
- name: Generate CSR (idempotent, check mode)
openssl_csr:
@ -38,8 +41,9 @@
subject:
commonName: www.ansible.com
select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
check_mode: yes
register: generate_csr_check_idempotent_check
register: generate_csr_idempotent_check
- name: Generate CSR without SAN (check mode)
openssl_csr:
@ -330,6 +334,7 @@
state: absent
backup: yes
select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: csr_backup_4
- name: Generate CSR (remove, idempotent)
openssl_csr:

View file

@ -22,8 +22,16 @@
that:
- generate_csr_check is changed
- generate_csr is changed
- generate_csr_check_idempotent is not changed
- generate_csr_check_idempotent_check is not changed
- generate_csr_idempotent is not changed
- generate_csr_idempotent_check is not changed
- name: Validate CSR (data retrieval)
assert:
that:
- generate_csr_check.csr is none
- generate_csr.csr == lookup('file', output_dir ~ '/csr.csr', rstrip=False)
- generate_csr.csr == generate_csr_idempotent.csr
- generate_csr.csr == generate_csr_idempotent_check.csr
- name: Validate CSR without SAN (check mode, idempotency)
assert:
@ -168,6 +176,7 @@
- csr_backup_4.backup_file is string
- csr_backup_5 is not changed
- csr_backup_5.backup_file is undefined
- csr_backup_4.csr is none
- name: Check CSR with everything
assert:

View file

@ -6,12 +6,15 @@
size: 768
path: '{{ output_dir }}/dh768.pem'
select_crypto_backend: "{{ select_crypto_backend }}"
return_content: yes
register: dhparam
- name: "[{{ select_crypto_backend }}] Don't regenerate parameters with no change"
openssl_dhparam:
size: 768
path: '{{ output_dir }}/dh768.pem'
select_crypto_backend: "{{ select_crypto_backend }}"
return_content: yes
register: dhparam_changed
- name: "[{{ select_crypto_backend }}] Generate parameters with size option"
@ -87,6 +90,7 @@
state: absent
backup: yes
select_crypto_backend: "{{ select_crypto_backend }}"
return_content: yes
register: dhparam_backup_4
- name: "[{{ select_crypto_backend }}] Generate params (remove, idempotent)"
openssl_dhparam:

View file

@ -31,6 +31,12 @@
- dhparam_changed_to_512 is changed
- dhparam_changed_force is changed
- name: "[{{ select_crypto_backend }}] Make sure correct values are returned"
assert:
that:
- dhparam.dhparams == lookup('file', output_dir ~ '/dh768.pem', rstrip=False)
- dhparam.dhparams == dhparam_changed.dhparams
- name: "[{{ select_crypto_backend }}] Verify that broken params will be regenerated"
assert:
that:
@ -49,3 +55,4 @@
- dhparam_backup_4.backup_file is string
- dhparam_backup_5 is not changed
- dhparam_backup_5.backup_file is undefined
- dhparam_backup_4.dhparams is none

View file

@ -51,6 +51,7 @@
privatekey_path: "{{ output_dir }}/ansible_pkey.pem"
certificate_path: "{{ output_dir }}/ansible.crt"
state: present
return_content: yes
register: p12_standard
- name: 'Generate PKCS#12 file again, idempotency'
@ -60,8 +61,20 @@
privatekey_path: "{{ output_dir }}/ansible_pkey.pem"
certificate_path: "{{ output_dir }}/ansible.crt"
state: present
return_content: yes
register: p12_standard_idempotency
- name: Read ansible.p12
slurp:
src: "{{ output_dir }}/ansible.p12"
register: ansible_p12_content
- name: 'Validate PKCS#12'
assert:
that:
- p12_standard.pkcs12 == ansible_p12_content.content
- p12_standard_idempotency.pkcs12 == p12_standard.pkcs12
- name: 'Generate PKCS#12 file (force)'
openssl_pkcs12:
path: "{{ output_dir }}/ansible.p12"
@ -216,6 +229,7 @@
path: "{{ output_dir }}/ansible_backup.p12"
state: absent
backup: yes
return_content: yes
register: p12_backup_4
- name: 'Generate PKCS#12 file (remove, idempotent)'
openssl_pkcs12:

View file

@ -1,3 +1,4 @@
---
- name: 'Validate PKCS#12'
command: "openssl pkcs12 -info -in {{ output_dir }}/ansible.p12 -nodes -passin pass:''"
register: p12
@ -53,3 +54,4 @@
- p12_backup_4.backup_file is string
- p12_backup_5 is not changed
- p12_backup_5.backup_file is undefined
- p12_backup_4.pkcs12 is none

View file

@ -3,6 +3,15 @@
openssl_privatekey:
path: '{{ output_dir }}/privatekey1.pem'
select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: privatekey1
- name: Generate privatekey1 - standard (idempotence)
openssl_privatekey:
path: '{{ output_dir }}/privatekey1.pem'
select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: privatekey1_idempotence
- name: Generate privatekey2 - size 2048
openssl_privatekey:
@ -27,6 +36,15 @@
state: absent
path: '{{ output_dir }}/privatekey4.pem'
select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: privatekey4_delete
- name: Delete privatekey4 - standard (idempotence)
openssl_privatekey:
state: absent
path: '{{ output_dir }}/privatekey4.pem'
select_crypto_backend: '{{ select_crypto_backend }}'
register: privatekey4_delete_idempotence
- name: Generate privatekey5 - standard - with passphrase
openssl_privatekey:
@ -381,30 +399,69 @@
type: X448
format: raw
select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: privatekey_fmt_2_step_3
- name: Read privatekey_fmt_2.pem
slurp:
src: "{{ output_dir }}/privatekey_fmt_2.pem"
register: content
- name: Generate privatekey_fmt_2 - verify that returned content is base64 encoded
assert:
that:
- privatekey_fmt_2_step_3.privatekey == content.content
- name: Generate privatekey_fmt_2 - raw format (idempotent)
openssl_privatekey:
path: '{{ output_dir }}/privatekey_fmt_2.pem'
type: X448
format: raw
select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: privatekey_fmt_2_step_4
- name: Read privatekey_fmt_2.pem
slurp:
src: "{{ output_dir }}/privatekey_fmt_2.pem"
register: content
- name: Generate privatekey_fmt_2 - verify that returned content is base64 encoded
assert:
that:
- privatekey_fmt_2_step_4.privatekey == content.content
- name: Generate privatekey_fmt_2 - auto format (ignore)
openssl_privatekey:
path: '{{ output_dir }}/privatekey_fmt_2.pem'
type: X448
format: auto_ignore
select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: privatekey_fmt_2_step_5
- name: Read privatekey_fmt_2.pem
slurp:
src: "{{ output_dir }}/privatekey_fmt_2.pem"
register: content
- name: Generate privatekey_fmt_2 - verify that returned content is base64 encoded
assert:
that:
- privatekey_fmt_2_step_5.privatekey == content.content
- name: Generate privatekey_fmt_2 - auto format (no ignore)
openssl_privatekey:
path: '{{ output_dir }}/privatekey_fmt_2.pem'
type: X448
format: auto
select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: privatekey_fmt_2_step_6
- name: Generate privatekey_fmt_2 - verify that returned content is not base64 encoded
assert:
that:
- privatekey_fmt_2_step_6.privatekey == lookup('file', output_dir ~ '/privatekey_fmt_2.pem', rstrip=False)
when: 'select_crypto_backend == "cryptography" and cryptography_version.stdout is version("2.6", ">=")'

View file

@ -1,4 +1,12 @@
---
- name: Validate privatekey1 idempotency and content returned
assert:
that:
- privatekey1_idempotence is not changed
- privatekey1.privatekey == lookup('file', output_dir ~ '/privatekey1.pem', rstrip=False)
- privatekey1.privatekey == privatekey1_idempotence.privatekey
- name: Validate privatekey1 (test - RSA key with size 4096 bits)
shell: "openssl rsa -noout -text -in {{ output_dir }}/privatekey1.pem | grep Private | sed 's/\\(RSA *\\)*Private-Key: (\\(.*\\) bit.*)/\\2/'"
register: privatekey1
@ -39,6 +47,13 @@
that:
- privatekey4.stat.exists == False
- name: Validate privatekey4 removal behavior
assert:
that:
- privatekey4_delete is changed
- privatekey4_delete.privatekey is none
- privatekey4_delete_idempotence is not changed
- name: Validate privatekey5 (test - Passphrase protected key + idempotence)
shell: "openssl rsa -noout -text -in {{ output_dir }}/privatekey5.pem -passin pass:ansible | grep Private | sed 's/\\(RSA *\\)*Private-Key: (\\(.*\\) bit.*)/\\2/'"

View file

@ -8,6 +8,16 @@
path: '{{ output_dir }}/publickey.pub'
privatekey_path: '{{ output_dir }}/privatekey.pem'
select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: publickey
- name: Generate publickey - PEM format (idempotence)
openssl_publickey:
path: '{{ output_dir }}/publickey.pub'
privatekey_path: '{{ output_dir }}/privatekey.pem'
select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: publickey_idempotence
- name: Generate publickey - OpenSSH format
openssl_publickey:
@ -38,6 +48,16 @@
path: '{{ output_dir }}/publickey2.pub'
privatekey_path: '{{ output_dir }}/privatekey.pem'
select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: publickey2_absent
- name: Delete publickey2 - standard (idempotence)
openssl_publickey:
state: absent
path: '{{ output_dir }}/publickey2.pub'
privatekey_path: '{{ output_dir }}/privatekey.pem'
select_crypto_backend: '{{ select_crypto_backend }}'
register: publickey2_absent_idempotence
- name: Generate privatekey3 - with passphrase
openssl_privatekey:

View file

@ -1,4 +1,12 @@
---
- name: Validate publickey 1 idempotence and result behavior
assert:
that:
- publickey is changed
- publickey_idempotence is not changed
- publickey.publickey == lookup('file', output_dir ~ '/publickey.pub', rstrip=False)
- publickey.publickey == publickey_idempotence.publickey
- name: Validate public key (test - privatekey modulus)
shell: 'openssl rsa -noout -modulus -in {{ output_dir }}/privatekey.pem'
register: privatekey_modulus
@ -45,6 +53,13 @@
that:
- publickey2.stat.exists == False
- name: Validate publickey2 removal behavior
assert:
that:
- publickey2_absent is changed
- publickey2_absent_idempotence is not changed
- publickey2_absent.publickey is none
- name: Validate publickey3 (test - privatekey modulus)
shell: 'openssl rsa -noout -modulus -in {{ output_dir }}/privatekey3.pem -passin pass:ansible'