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) 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'): def load_privatekey(path, passphrase=None, check_passphrase=True, content=None, backend='pyopenssl'):
"""Load the specified OpenSSL private key. """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 default: https://cloud.entrust.net/EntrustCloud/documentation/cms-api-2.1.0.yaml
version_added: "2.9" 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 extends_documentation_fragment: files
notes: notes:
- All ASN.1 TIME values should be specified following the YYYYMMDDHHMMSSZ pattern. - 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) returned: changed and if I(backup) is C(yes)
type: str type: str
sample: /path/to/www.ansible.com.crt.2019-03-09@11:22~ 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.csr = None
self.backend = backend self.backend = backend
self.module = module self.module = module
self.return_content = module.params['return_content']
# The following are default values which make sure check() works as # The following are default values which make sure check() works as
# before if providers do not explicitly change these properties. # before if providers do not explicitly change these properties.
@ -1115,6 +1128,8 @@ class CertificateAbsent(Certificate):
} }
if self.backup_file: if self.backup_file:
result['backup_file'] = self.backup_file result['backup_file'] = self.backup_file
if self.return_content:
result['certificate'] = None
return result return result
@ -1230,6 +1245,9 @@ class SelfSignedCertificateCryptography(Certificate):
} }
if self.backup_file: if self.backup_file:
result['backup_file'] = 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: if check_mode:
result.update({ result.update({
@ -1327,6 +1345,9 @@ class SelfSignedCertificate(Certificate):
} }
if self.backup_file: if self.backup_file:
result['backup_file'] = 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: if check_mode:
result.update({ result.update({
@ -1521,6 +1542,9 @@ class OwnCACertificateCryptography(Certificate):
} }
if self.backup_file: if self.backup_file:
result['backup_file'] = 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: if check_mode:
result.update({ result.update({
@ -1644,6 +1668,9 @@ class OwnCACertificate(Certificate):
} }
if self.backup_file: if self.backup_file:
result['backup_file'] = 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: if check_mode:
result.update({ result.update({
@ -1959,6 +1986,9 @@ class AssertOnlyCertificateBase(Certificate):
'privatekey': self.privatekey_path, 'privatekey': self.privatekey_path,
'csr': self.csr_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 return result
@ -2424,6 +2454,9 @@ class EntrustCertificate(Certificate):
if self.backup_file: if self.backup_file:
result['backup_file'] = 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()) result.update(self._get_cert_details())
@ -2511,6 +2544,9 @@ class AcmeCertificate(Certificate):
} }
if self.backup_file: if self.backup_file:
result['backup_file'] = 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 return result
@ -2526,6 +2562,7 @@ def main():
csr_content=dict(type='str'), csr_content=dict(type='str'),
backup=dict(type='bool', default=False), backup=dict(type='bool', default=False),
select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'cryptography', 'pyopenssl']), select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'cryptography', 'pyopenssl']),
return_content=dict(type='bool', default=False),
# General properties of a certificate # General properties of a certificate
privatekey_path=dict(type='path'), privatekey_path=dict(type='path'),

View file

@ -280,6 +280,12 @@ options:
I(authority_cert_issuer) and I(authority_cert_serial_number) is specified. I(authority_cert_issuer) and I(authority_cert_serial_number) is specified.
type: int type: int
version_added: "2.9" 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: extends_documentation_fragment:
- files - files
notes: notes:
@ -419,6 +425,11 @@ backup_file:
returned: changed and if I(backup) is C(yes) returned: changed and if I(backup) is C(yes)
type: str type: str
sample: /path/to/www.ansible.com.csr.2019-03-09@11:22~ 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 import abc
@ -510,6 +521,8 @@ class CertificateSigningRequestBase(crypto_utils.OpenSSLObject):
self.authority_cert_serial_number = module.params['authority_cert_serial_number'] self.authority_cert_serial_number = module.params['authority_cert_serial_number']
self.request = None self.request = None
self.privatekey = 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: 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') 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() result = self._generate_csr()
if self.backup: if self.backup:
self.backup_file = module.backup_local(self.path) self.backup_file = module.backup_local(self.path)
if self.return_content:
self.csr_bytes = result
crypto_utils.write_file(module, result) crypto_utils.write_file(module, result)
self.changed = True self.changed = True
@ -606,6 +621,10 @@ class CertificateSigningRequestBase(crypto_utils.OpenSSLObject):
} }
if self.backup_file: if self.backup_file:
result['backup_file'] = 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 return result
@ -1059,6 +1078,7 @@ def main():
authority_cert_issuer=dict(type='list', elements='str'), authority_cert_issuer=dict(type='list', elements='str'),
authority_cert_serial_number=dict(type='int'), authority_cert_serial_number=dict(type='int'),
select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'cryptography', 'pyopenssl']), 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_together=[('authority_cert_issuer', 'authority_cert_serial_number')],
required_if=[('state', 'present', ['privatekey_path', 'privatekey_content'], True)], required_if=[('state', 'present', ['privatekey_path', 'privatekey_content'], True)],

View file

@ -70,6 +70,12 @@ options:
default: auto default: auto
choices: [ auto, cryptography, openssl ] choices: [ auto, cryptography, openssl ]
version_added: '2.10' 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: extends_documentation_fragment:
- files - files
seealso: seealso:
@ -112,6 +118,11 @@ backup_file:
returned: changed and if I(backup) is C(yes) returned: changed and if I(backup) is C(yes)
type: str type: str
sample: /path/to/dhparams.pem.2019-03-09@11:22~ 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 import abc
@ -155,6 +166,7 @@ class DHParameterBase(object):
self.size = module.params['size'] self.size = module.params['size']
self.force = module.params['force'] self.force = module.params['force']
self.changed = False self.changed = False
self.return_content = module.params['return_content']
self.backup = module.params['backup'] self.backup = module.params['backup']
self.backup_file = None self.backup_file = None
@ -218,6 +230,9 @@ class DHParameterBase(object):
} }
if self.backup_file: if self.backup_file:
result['backup_file'] = 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 return result
@ -332,6 +347,7 @@ def main():
path=dict(type='path', required=True), path=dict(type='path', required=True),
backup=dict(type='bool', default=False), backup=dict(type='bool', default=False),
select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'cryptography', 'openssl']), select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'cryptography', 'openssl']),
return_content=dict(type='bool', default=False),
), ),
supports_check_mode=True, supports_check_mode=True,
add_file_common_args=True, add_file_common_args=True,

View file

@ -95,6 +95,12 @@ options:
type: bool type: bool
default: no default: no
version_added: "2.8" 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: extends_documentation_fragment:
- files - files
seealso: seealso:
@ -169,8 +175,14 @@ backup_file:
returned: changed and if I(backup) is C(yes) returned: changed and if I(backup) is C(yes)
type: str type: str
sample: /path/to/ansible.com.pem.2019-03-09@11:22~ 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 stat
import os import os
import traceback import traceback
@ -212,6 +224,8 @@ class Pkcs(crypto_utils.OpenSSLObject):
self.pkcs12 = None self.pkcs12 = None
self.privatekey_passphrase = module.params['privatekey_passphrase'] self.privatekey_passphrase = module.params['privatekey_passphrase']
self.privatekey_path = module.params['privatekey_path'] self.privatekey_path = module.params['privatekey_path']
self.pkcs12_bytes = None
self.return_content = module.params['return_content']
self.src = module.params['src'] self.src = module.params['src']
if module.params['mode'] is None: if module.params['mode'] is None:
@ -294,6 +308,10 @@ class Pkcs(crypto_utils.OpenSSLObject):
result['privatekey_path'] = self.privatekey_path result['privatekey_path'] = self.privatekey_path
if self.backup_file: if self.backup_file:
result['backup_file'] = 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 return result
@ -358,6 +376,8 @@ class Pkcs(crypto_utils.OpenSSLObject):
if self.backup: if self.backup:
self.backup_file = module.backup_local(self.path) self.backup_file = module.backup_local(self.path)
crypto_utils.write_file(module, content, mode) crypto_utils.write_file(module, content, mode)
if self.return_content:
self.pkcs12_bytes = content
def main(): def main():
@ -376,6 +396,7 @@ def main():
state=dict(type='str', default='present', choices=['absent', 'present']), state=dict(type='str', default='present', choices=['absent', 'present']),
src=dict(type='path'), src=dict(type='path'),
backup=dict(type='bool', default=False), backup=dict(type='bool', default=False),
return_content=dict(type='bool', default=False),
) )
required_if = [ required_if = [

View file

@ -156,6 +156,14 @@ options:
type: bool type: bool
default: no default: no
version_added: "2.8" 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: extends_documentation_fragment:
- files - files
seealso: seealso:
@ -232,9 +240,17 @@ backup_file:
returned: changed and if I(backup) is C(yes) returned: changed and if I(backup) is C(yes)
type: str type: str
sample: /path/to/privatekey.pem.2019-03-09@11:22~ 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 abc
import base64
import os import os
import traceback import traceback
from distutils.version import LooseVersion from distutils.version import LooseVersion
@ -303,6 +319,8 @@ class PrivateKeyBase(crypto_utils.OpenSSLObject):
self.fingerprint = {} self.fingerprint = {}
self.format = module.params['format'] self.format = module.params['format']
self.format_mismatch = module.params['format_mismatch'] 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 = module.params['backup']
self.backup_file = None self.backup_file = None
@ -333,6 +351,8 @@ class PrivateKeyBase(crypto_utils.OpenSSLObject):
self.backup_file = module.backup_local(self.path) self.backup_file = module.backup_local(self.path)
self._generate_private_key() self._generate_private_key()
privatekey_data = self._get_private_key_data() privatekey_data = self._get_private_key_data()
if self.return_content:
self.privatekey_bytes = privatekey_data
crypto_utils.write_file(module, privatekey_data, 0o600) crypto_utils.write_file(module, privatekey_data, 0o600)
self.changed = True self.changed = True
elif not self.check(module, perms_required=False, ignore_conversion=False): elif not self.check(module, perms_required=False, ignore_conversion=False):
@ -340,6 +360,8 @@ class PrivateKeyBase(crypto_utils.OpenSSLObject):
if self.backup: if self.backup:
self.backup_file = module.backup_local(self.path) self.backup_file = module.backup_local(self.path)
privatekey_data = self._get_private_key_data() privatekey_data = self._get_private_key_data()
if self.return_content:
self.privatekey_bytes = privatekey_data
crypto_utils.write_file(module, privatekey_data, 0o600) crypto_utils.write_file(module, privatekey_data, 0o600)
self.changed = True self.changed = True
@ -393,6 +415,16 @@ class PrivateKeyBase(crypto_utils.OpenSSLObject):
} }
if self.backup_file: if self.backup_file:
result['backup_file'] = 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 return result
@ -744,6 +776,7 @@ def main():
format=dict(type='str', default='auto_ignore', choices=['pkcs1', 'pkcs8', 'raw', 'auto', 'auto_ignore']), format=dict(type='str', default='auto_ignore', choices=['pkcs1', 'pkcs8', 'raw', 'auto', 'auto_ignore']),
format_mismatch=dict(type='str', default='regenerate', choices=['regenerate', 'convert']), format_mismatch=dict(type='str', default='regenerate', choices=['regenerate', 'convert']),
select_crypto_backend=dict(type='str', choices=['auto', 'pyopenssl', 'cryptography'], default='auto'), select_crypto_backend=dict(type='str', choices=['auto', 'pyopenssl', 'cryptography'], default='auto'),
return_content=dict(type='bool', default=False),
), ),
supports_check_mode=True, supports_check_mode=True,
add_file_common_args=True, add_file_common_args=True,

View file

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

View file

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

View file

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

View file

@ -32,6 +32,7 @@
provider: selfsigned provider: selfsigned
selfsigned_digest: sha256 selfsigned_digest: sha256
select_crypto_backend: '{{ select_crypto_backend }}' select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: selfsigned_certificate register: selfsigned_certificate
- name: (Selfsigned, {{select_crypto_backend}}) Generate selfsigned certificate - idempotency - name: (Selfsigned, {{select_crypto_backend}}) Generate selfsigned certificate - idempotency
@ -42,6 +43,7 @@
provider: selfsigned provider: selfsigned
selfsigned_digest: sha256 selfsigned_digest: sha256
select_crypto_backend: '{{ select_crypto_backend }}' select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: selfsigned_certificate_idempotence register: selfsigned_certificate_idempotence
- name: (Selfsigned, {{select_crypto_backend}}) Generate selfsigned certificate (check mode) - 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.notBefore == ownca_certificate_idempotence.notBefore
- ownca_certificate.notAfter == ownca_certificate_idempotence.notAfter - 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: - block:
- name: (OwnCA validation, {{select_crypto_backend}}) Validate ownca certificate v2 (test - ownca certificate version == 2) - 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"' 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.notBefore == selfsigned_certificate_idempotence.notBefore
- selfsigned_certificate.notAfter == selfsigned_certificate_idempotence.notAfter - 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 - name: Make sure that changes in CSR are detected even if private key is specified
assert: assert:
that: that:

View file

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

View file

@ -22,8 +22,16 @@
that: that:
- generate_csr_check is changed - generate_csr_check is changed
- generate_csr is changed - generate_csr is changed
- generate_csr_check_idempotent is not changed - generate_csr_idempotent is not changed
- generate_csr_check_idempotent_check 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) - name: Validate CSR without SAN (check mode, idempotency)
assert: assert:
@ -168,6 +176,7 @@
- csr_backup_4.backup_file is string - csr_backup_4.backup_file is string
- csr_backup_5 is not changed - csr_backup_5 is not changed
- csr_backup_5.backup_file is undefined - csr_backup_5.backup_file is undefined
- csr_backup_4.csr is none
- name: Check CSR with everything - name: Check CSR with everything
assert: assert:

View file

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

View file

@ -31,6 +31,12 @@
- dhparam_changed_to_512 is changed - dhparam_changed_to_512 is changed
- dhparam_changed_force 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" - name: "[{{ select_crypto_backend }}] Verify that broken params will be regenerated"
assert: assert:
that: that:
@ -49,3 +55,4 @@
- dhparam_backup_4.backup_file is string - dhparam_backup_4.backup_file is string
- dhparam_backup_5 is not changed - dhparam_backup_5 is not changed
- dhparam_backup_5.backup_file is undefined - 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" privatekey_path: "{{ output_dir }}/ansible_pkey.pem"
certificate_path: "{{ output_dir }}/ansible.crt" certificate_path: "{{ output_dir }}/ansible.crt"
state: present state: present
return_content: yes
register: p12_standard register: p12_standard
- name: 'Generate PKCS#12 file again, idempotency' - name: 'Generate PKCS#12 file again, idempotency'
@ -60,8 +61,20 @@
privatekey_path: "{{ output_dir }}/ansible_pkey.pem" privatekey_path: "{{ output_dir }}/ansible_pkey.pem"
certificate_path: "{{ output_dir }}/ansible.crt" certificate_path: "{{ output_dir }}/ansible.crt"
state: present state: present
return_content: yes
register: p12_standard_idempotency 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)' - name: 'Generate PKCS#12 file (force)'
openssl_pkcs12: openssl_pkcs12:
path: "{{ output_dir }}/ansible.p12" path: "{{ output_dir }}/ansible.p12"
@ -216,6 +229,7 @@
path: "{{ output_dir }}/ansible_backup.p12" path: "{{ output_dir }}/ansible_backup.p12"
state: absent state: absent
backup: yes backup: yes
return_content: yes
register: p12_backup_4 register: p12_backup_4
- name: 'Generate PKCS#12 file (remove, idempotent)' - name: 'Generate PKCS#12 file (remove, idempotent)'
openssl_pkcs12: openssl_pkcs12:

View file

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

View file

@ -3,6 +3,15 @@
openssl_privatekey: openssl_privatekey:
path: '{{ output_dir }}/privatekey1.pem' path: '{{ output_dir }}/privatekey1.pem'
select_crypto_backend: '{{ select_crypto_backend }}' 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 - name: Generate privatekey2 - size 2048
openssl_privatekey: openssl_privatekey:
@ -27,6 +36,15 @@
state: absent state: absent
path: '{{ output_dir }}/privatekey4.pem' path: '{{ output_dir }}/privatekey4.pem'
select_crypto_backend: '{{ select_crypto_backend }}' 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 - name: Generate privatekey5 - standard - with passphrase
openssl_privatekey: openssl_privatekey:
@ -381,30 +399,69 @@
type: X448 type: X448
format: raw format: raw
select_crypto_backend: '{{ select_crypto_backend }}' select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: privatekey_fmt_2_step_3 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) - name: Generate privatekey_fmt_2 - raw format (idempotent)
openssl_privatekey: openssl_privatekey:
path: '{{ output_dir }}/privatekey_fmt_2.pem' path: '{{ output_dir }}/privatekey_fmt_2.pem'
type: X448 type: X448
format: raw format: raw
select_crypto_backend: '{{ select_crypto_backend }}' select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: privatekey_fmt_2_step_4 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) - name: Generate privatekey_fmt_2 - auto format (ignore)
openssl_privatekey: openssl_privatekey:
path: '{{ output_dir }}/privatekey_fmt_2.pem' path: '{{ output_dir }}/privatekey_fmt_2.pem'
type: X448 type: X448
format: auto_ignore format: auto_ignore
select_crypto_backend: '{{ select_crypto_backend }}' select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: privatekey_fmt_2_step_5 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) - name: Generate privatekey_fmt_2 - auto format (no ignore)
openssl_privatekey: openssl_privatekey:
path: '{{ output_dir }}/privatekey_fmt_2.pem' path: '{{ output_dir }}/privatekey_fmt_2.pem'
type: X448 type: X448
format: auto format: auto
select_crypto_backend: '{{ select_crypto_backend }}' select_crypto_backend: '{{ select_crypto_backend }}'
return_content: yes
register: privatekey_fmt_2_step_6 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", ">=")' 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) - 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/'" shell: "openssl rsa -noout -text -in {{ output_dir }}/privatekey1.pem | grep Private | sed 's/\\(RSA *\\)*Private-Key: (\\(.*\\) bit.*)/\\2/'"
register: privatekey1 register: privatekey1
@ -39,6 +47,13 @@
that: that:
- privatekey4.stat.exists == False - 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) - 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/'" 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' path: '{{ output_dir }}/publickey.pub'
privatekey_path: '{{ output_dir }}/privatekey.pem' privatekey_path: '{{ output_dir }}/privatekey.pem'
select_crypto_backend: '{{ select_crypto_backend }}' 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 - name: Generate publickey - OpenSSH format
openssl_publickey: openssl_publickey:
@ -38,6 +48,16 @@
path: '{{ output_dir }}/publickey2.pub' path: '{{ output_dir }}/publickey2.pub'
privatekey_path: '{{ output_dir }}/privatekey.pem' privatekey_path: '{{ output_dir }}/privatekey.pem'
select_crypto_backend: '{{ select_crypto_backend }}' 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 - name: Generate privatekey3 - with passphrase
openssl_privatekey: 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) - name: Validate public key (test - privatekey modulus)
shell: 'openssl rsa -noout -modulus -in {{ output_dir }}/privatekey.pem' shell: 'openssl rsa -noout -modulus -in {{ output_dir }}/privatekey.pem'
register: privatekey_modulus register: privatekey_modulus
@ -45,6 +53,13 @@
that: that:
- publickey2.stat.exists == False - 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) - name: Validate publickey3 (test - privatekey modulus)
shell: 'openssl rsa -noout -modulus -in {{ output_dir }}/privatekey3.pem -passin pass:ansible' shell: 'openssl rsa -noout -modulus -in {{ output_dir }}/privatekey3.pem -passin pass:ansible'