openssl_certificate/csr(_info): add support for SubjectKeyIdentifier and AuthorityKeyIdentifier (#60741)
* Add support for SubjectKeyIdentifier and AuthorityKeyIdentifier to _info modules. * Adding SubjectKeyIdentifier and AuthorityKeyIdentifier support to openssl_certificate and openssl_csr. * Fix type of authority_cert_issuer. * Add basic tests. * Add changelog. * Added proper tests for _info modules. * Fix docs bug. * Make sure new features are only used when cryptography backend for openssl_csr is available. * Work around jinja2 being too old on some CI hosts. * Add tests for openssl_csr. * Add openssl_certificate tests. * Fix idempotence test. * Move one level up. * Add ownca_create_authority_key_identifier option. * Add ownca_create_authority_key_identifier option. * Add idempotency check. * Apparently the function call expected different args for cryptography < 2.7. * Fix copy'n'paste errors and typos. * string -> general name. * Add disclaimer. * Implement always_create / create_if_not_provided / never_create for openssl_certificate. * Update changelog and porting guide. * Add comments for defaults.
This commit is contained in:
parent
77e4371460
commit
fa70690e5c
19 changed files with 1071 additions and 6 deletions
|
@ -0,0 +1,6 @@
|
|||
minor_changes:
|
||||
- "openssl_certificate - add support for subject key identifier and authority key identifier extensions. Subject key identifiers are created by default when not explicitly disabled."
|
||||
- "openssl_certificate - the ``ownca`` provider creates authority key identifiers if not explicitly disabled with ``ownca_create_authority_key_identifier: no``."
|
||||
- "openssl_certificate_info - add support for subject key identifier and authority key identifier extensions."
|
||||
- "openssl_csr - add support for subject key identifier and authority key identifier extensions."
|
||||
- "openssl_csr_info - add support for subject key identifier and authority key identifier extensions."
|
|
@ -306,6 +306,8 @@ Noteworthy module changes
|
|||
* `mysql_db <mysql_db_module>` returns new `db_list` parameter in addition to `db` parameter. This `db_list` parameter refers to list of database names. `db` parameter will be deprecated in version `2.13`.
|
||||
* `snow_record <snow_record_module>` and `snow_record_find <snow_record_find_module>` now takes environment variables for `instance`, `username` and `password` parameters. This change marks these parameters as optional.
|
||||
* The deprecated ``force`` option in ``win_firewall_rule`` has been removed.
|
||||
* :ref:`openssl_certificate <openssl_certificate_module>`'s ``ownca`` provider creates authority key identifiers if not explicitly disabled with ``ownca_create_authority_key_identifier: no``. This is only the case for the ``cryptography`` backend, which is selected by default if the ``cryptography`` library is available.
|
||||
* :ref:`openssl_certificate <openssl_certificate_module>`'s ``ownca`` and ``selfsigned`` providers create subject key identifiers if not explicitly disabled with ``ownca_create_subject_key_identifier: never_create`` resp. ``selfsigned_create_subject_key_identifier: never_create``. If a subject key identifier is provided by the CSR, it is taken; if not, it is created from the public key. This is only the case for the ``cryptography`` backend, which is selected by default if the ``cryptography`` library is available.
|
||||
|
||||
|
||||
Plugins
|
||||
|
|
|
@ -138,6 +138,21 @@ options:
|
|||
default: +3650d
|
||||
aliases: [ selfsigned_notAfter ]
|
||||
|
||||
selfsigned_create_subject_key_identifier:
|
||||
description:
|
||||
- Whether to create the Subject Key Identifier (SKI) from the public key.
|
||||
- A value of C(create_if_not_provided) (default) only creates a SKI when the CSR does not
|
||||
provide one.
|
||||
- A value of C(always_create) always creates a SKI. If the CSR provides one, that one is
|
||||
ignored.
|
||||
- A value of C(never_create) never creates a SKI. If the CSR provides one, that one is used.
|
||||
- This is only used by the C(selfsigned) provider.
|
||||
- Note that this is only supported if the C(cryptography) backend is used!
|
||||
type: str
|
||||
choices: [create_if_not_provided, always_create, never_create]
|
||||
default: create_if_not_provided
|
||||
version_added: "2.9"
|
||||
|
||||
ownca_path:
|
||||
description:
|
||||
- Remote absolute path of the CA (Certificate Authority) certificate.
|
||||
|
@ -204,6 +219,33 @@ options:
|
|||
default: +3650d
|
||||
version_added: "2.7"
|
||||
|
||||
ownca_create_subject_key_identifier:
|
||||
description:
|
||||
- Whether to create the Subject Key Identifier (SKI) from the public key.
|
||||
- A value of C(create_if_not_provided) (default) only creates a SKI when the CSR does not
|
||||
provide one.
|
||||
- A value of C(always_create) always creates a SKI. If the CSR provides one, that one is
|
||||
ignored.
|
||||
- A value of C(never_create) never creates a SKI. If the CSR provides one, that one is used.
|
||||
- This is only used by the C(ownca) provider.
|
||||
- Note that this is only supported if the C(cryptography) backend is used!
|
||||
type: str
|
||||
choices: [create_if_not_provided, always_create, never_create]
|
||||
default: create_if_not_provided
|
||||
version_added: "2.9"
|
||||
|
||||
ownca_create_authority_key_identifier:
|
||||
description:
|
||||
- Create a Authority Key Identifier from the CA's certificate. If the CSR provided
|
||||
a authority key identifier, it is ignored.
|
||||
- The Authority Key Identifier is generated from the CA certificate's Subject Key Identifier,
|
||||
if available. If it is not available, the CA certificate's public key will be used.
|
||||
- This is only used by the C(ownca) provider.
|
||||
- Note that this is only supported if the C(cryptography) backend is used!
|
||||
type: bool
|
||||
default: yes
|
||||
version_added: "2.9"
|
||||
|
||||
acme_accountkey_path:
|
||||
description:
|
||||
- The path to the accountkey for the C(acme) provider.
|
||||
|
@ -843,6 +885,11 @@ class Certificate(crypto_utils.OpenSSLObject):
|
|||
self.backend = backend
|
||||
self.module = module
|
||||
|
||||
# The following are default values which make sure check() works as
|
||||
# before if providers do not explicitly change these properties.
|
||||
self.create_subject_key_identifier = 'never_create'
|
||||
self.create_authority_key_identifier = False
|
||||
|
||||
self.backup = module.params['backup']
|
||||
self.backup_file = None
|
||||
|
||||
|
@ -918,13 +965,21 @@ class Certificate(crypto_utils.OpenSSLObject):
|
|||
if self.csr.subject != self.cert.subject:
|
||||
return False
|
||||
# Check extensions
|
||||
cert_exts = self.cert.extensions
|
||||
csr_exts = self.csr.extensions
|
||||
cert_exts = list(self.cert.extensions)
|
||||
csr_exts = list(self.csr.extensions)
|
||||
if self.create_subject_key_identifier != 'never_create':
|
||||
# Filter out SubjectKeyIdentifier extension before comparison
|
||||
cert_exts = list(filter(lambda x: not isinstance(x.value, x509.SubjectKeyIdentifier), cert_exts))
|
||||
csr_exts = list(filter(lambda x: not isinstance(x.value, x509.SubjectKeyIdentifier), csr_exts))
|
||||
if self.create_authority_key_identifier:
|
||||
# Filter out AuthorityKeyIdentifier extension before comparison
|
||||
cert_exts = list(filter(lambda x: not isinstance(x.value, x509.AuthorityKeyIdentifier), cert_exts))
|
||||
csr_exts = list(filter(lambda x: not isinstance(x.value, x509.AuthorityKeyIdentifier), csr_exts))
|
||||
if len(cert_exts) != len(csr_exts):
|
||||
return False
|
||||
for cert_ext in cert_exts:
|
||||
try:
|
||||
csr_ext = csr_exts.get_extension_for_oid(cert_ext.oid)
|
||||
csr_ext = self.csr.extensions.get_extension_for_oid(cert_ext.oid)
|
||||
if cert_ext != csr_ext:
|
||||
return False
|
||||
except cryptography.x509.ExtensionNotFound as dummy:
|
||||
|
@ -966,6 +1021,29 @@ class Certificate(crypto_utils.OpenSSLObject):
|
|||
if not self._validate_csr():
|
||||
return False
|
||||
|
||||
# Check SubjectKeyIdentifier
|
||||
if self.backend == 'cryptography' and self.create_subject_key_identifier != 'never_create':
|
||||
# Get hold of certificate's SKI
|
||||
try:
|
||||
ext = self.cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier)
|
||||
except cryptography.x509.ExtensionNotFound as dummy:
|
||||
return False
|
||||
# Get hold of CSR's SKI for 'create_if_not_provided'
|
||||
csr_ext = None
|
||||
if self.create_subject_key_identifier == 'create_if_not_provided':
|
||||
try:
|
||||
csr_ext = self.csr.extensions.get_extension_for_class(x509.SubjectKeyIdentifier)
|
||||
except cryptography.x509.ExtensionNotFound as dummy:
|
||||
pass
|
||||
if csr_ext is None:
|
||||
# If CSR had no SKI, or we chose to ignore it ('always_create'), compare with created SKI
|
||||
if ext.value.digest != x509.SubjectKeyIdentifier.from_public_key(self.cert.public_key()).digest:
|
||||
return False
|
||||
else:
|
||||
# If CSR had SKI and we didn't ignore it ('create_if_not_provided'), compare SKIs
|
||||
if ext.value.digest != csr_ext.value.digest:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
@ -995,6 +1073,7 @@ class SelfSignedCertificateCryptography(Certificate):
|
|||
"""Generate the self-signed certificate, using the cryptography backend"""
|
||||
def __init__(self, module):
|
||||
super(SelfSignedCertificateCryptography, self).__init__(module, 'cryptography')
|
||||
self.create_subject_key_identifier = module.params['selfsigned_create_subject_key_identifier']
|
||||
self.notBefore = self.get_relative_time_option(module.params['selfsigned_not_before'], 'selfsigned_not_before')
|
||||
self.notAfter = self.get_relative_time_option(module.params['selfsigned_not_after'], 'selfsigned_not_after')
|
||||
self.digest = crypto_utils.select_message_digest(module.params['selfsigned_digest'])
|
||||
|
@ -1043,8 +1122,18 @@ class SelfSignedCertificateCryptography(Certificate):
|
|||
cert_builder = cert_builder.not_valid_before(self.notBefore)
|
||||
cert_builder = cert_builder.not_valid_after(self.notAfter)
|
||||
cert_builder = cert_builder.public_key(self.privatekey.public_key())
|
||||
has_ski = False
|
||||
for extension in self.csr.extensions:
|
||||
if isinstance(extension.value, x509.SubjectKeyIdentifier):
|
||||
if self.create_subject_key_identifier == 'always_create':
|
||||
continue
|
||||
has_ski = True
|
||||
cert_builder = cert_builder.add_extension(extension.value, critical=extension.critical)
|
||||
if not has_ski and self.create_subject_key_identifier != 'never_create':
|
||||
cert_builder = cert_builder.add_extension(
|
||||
x509.SubjectKeyIdentifier.from_public_key(self.privatekey.public_key()),
|
||||
critical=False
|
||||
)
|
||||
except ValueError as e:
|
||||
raise CertificateError(str(e))
|
||||
|
||||
|
@ -1098,6 +1187,8 @@ class SelfSignedCertificate(Certificate):
|
|||
|
||||
def __init__(self, module):
|
||||
super(SelfSignedCertificate, self).__init__(module, 'pyopenssl')
|
||||
if module.params['selfsigned_create_subject_key_identifier'] != 'create_if_not_provided':
|
||||
module.fail_json(msg='selfsigned_create_subject_key_identifier cannot be used with the pyOpenSSL backend!')
|
||||
self.notBefore = self.get_relative_time_option(module.params['selfsigned_not_before'], 'selfsigned_not_before')
|
||||
self.notAfter = self.get_relative_time_option(module.params['selfsigned_not_after'], 'selfsigned_not_after')
|
||||
self.digest = module.params['selfsigned_digest']
|
||||
|
@ -1187,6 +1278,8 @@ class OwnCACertificateCryptography(Certificate):
|
|||
"""Generate the own CA certificate. Using the cryptography backend"""
|
||||
def __init__(self, module):
|
||||
super(OwnCACertificateCryptography, self).__init__(module, 'cryptography')
|
||||
self.create_subject_key_identifier = module.params['ownca_create_subject_key_identifier']
|
||||
self.create_authority_key_identifier = module.params['ownca_create_authority_key_identifier']
|
||||
self.notBefore = self.get_relative_time_option(module.params['ownca_not_before'], 'ownca_not_before')
|
||||
self.notAfter = self.get_relative_time_option(module.params['ownca_not_after'], 'ownca_not_after')
|
||||
self.digest = crypto_utils.select_message_digest(module.params['ownca_digest'])
|
||||
|
@ -1243,8 +1336,34 @@ class OwnCACertificateCryptography(Certificate):
|
|||
cert_builder = cert_builder.not_valid_before(self.notBefore)
|
||||
cert_builder = cert_builder.not_valid_after(self.notAfter)
|
||||
cert_builder = cert_builder.public_key(self.csr.public_key())
|
||||
has_ski = False
|
||||
for extension in self.csr.extensions:
|
||||
if isinstance(extension.value, x509.SubjectKeyIdentifier):
|
||||
if self.create_subject_key_identifier == 'always_create':
|
||||
continue
|
||||
has_ski = True
|
||||
if self.create_authority_key_identifier and isinstance(extension.value, x509.AuthorityKeyIdentifier):
|
||||
continue
|
||||
cert_builder = cert_builder.add_extension(extension.value, critical=extension.critical)
|
||||
if not has_ski and self.create_subject_key_identifier != 'never_create':
|
||||
cert_builder = cert_builder.add_extension(
|
||||
x509.SubjectKeyIdentifier.from_public_key(self.csr.public_key()),
|
||||
critical=False
|
||||
)
|
||||
if self.create_authority_key_identifier:
|
||||
try:
|
||||
ext = self.ca_cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier)
|
||||
cert_builder = cert_builder.add_extension(
|
||||
x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(ext.value)
|
||||
if CRYPTOGRAPHY_VERSION >= LooseVersion('2.7') else
|
||||
x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(ext),
|
||||
critical=False
|
||||
)
|
||||
except cryptography.x509.ExtensionNotFound:
|
||||
cert_builder = cert_builder.add_extension(
|
||||
x509.AuthorityKeyIdentifier.from_issuer_public_key(self.ca_cert.public_key()),
|
||||
critical=False
|
||||
)
|
||||
|
||||
certificate = cert_builder.sign(
|
||||
private_key=self.ca_private_key, algorithm=self.digest,
|
||||
|
@ -1264,6 +1383,32 @@ class OwnCACertificateCryptography(Certificate):
|
|||
if module.set_fs_attributes_if_different(file_args, False):
|
||||
self.changed = True
|
||||
|
||||
def check(self, module, perms_required=True):
|
||||
"""Ensure the resource is in its desired state."""
|
||||
|
||||
if not super(OwnCACertificateCryptography, self).check(module, perms_required):
|
||||
return False
|
||||
|
||||
# Check AuthorityKeyIdentifier
|
||||
if self.create_authority_key_identifier:
|
||||
try:
|
||||
ext = self.ca_cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier)
|
||||
expected_ext = (
|
||||
x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(ext.value)
|
||||
if CRYPTOGRAPHY_VERSION >= LooseVersion('2.7') else
|
||||
x509.AuthorityKeyIdentifier.from_issuer_subject_key_identifier(ext)
|
||||
)
|
||||
except cryptography.x509.ExtensionNotFound:
|
||||
expected_ext = x509.AuthorityKeyIdentifier.from_issuer_public_key(self.ca_cert.public_key())
|
||||
try:
|
||||
ext = self.cert.extensions.get_extension_for_class(x509.AuthorityKeyIdentifier)
|
||||
if ext.value != expected_ext:
|
||||
return False
|
||||
except cryptography.x509.ExtensionNotFound as dummy:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def dump(self, check_mode=False):
|
||||
|
||||
result = {
|
||||
|
@ -1303,6 +1448,10 @@ class OwnCACertificate(Certificate):
|
|||
self.digest = module.params['ownca_digest']
|
||||
self.version = module.params['ownca_version']
|
||||
self.serial_number = randint(1000, 99999)
|
||||
if module.params['ownca_create_subject_key_identifier'] != 'create_if_not_provided':
|
||||
module.fail_json(msg='ownca_create_subject_key_identifier cannot be used with the pyOpenSSL backend!')
|
||||
if module.params['ownca_create_authority_key_identifier']:
|
||||
module.warn('ownca_create_authority_key_identifier is ignored by the pyOpenSSL backend!')
|
||||
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']
|
||||
|
@ -2268,6 +2417,11 @@ def main():
|
|||
selfsigned_digest=dict(type='str', default='sha256'),
|
||||
selfsigned_not_before=dict(type='str', default='+0s', aliases=['selfsigned_notBefore']),
|
||||
selfsigned_not_after=dict(type='str', default='+3650d', aliases=['selfsigned_notAfter']),
|
||||
selfsigned_create_subject_key_identifier=dict(
|
||||
type='str',
|
||||
default='create_if_not_provided',
|
||||
choices=['create_if_not_provided', 'always_create', 'never_create']
|
||||
),
|
||||
|
||||
# provider: ownca
|
||||
ownca_path=dict(type='path'),
|
||||
|
@ -2277,6 +2431,12 @@ def main():
|
|||
ownca_version=dict(type='int', default=3),
|
||||
ownca_not_before=dict(type='str', default='+0s'),
|
||||
ownca_not_after=dict(type='str', default='+3650d'),
|
||||
ownca_create_subject_key_identifier=dict(
|
||||
type='str',
|
||||
default='create_if_not_provided',
|
||||
choices=['create_if_not_provided', 'always_create', 'never_create']
|
||||
),
|
||||
ownca_create_authority_key_identifier=dict(type='bool', default=True),
|
||||
|
||||
# provider: acme
|
||||
acme_accountkey_path=dict(type='path'),
|
||||
|
|
|
@ -238,10 +238,45 @@ valid_at:
|
|||
or not.
|
||||
returned: success
|
||||
type: dict
|
||||
subject_key_identifier:
|
||||
description:
|
||||
- The certificate's subject key identifier.
|
||||
- The identifier is returned in hexadecimal, with C(:) used to separate bytes.
|
||||
- Is C(none) if the C(SubjectKeyIdentifier) extension is not present.
|
||||
returned: success and if the pyOpenSSL backend is I(not) used
|
||||
type: str
|
||||
sample: '00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33'
|
||||
version_added: "2.9"
|
||||
authority_key_identifier:
|
||||
description:
|
||||
- The certificate's authority key identifier.
|
||||
- The identifier is returned in hexadecimal, with C(:) used to separate bytes.
|
||||
- Is C(none) if the C(AuthorityKeyIdentifier) extension is not present.
|
||||
returned: success and if the pyOpenSSL backend is I(not) used
|
||||
type: str
|
||||
sample: '00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33'
|
||||
version_added: "2.9"
|
||||
authority_cert_issuer:
|
||||
description:
|
||||
- The certificate's authority cert issuer as a list of general names.
|
||||
- Is C(none) if the C(AuthorityKeyIdentifier) extension is not present.
|
||||
returned: success and if the pyOpenSSL backend is I(not) used
|
||||
type: list
|
||||
sample: "[DNS:www.ansible.com, IP:1.2.3.4]"
|
||||
version_added: "2.9"
|
||||
authority_cert_serial_number:
|
||||
description:
|
||||
- The certificate's authority cert serial number.
|
||||
- Is C(none) if the C(AuthorityKeyIdentifier) extension is not present.
|
||||
returned: success and if the pyOpenSSL backend is I(not) used
|
||||
type: int
|
||||
sample: '12345'
|
||||
version_added: "2.9"
|
||||
'''
|
||||
|
||||
|
||||
import abc
|
||||
import binascii
|
||||
import datetime
|
||||
import os
|
||||
import traceback
|
||||
|
@ -392,6 +427,14 @@ class CertificateInfo(crypto_utils.OpenSSLObject):
|
|||
def _get_public_key(self, binary):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def _get_subject_key_identifier(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def _get_authority_key_identifier(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def _get_serial_number(self):
|
||||
pass
|
||||
|
@ -437,6 +480,21 @@ class CertificateInfo(crypto_utils.OpenSSLObject):
|
|||
pk = self._get_public_key(binary=True)
|
||||
result['public_key_fingerprints'] = crypto_utils.get_fingerprint_of_bytes(pk) if pk is not None else dict()
|
||||
|
||||
if self.backend != 'pyopenssl':
|
||||
ski = self._get_subject_key_identifier()
|
||||
if ski is not None:
|
||||
ski = to_native(binascii.hexlify(ski))
|
||||
ski = ':'.join([ski[i:i + 2] for i in range(0, len(ski), 2)])
|
||||
result['subject_key_identifier'] = ski
|
||||
|
||||
aki, aci, acsn = self._get_authority_key_identifier()
|
||||
if aki is not None:
|
||||
aki = to_native(binascii.hexlify(aki))
|
||||
aki = ':'.join([aki[i:i + 2] for i in range(0, len(aki), 2)])
|
||||
result['authority_key_identifier'] = aki
|
||||
result['authority_cert_issuer'] = aci
|
||||
result['authority_cert_serial_number'] = acsn
|
||||
|
||||
result['serial_number'] = self._get_serial_number()
|
||||
result['extensions_by_oid'] = self._get_all_extensions()
|
||||
|
||||
|
@ -563,6 +621,23 @@ class CertificateInfoCryptography(CertificateInfo):
|
|||
serialization.PublicFormat.SubjectPublicKeyInfo
|
||||
)
|
||||
|
||||
def _get_subject_key_identifier(self):
|
||||
try:
|
||||
ext = self.cert.extensions.get_extension_for_class(x509.SubjectKeyIdentifier)
|
||||
return ext.value.digest
|
||||
except cryptography.x509.ExtensionNotFound:
|
||||
return None
|
||||
|
||||
def _get_authority_key_identifier(self):
|
||||
try:
|
||||
ext = self.cert.extensions.get_extension_for_class(x509.AuthorityKeyIdentifier)
|
||||
issuer = None
|
||||
if ext.value.authority_cert_issuer is not None:
|
||||
issuer = [crypto_utils.cryptography_decode_name(san) for san in ext.value.authority_cert_issuer]
|
||||
return ext.value.key_identifier, issuer, ext.value.authority_cert_serial_number
|
||||
except cryptography.x509.ExtensionNotFound:
|
||||
return None, None, None
|
||||
|
||||
def _get_serial_number(self):
|
||||
return self.cert.serial_number
|
||||
|
||||
|
@ -675,6 +750,14 @@ class CertificateInfoPyOpenSSL(CertificateInfo):
|
|||
self.module.warn('Your pyOpenSSL version does not support dumping public keys. '
|
||||
'Please upgrade to version 16.0 or newer, or use the cryptography backend.')
|
||||
|
||||
def _get_subject_key_identifier(self):
|
||||
# Won't be implemented
|
||||
return None
|
||||
|
||||
def _get_authority_key_identifier(self):
|
||||
# Won't be implemented
|
||||
return None, None, None
|
||||
|
||||
def _get_serial_number(self):
|
||||
return self.cert.get_serial_number()
|
||||
|
||||
|
|
|
@ -200,6 +200,66 @@ options:
|
|||
type: bool
|
||||
default: no
|
||||
version_added: "2.8"
|
||||
create_subject_key_identifier:
|
||||
description:
|
||||
- Create the Subject Key Identifier from the public key.
|
||||
- "Please note that commercial CAs can ignore the value, respectively use a value of
|
||||
their own choice instead. Specifying this option is mostly useful for self-signed
|
||||
certificates or for own CAs."
|
||||
- Note that this is only supported if the C(cryptography) backend is used!
|
||||
type: bool
|
||||
default: no
|
||||
version_added: "2.9"
|
||||
subject_key_identifier:
|
||||
description:
|
||||
- The subject key identifier as a hex string, where two bytes are separated by colons.
|
||||
- "Example: C(00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33)"
|
||||
- "Please note that commercial CAs ignore this value, respectively use a value of their
|
||||
own choice. Specifying this option is mostly useful for self-signed certificates
|
||||
or for own CAs."
|
||||
- Note that this option can only be used if I(create_subject_key_identifier) is C(no).
|
||||
- Note that this is only supported if the C(cryptography) backend is used!
|
||||
type: str
|
||||
version_added: "2.9"
|
||||
authority_key_identifier:
|
||||
description:
|
||||
- The authority key identifier as a hex string, where two bytes are separated by colons.
|
||||
- "Example: C(00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33)"
|
||||
- If specified, I(authority_cert_issuer) must also be specified.
|
||||
- "Please note that commercial CAs ignore this value, respectively use a value of their
|
||||
own choice. Specifying this option is mostly useful for self-signed certificates
|
||||
or for own CAs."
|
||||
- Note that this is only supported if the C(cryptography) backend is used!
|
||||
- The C(AuthorityKeyIdentifier) will only be added if at least one of I(authority_key_identifier),
|
||||
I(authority_cert_issuer) and I(authority_cert_serial_number) is specified.
|
||||
type: str
|
||||
version_added: "2.9"
|
||||
authority_cert_issuer:
|
||||
description:
|
||||
- Names that will be present in the authority cert issuer field of the certificate signing request.
|
||||
- Values must be prefixed by their options. (i.e., C(email), C(URI), C(DNS), C(RID), C(IP), C(dirName),
|
||||
C(otherName) and the ones specific to your CA)
|
||||
- "Example: C(DNS:ca.example.org)"
|
||||
- If specified, I(authority_key_identifier) must also be specified.
|
||||
- "Please note that commercial CAs ignore this value, respectively use a value of their
|
||||
own choice. Specifying this option is mostly useful for self-signed certificates
|
||||
or for own CAs."
|
||||
- Note that this is only supported if the C(cryptography) backend is used!
|
||||
- The C(AuthorityKeyIdentifier) will only be added if at least one of I(authority_key_identifier),
|
||||
I(authority_cert_issuer) and I(authority_cert_serial_number) is specified.
|
||||
type: list
|
||||
version_added: "2.9"
|
||||
authority_cert_serial_number:
|
||||
description:
|
||||
- The authority cert serial number.
|
||||
- Note that this is only supported if the C(cryptography) backend is used!
|
||||
- "Please note that commercial CAs ignore this value, respectively use a value of their
|
||||
own choice. Specifying this option is mostly useful for self-signed certificates
|
||||
or for own CAs."
|
||||
- The C(AuthorityKeyIdentifier) will only be added if at least one of I(authority_key_identifier),
|
||||
I(authority_cert_issuer) and I(authority_cert_serial_number) is specified.
|
||||
type: int
|
||||
version_added: "2.9"
|
||||
extends_documentation_fragment:
|
||||
- files
|
||||
notes:
|
||||
|
@ -329,6 +389,7 @@ backup_file:
|
|||
'''
|
||||
|
||||
import abc
|
||||
import binascii
|
||||
import os
|
||||
import traceback
|
||||
from distutils.version import LooseVersion
|
||||
|
@ -406,9 +467,17 @@ class CertificateSigningRequestBase(crypto_utils.OpenSSLObject):
|
|||
self.basicConstraints_critical = module.params['basic_constraints_critical']
|
||||
self.ocspMustStaple = module.params['ocsp_must_staple']
|
||||
self.ocspMustStaple_critical = module.params['ocsp_must_staple_critical']
|
||||
self.create_subject_key_identifier = module.params['create_subject_key_identifier']
|
||||
self.subject_key_identifier = module.params['subject_key_identifier']
|
||||
self.authority_key_identifier = module.params['authority_key_identifier']
|
||||
self.authority_cert_issuer = module.params['authority_cert_issuer']
|
||||
self.authority_cert_serial_number = module.params['authority_cert_serial_number']
|
||||
self.request = None
|
||||
self.privatekey = 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')
|
||||
|
||||
self.backup = module.params['backup']
|
||||
self.backup_file = None
|
||||
|
||||
|
@ -432,6 +501,18 @@ class CertificateSigningRequestBase(crypto_utils.OpenSSLObject):
|
|||
self.subjectAltName = ['DNS:%s' % sub[1]]
|
||||
break
|
||||
|
||||
if self.subject_key_identifier is not None:
|
||||
try:
|
||||
self.subject_key_identifier = binascii.unhexlify(self.subject_key_identifier.replace(':', ''))
|
||||
except Exception as e:
|
||||
raise CertificateSigningRequestError('Cannot parse subject_key_identifier: {0}'.format(e))
|
||||
|
||||
if self.authority_key_identifier is not None:
|
||||
try:
|
||||
self.authority_key_identifier = binascii.unhexlify(self.authority_key_identifier.replace(':', ''))
|
||||
except Exception as e:
|
||||
raise CertificateSigningRequestError('Cannot parse authority_key_identifier: {0}'.format(e))
|
||||
|
||||
@abc.abstractmethod
|
||||
def _generate_csr(self):
|
||||
pass
|
||||
|
@ -496,6 +577,11 @@ class CertificateSigningRequestBase(crypto_utils.OpenSSLObject):
|
|||
class CertificateSigningRequestPyOpenSSL(CertificateSigningRequestBase):
|
||||
|
||||
def __init__(self, module):
|
||||
if module.params['create_subject_key_identifier']:
|
||||
module.fail_json(msg='You cannot use create_subject_key_identifier with the pyOpenSSL backend!')
|
||||
for o in ('subject_key_identifier', 'authority_key_identifier', 'authority_cert_issuer', 'authority_cert_serial_number'):
|
||||
if module.params[o] is not None:
|
||||
module.fail_json(msg='You cannot use {0} with the pyOpenSSL backend!'.format(o))
|
||||
super(CertificateSigningRequestPyOpenSSL, self).__init__(module)
|
||||
|
||||
def _generate_csr(self):
|
||||
|
@ -691,6 +777,23 @@ class CertificateSigningRequestCryptography(CertificateSigningRequestBase):
|
|||
critical=self.ocspMustStaple_critical
|
||||
)
|
||||
|
||||
if self.create_subject_key_identifier:
|
||||
csr = csr.add_extension(
|
||||
cryptography.x509.SubjectKeyIdentifier.from_public_key(self.privatekey.public_key()),
|
||||
critical=False
|
||||
)
|
||||
elif self.subject_key_identifier is not None:
|
||||
csr = csr.add_extension(cryptography.x509.SubjectKeyIdentifier(self.subject_key_identifier), critical=False)
|
||||
|
||||
if self.authority_key_identifier is not None or self.authority_cert_issuer is not None or self.authority_cert_serial_number is not None:
|
||||
issuers = None
|
||||
if self.authority_cert_issuer is not None:
|
||||
issuers = [crypto_utils.cryptography_get_name(n) for n in self.authority_cert_issuer]
|
||||
csr = csr.add_extension(
|
||||
cryptography.x509.AuthorityKeyIdentifier(self.authority_key_identifier, issuers, self.authority_cert_serial_number),
|
||||
critical=False
|
||||
)
|
||||
|
||||
digest = None
|
||||
if self.digest == 'sha256':
|
||||
digest = cryptography.hazmat.primitives.hashes.SHA256()
|
||||
|
@ -806,11 +909,42 @@ class CertificateSigningRequestCryptography(CertificateSigningRequestBase):
|
|||
else:
|
||||
return tlsfeature_ext is None
|
||||
|
||||
def _check_subject_key_identifier(extensions):
|
||||
ext = _find_extension(extensions, cryptography.x509.SubjectKeyIdentifier)
|
||||
if self.create_subject_key_identifier or self.subject_key_identifier is not None:
|
||||
if not ext or ext.critical:
|
||||
return False
|
||||
if self.create_subject_key_identifier:
|
||||
digest = cryptography.x509.SubjectKeyIdentifier.from_public_key(self.privatekey.public_key()).digest
|
||||
return ext.value.digest == digest
|
||||
else:
|
||||
return ext.value.digest == self.subject_key_identifier
|
||||
else:
|
||||
return ext is None
|
||||
|
||||
def _check_authority_key_identifier(extensions):
|
||||
ext = _find_extension(extensions, cryptography.x509.AuthorityKeyIdentifier)
|
||||
if self.authority_key_identifier is not None or self.authority_cert_issuer is not None or self.authority_cert_serial_number is not None:
|
||||
if not ext or ext.critical:
|
||||
return False
|
||||
aci = None
|
||||
csr_aci = None
|
||||
if self.authority_cert_issuer is not None:
|
||||
aci = [str(crypto_utils.cryptography_get_name(n)) for n in self.authority_cert_issuer]
|
||||
if ext.value.authority_cert_issuer is not None:
|
||||
csr_aci = [str(n) for n in ext.value.authority_cert_issuer]
|
||||
return (ext.value.key_identifier == self.authority_key_identifier
|
||||
and csr_aci == aci
|
||||
and ext.value.authority_cert_serial_number == self.authority_cert_serial_number)
|
||||
else:
|
||||
return ext is None
|
||||
|
||||
def _check_extensions(csr):
|
||||
extensions = csr.extensions
|
||||
return (_check_subjectAltName(extensions) and _check_keyUsage(extensions) and
|
||||
_check_extenededKeyUsage(extensions) and _check_basicConstraints(extensions) and
|
||||
_check_ocspMustStaple(extensions))
|
||||
_check_ocspMustStaple(extensions) and _check_subject_key_identifier(extensions) and
|
||||
_check_authority_key_identifier(extensions))
|
||||
|
||||
def _check_signature(csr):
|
||||
if not csr.is_signature_valid:
|
||||
|
@ -865,8 +999,14 @@ def main():
|
|||
ocsp_must_staple=dict(type='bool', default=False, aliases=['ocspMustStaple']),
|
||||
ocsp_must_staple_critical=dict(type='bool', default=False, aliases=['ocspMustStaple_critical']),
|
||||
backup=dict(type='bool', default=False),
|
||||
create_subject_key_identifier=dict(type='bool', default=False),
|
||||
subject_key_identifier=dict(type='str'),
|
||||
authority_key_identifier=dict(type='str'),
|
||||
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']),
|
||||
),
|
||||
required_together=[('authority_cert_issuer', 'authority_cert_serial_number')],
|
||||
add_file_common_args=True,
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
|
|
@ -160,10 +160,45 @@ public_key_fingerprints:
|
|||
type: dict
|
||||
sample: "{'sha256': 'd4:b3:aa:6d:c8:04:ce:4e:ba:f6:29:4d:92:a3:94:b0:c2:ff:bd:bf:33:63:11:43:34:0f:51:b0:95:09:2f:63',
|
||||
'sha512': 'f7:07:4a:f0:b0:f0:e6:8b:95:5f:f9:e6:61:0a:32:68:f1..."
|
||||
subject_key_identifier:
|
||||
description:
|
||||
- The CSR's subject key identifier.
|
||||
- The identifier is returned in hexadecimal, with C(:) used to separate bytes.
|
||||
- Is C(none) if the C(SubjectKeyIdentifier) extension is not present.
|
||||
returned: success and if the pyOpenSSL backend is I(not) used
|
||||
type: str
|
||||
sample: '00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33'
|
||||
version_added: "2.9"
|
||||
authority_key_identifier:
|
||||
description:
|
||||
- The CSR's authority key identifier.
|
||||
- The identifier is returned in hexadecimal, with C(:) used to separate bytes.
|
||||
- Is C(none) if the C(AuthorityKeyIdentifier) extension is not present.
|
||||
returned: success and if the pyOpenSSL backend is I(not) used
|
||||
type: str
|
||||
sample: '00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22:33'
|
||||
version_added: "2.9"
|
||||
authority_cert_issuer:
|
||||
description:
|
||||
- The CSR's authority cert issuer as a list of general names.
|
||||
- Is C(none) if the C(AuthorityKeyIdentifier) extension is not present.
|
||||
returned: success and if the pyOpenSSL backend is I(not) used
|
||||
type: list
|
||||
sample: "[DNS:www.ansible.com, IP:1.2.3.4]"
|
||||
version_added: "2.9"
|
||||
authority_cert_serial_number:
|
||||
description:
|
||||
- The CSR's authority cert serial number.
|
||||
- Is C(none) if the C(AuthorityKeyIdentifier) extension is not present.
|
||||
returned: success and if the pyOpenSSL backend is I(not) used
|
||||
type: int
|
||||
sample: '12345'
|
||||
version_added: "2.9"
|
||||
'''
|
||||
|
||||
|
||||
import abc
|
||||
import binascii
|
||||
import os
|
||||
import traceback
|
||||
from distutils.version import LooseVersion
|
||||
|
@ -258,6 +293,14 @@ class CertificateSigningRequestInfo(crypto_utils.OpenSSLObject):
|
|||
def _get_public_key(self, binary):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def _get_subject_key_identifier(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def _get_authority_key_identifier(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def _get_all_extensions(self):
|
||||
pass
|
||||
|
@ -285,6 +328,21 @@ class CertificateSigningRequestInfo(crypto_utils.OpenSSLObject):
|
|||
pk = self._get_public_key(binary=True)
|
||||
result['public_key_fingerprints'] = crypto_utils.get_fingerprint_of_bytes(pk) if pk is not None else dict()
|
||||
|
||||
if self.backend != 'pyopenssl':
|
||||
ski = self._get_subject_key_identifier()
|
||||
if ski is not None:
|
||||
ski = to_native(binascii.hexlify(ski))
|
||||
ski = ':'.join([ski[i:i + 2] for i in range(0, len(ski), 2)])
|
||||
result['subject_key_identifier'] = ski
|
||||
|
||||
aki, aci, acsn = self._get_authority_key_identifier()
|
||||
if aki is not None:
|
||||
aki = to_native(binascii.hexlify(aki))
|
||||
aki = ':'.join([aki[i:i + 2] for i in range(0, len(aki), 2)])
|
||||
result['authority_key_identifier'] = aki
|
||||
result['authority_cert_issuer'] = aci
|
||||
result['authority_cert_serial_number'] = acsn
|
||||
|
||||
result['extensions_by_oid'] = self._get_all_extensions()
|
||||
|
||||
result['signature_valid'] = self._is_signature_valid()
|
||||
|
@ -394,6 +452,23 @@ class CertificateSigningRequestInfoCryptography(CertificateSigningRequestInfo):
|
|||
serialization.PublicFormat.SubjectPublicKeyInfo
|
||||
)
|
||||
|
||||
def _get_subject_key_identifier(self):
|
||||
try:
|
||||
ext = self.csr.extensions.get_extension_for_class(x509.SubjectKeyIdentifier)
|
||||
return ext.value.digest
|
||||
except cryptography.x509.ExtensionNotFound:
|
||||
return None
|
||||
|
||||
def _get_authority_key_identifier(self):
|
||||
try:
|
||||
ext = self.csr.extensions.get_extension_for_class(x509.AuthorityKeyIdentifier)
|
||||
issuer = None
|
||||
if ext.value.authority_cert_issuer is not None:
|
||||
issuer = [crypto_utils.cryptography_decode_name(san) for san in ext.value.authority_cert_issuer]
|
||||
return ext.value.key_identifier, issuer, ext.value.authority_cert_serial_number
|
||||
except cryptography.x509.ExtensionNotFound:
|
||||
return None, None, None
|
||||
|
||||
def _get_all_extensions(self):
|
||||
return crypto_utils.cryptography_get_extensions_from_csr(self.csr)
|
||||
|
||||
|
@ -486,6 +561,14 @@ class CertificateSigningRequestInfoPyOpenSSL(CertificateSigningRequestInfo):
|
|||
self.module.warn('Your pyOpenSSL version does not support dumping public keys. '
|
||||
'Please upgrade to version 16.0 or newer, or use the cryptography backend.')
|
||||
|
||||
def _get_subject_key_identifier(self):
|
||||
# Won't be implemented
|
||||
return None
|
||||
|
||||
def _get_authority_key_identifier(self):
|
||||
# Won't be implemented
|
||||
return None, None, None
|
||||
|
||||
def _get_all_extensions(self):
|
||||
return crypto_utils.pyopenssl_get_extensions_from_csr(self.csr)
|
||||
|
||||
|
|
|
@ -308,4 +308,134 @@
|
|||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: ownca_backup_5
|
||||
|
||||
- name: (OwnCA, {{select_crypto_backend}}) Create subject key identifier
|
||||
openssl_certificate:
|
||||
path: '{{ output_dir }}/ownca_cert_ski.pem'
|
||||
csr_path: '{{ output_dir }}/csr_ecc.csr'
|
||||
ownca_path: '{{ output_dir }}/ca_cert.pem'
|
||||
ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
provider: ownca
|
||||
ownca_digest: sha256
|
||||
ownca_create_subject_key_identifier: always_create
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: ownca_subject_key_identifier_1
|
||||
|
||||
- name: (OwnCA, {{select_crypto_backend}}) Create subject key identifier (idempotency)
|
||||
openssl_certificate:
|
||||
path: '{{ output_dir }}/ownca_cert_ski.pem'
|
||||
csr_path: '{{ output_dir }}/csr_ecc.csr'
|
||||
ownca_path: '{{ output_dir }}/ca_cert.pem'
|
||||
ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
provider: ownca
|
||||
ownca_digest: sha256
|
||||
ownca_create_subject_key_identifier: always_create
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: ownca_subject_key_identifier_2
|
||||
|
||||
- name: (OwnCA, {{select_crypto_backend}}) Create subject key identifier (remove)
|
||||
openssl_certificate:
|
||||
path: '{{ output_dir }}/ownca_cert_ski.pem'
|
||||
csr_path: '{{ output_dir }}/csr_ecc.csr'
|
||||
ownca_path: '{{ output_dir }}/ca_cert.pem'
|
||||
ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
provider: ownca
|
||||
ownca_digest: sha256
|
||||
ownca_create_subject_key_identifier: never_create
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: ownca_subject_key_identifier_3
|
||||
|
||||
- name: (OwnCA, {{select_crypto_backend}}) Create subject key identifier (remove idempotency)
|
||||
openssl_certificate:
|
||||
path: '{{ output_dir }}/ownca_cert_ski.pem'
|
||||
csr_path: '{{ output_dir }}/csr_ecc.csr'
|
||||
ownca_path: '{{ output_dir }}/ca_cert.pem'
|
||||
ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
provider: ownca
|
||||
ownca_digest: sha256
|
||||
ownca_create_subject_key_identifier: never_create
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: ownca_subject_key_identifier_4
|
||||
|
||||
- name: (OwnCA, {{select_crypto_backend}}) Create subject key identifier (re-enable)
|
||||
openssl_certificate:
|
||||
path: '{{ output_dir }}/ownca_cert_ski.pem'
|
||||
csr_path: '{{ output_dir }}/csr_ecc.csr'
|
||||
ownca_path: '{{ output_dir }}/ca_cert.pem'
|
||||
ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
provider: ownca
|
||||
ownca_digest: sha256
|
||||
ownca_create_subject_key_identifier: always_create
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: ownca_subject_key_identifier_5
|
||||
|
||||
- name: (OwnCA, {{select_crypto_backend}}) Create authority key identifier
|
||||
openssl_certificate:
|
||||
path: '{{ output_dir }}/ownca_cert_aki.pem'
|
||||
csr_path: '{{ output_dir }}/csr_ecc.csr'
|
||||
ownca_path: '{{ output_dir }}/ca_cert.pem'
|
||||
ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
provider: ownca
|
||||
ownca_digest: sha256
|
||||
ownca_create_authority_key_identifier: yes
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: ownca_authority_key_identifier_1
|
||||
|
||||
- name: (OwnCA, {{select_crypto_backend}}) Create authority key identifier (idempotency)
|
||||
openssl_certificate:
|
||||
path: '{{ output_dir }}/ownca_cert_aki.pem'
|
||||
csr_path: '{{ output_dir }}/csr_ecc.csr'
|
||||
ownca_path: '{{ output_dir }}/ca_cert.pem'
|
||||
ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
provider: ownca
|
||||
ownca_digest: sha256
|
||||
ownca_create_authority_key_identifier: yes
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: ownca_authority_key_identifier_2
|
||||
|
||||
- name: (OwnCA, {{select_crypto_backend}}) Create authority key identifier (remove)
|
||||
openssl_certificate:
|
||||
path: '{{ output_dir }}/ownca_cert_aki.pem'
|
||||
csr_path: '{{ output_dir }}/csr_ecc.csr'
|
||||
ownca_path: '{{ output_dir }}/ca_cert.pem'
|
||||
ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
provider: ownca
|
||||
ownca_digest: sha256
|
||||
ownca_create_authority_key_identifier: no
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: ownca_authority_key_identifier_3
|
||||
|
||||
- name: (OwnCA, {{select_crypto_backend}}) Create authority key identifier (remove idempotency)
|
||||
openssl_certificate:
|
||||
path: '{{ output_dir }}/ownca_cert_aki.pem'
|
||||
csr_path: '{{ output_dir }}/csr_ecc.csr'
|
||||
ownca_path: '{{ output_dir }}/ca_cert.pem'
|
||||
ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
provider: ownca
|
||||
ownca_digest: sha256
|
||||
ownca_create_authority_key_identifier: no
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: ownca_authority_key_identifier_4
|
||||
|
||||
- name: (OwnCA, {{select_crypto_backend}}) Create authority key identifier (re-add)
|
||||
openssl_certificate:
|
||||
path: '{{ output_dir }}/ownca_cert_aki.pem'
|
||||
csr_path: '{{ output_dir }}/csr_ecc.csr'
|
||||
ownca_path: '{{ output_dir }}/ca_cert.pem'
|
||||
ownca_privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
provider: ownca
|
||||
ownca_digest: sha256
|
||||
ownca_create_authority_key_identifier: yes
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: ownca_authority_key_identifier_5
|
||||
|
||||
- import_tasks: ../tests/validate_ownca.yml
|
||||
|
|
|
@ -308,4 +308,64 @@
|
|||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: selfsigned_backup_5
|
||||
|
||||
- name: (Selfsigned, {{select_crypto_backend}}) Create subject key identifier test
|
||||
openssl_certificate:
|
||||
path: '{{ output_dir }}/selfsigned_cert_ski.pem'
|
||||
csr_path: '{{ output_dir }}/csr_ecc.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey_ecc.pem'
|
||||
provider: selfsigned
|
||||
selfsigned_digest: sha256
|
||||
selfsigned_create_subject_key_identifier: always_create
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: selfsigned_subject_key_identifier_1
|
||||
|
||||
- name: (Selfsigned, {{select_crypto_backend}}) Create subject key identifier test (idempotency)
|
||||
openssl_certificate:
|
||||
path: '{{ output_dir }}/selfsigned_cert_ski.pem'
|
||||
csr_path: '{{ output_dir }}/csr_ecc.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey_ecc.pem'
|
||||
provider: selfsigned
|
||||
selfsigned_digest: sha256
|
||||
selfsigned_create_subject_key_identifier: always_create
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: selfsigned_subject_key_identifier_2
|
||||
|
||||
- name: (Selfsigned, {{select_crypto_backend}}) Create subject key identifier test (remove)
|
||||
openssl_certificate:
|
||||
path: '{{ output_dir }}/selfsigned_cert_ski.pem'
|
||||
csr_path: '{{ output_dir }}/csr_ecc.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey_ecc.pem'
|
||||
provider: selfsigned
|
||||
selfsigned_digest: sha256
|
||||
selfsigned_create_subject_key_identifier: never_create
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: selfsigned_subject_key_identifier_3
|
||||
|
||||
- name: (Selfsigned, {{select_crypto_backend}}) Create subject key identifier test (remove idempotency)
|
||||
openssl_certificate:
|
||||
path: '{{ output_dir }}/selfsigned_cert_ski.pem'
|
||||
csr_path: '{{ output_dir }}/csr_ecc.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey_ecc.pem'
|
||||
provider: selfsigned
|
||||
selfsigned_digest: sha256
|
||||
selfsigned_create_subject_key_identifier: never_create
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: selfsigned_subject_key_identifier_4
|
||||
|
||||
- name: (Selfsigned, {{select_crypto_backend}}) Create subject key identifier test (re-enable)
|
||||
openssl_certificate:
|
||||
path: '{{ output_dir }}/selfsigned_cert_ski.pem'
|
||||
csr_path: '{{ output_dir }}/csr_ecc.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey_ecc.pem'
|
||||
provider: selfsigned
|
||||
selfsigned_digest: sha256
|
||||
selfsigned_create_subject_key_identifier: always_create
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: selfsigned_subject_key_identifier_5
|
||||
|
||||
- import_tasks: ../tests/validate_selfsigned.yml
|
||||
|
|
|
@ -120,3 +120,23 @@
|
|||
- ownca_backup_4.backup_file is string
|
||||
- ownca_backup_5 is not changed
|
||||
- ownca_backup_5.backup_file is undefined
|
||||
|
||||
- name: Check create subject key identifier
|
||||
assert:
|
||||
that:
|
||||
- ownca_subject_key_identifier_1 is changed
|
||||
- ownca_subject_key_identifier_2 is not changed
|
||||
- ownca_subject_key_identifier_3 is changed
|
||||
- ownca_subject_key_identifier_4 is not changed
|
||||
- ownca_subject_key_identifier_5 is changed
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
|
||||
- name: Check create authority key identifier
|
||||
assert:
|
||||
that:
|
||||
- ownca_authority_key_identifier_1 is changed
|
||||
- ownca_authority_key_identifier_2 is not changed
|
||||
- ownca_authority_key_identifier_3 is changed
|
||||
- ownca_authority_key_identifier_4 is not changed
|
||||
- ownca_authority_key_identifier_5 is changed
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
|
|
|
@ -126,3 +126,13 @@
|
|||
- selfsigned_backup_4.backup_file is string
|
||||
- selfsigned_backup_5 is not changed
|
||||
- selfsigned_backup_5.backup_file is undefined
|
||||
|
||||
- name: Check create subject key identifier
|
||||
assert:
|
||||
that:
|
||||
- selfsigned_subject_key_identifier_1 is changed
|
||||
- selfsigned_subject_key_identifier_2 is not changed
|
||||
- selfsigned_subject_key_identifier_3 is changed
|
||||
- selfsigned_subject_key_identifier_4 is not changed
|
||||
- selfsigned_subject_key_identifier_5 is changed
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
|
|
|
@ -18,6 +18,19 @@
|
|||
- "['organizationalUnitName', 'Crypto Department'] in result.subject_ordered"
|
||||
- "['organizationalUnitName', 'ACME Department'] in result.subject_ordered"
|
||||
|
||||
- name: Check SubjectKeyIdentifier and AuthorityKeyIdentifier
|
||||
assert:
|
||||
that:
|
||||
- result.subject_key_identifier == "00:11:22:33"
|
||||
- result.authority_key_identifier == "44:55:66:77"
|
||||
- result.authority_cert_issuer == expected_authority_cert_issuer
|
||||
- result.authority_cert_serial_number == 12345
|
||||
vars:
|
||||
expected_authority_cert_issuer:
|
||||
- "DNS:ca.example.org"
|
||||
- "IP:1.2.3.4"
|
||||
when: select_crypto_backend != 'pyopenssl' and cryptography_version.stdout is version('1.3', '>=')
|
||||
|
||||
- name: Update result list
|
||||
set_fact:
|
||||
info_results: "{{ info_results + [result] }}"
|
||||
|
@ -47,6 +60,18 @@
|
|||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: result
|
||||
|
||||
- name: Check AuthorityKeyIdentifier
|
||||
assert:
|
||||
that:
|
||||
- result.authority_key_identifier is none
|
||||
- result.authority_cert_issuer == expected_authority_cert_issuer
|
||||
- result.authority_cert_serial_number == 12345
|
||||
vars:
|
||||
expected_authority_cert_issuer:
|
||||
- "DNS:ca.example.org"
|
||||
- "IP:1.2.3.4"
|
||||
when: select_crypto_backend != 'pyopenssl' and cryptography_version.stdout is version('1.3', '>=')
|
||||
|
||||
- name: Update result list
|
||||
set_fact:
|
||||
info_results: "{{ info_results + [result] }}"
|
||||
|
@ -57,6 +82,14 @@
|
|||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: result
|
||||
|
||||
- name: Check AuthorityKeyIdentifier
|
||||
assert:
|
||||
that:
|
||||
- result.authority_key_identifier == "44:55:66:77"
|
||||
- result.authority_cert_issuer is none
|
||||
- result.authority_cert_serial_number is none
|
||||
when: select_crypto_backend != 'pyopenssl' and cryptography_version.stdout is version('1.3', '>=')
|
||||
|
||||
- name: Update result list
|
||||
set_fact:
|
||||
info_results: "{{ info_results + [result] }}"
|
||||
|
|
|
@ -69,6 +69,14 @@
|
|||
- "pathlen:23"
|
||||
basic_constraints_critical: yes
|
||||
ocsp_must_staple: yes
|
||||
subject_key_identifier: '{{ "00:11:22:33" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
authority_key_identifier: '{{ "44:55:66:77" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
authority_cert_issuer: '{{ value_for_authority_cert_issuer if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
authority_cert_serial_number: '{{ 12345 if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
vars:
|
||||
value_for_authority_cert_issuer:
|
||||
- "DNS:ca.example.org"
|
||||
- "IP:1.2.3.4"
|
||||
|
||||
- name: Generate CSR 2
|
||||
openssl_csr:
|
||||
|
@ -90,12 +98,19 @@
|
|||
- "IP:DEAD:BEEF::1"
|
||||
basic_constraints:
|
||||
- "CA:FALSE"
|
||||
authority_cert_issuer: '{{ value_for_authority_cert_issuer if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
authority_cert_serial_number: '{{ 12345 if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
vars:
|
||||
value_for_authority_cert_issuer:
|
||||
- "DNS:ca.example.org"
|
||||
- "IP:1.2.3.4"
|
||||
|
||||
- name: Generate CSR 4
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_4.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
useCommonNameForSAN: no
|
||||
authority_key_identifier: '{{ "44:55:66:77" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
|
||||
- name: Generate selfsigned certificates
|
||||
openssl_certificate:
|
||||
|
@ -147,7 +162,14 @@
|
|||
- name: Compare results
|
||||
assert:
|
||||
that:
|
||||
- item.0 == item.1
|
||||
- ' (item.0 | dict2items | rejectattr("key", "in", keys_to_ignore) | list | items2dict)
|
||||
== (item.1 | dict2items | rejectattr("key", "in", keys_to_ignore) | list | items2dict)'
|
||||
quiet: yes
|
||||
loop: "{{ pyopenssl_info_results | zip(cryptography_info_results) | list }}"
|
||||
when: pyopenssl_version.stdout is version('0.15', '>=') and cryptography_version.stdout is version('1.6', '>=')
|
||||
vars:
|
||||
keys_to_ignore:
|
||||
- subject_key_identifier
|
||||
- authority_key_identifier
|
||||
- authority_cert_issuer
|
||||
- authority_cert_serial_number
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
def compatibility_in_test(a, b):
|
||||
return a in b
|
||||
|
||||
|
||||
class TestModule:
|
||||
''' Ansible math jinja2 tests '''
|
||||
|
||||
def tests(self):
|
||||
return {
|
||||
'in': compatibility_in_test,
|
||||
}
|
|
@ -339,6 +339,179 @@
|
|||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: csr_backup_5
|
||||
|
||||
- name: Generate CSR with subject key identifier
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_ski.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
subject_key_identifier: "00:11:22:33"
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: subject_key_identifier_1
|
||||
|
||||
- name: Generate CSR with subject key identifier (idempotency)
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_ski.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
subject_key_identifier: "00:11:22:33"
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: subject_key_identifier_2
|
||||
|
||||
- name: Generate CSR with subject key identifier (change)
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_ski.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
subject_key_identifier: "44:55:66:77:88"
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: subject_key_identifier_3
|
||||
|
||||
- name: Generate CSR with subject key identifier (auto-create)
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_ski.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
create_subject_key_identifier: yes
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: subject_key_identifier_4
|
||||
|
||||
- name: Generate CSR with subject key identifier (auto-create idempotency)
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_ski.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
create_subject_key_identifier: yes
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: subject_key_identifier_5
|
||||
|
||||
- name: Generate CSR with subject key identifier (remove)
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_ski.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: subject_key_identifier_6
|
||||
|
||||
- name: Generate CSR with authority key identifier
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_aki.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
authority_key_identifier: "00:11:22:33"
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: authority_key_identifier_1
|
||||
|
||||
- name: Generate CSR with authority key identifier (idempotency)
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_aki.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
authority_key_identifier: "00:11:22:33"
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: authority_key_identifier_2
|
||||
|
||||
- name: Generate CSR with authority key identifier (change)
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_aki.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
authority_key_identifier: "44:55:66:77:88"
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: authority_key_identifier_3
|
||||
|
||||
- name: Generate CSR with authority key identifier (remove)
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_aki.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: authority_key_identifier_4
|
||||
|
||||
- name: Generate CSR with authority cert issuer / serial number
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_acisn.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
authority_cert_issuer:
|
||||
- "DNS:ca.example.org"
|
||||
- "IP:1.2.3.4"
|
||||
authority_cert_serial_number: 12345
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: authority_cert_issuer_sn_1
|
||||
|
||||
- name: Generate CSR with authority cert issuer / serial number (idempotency)
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_acisn.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
authority_cert_issuer:
|
||||
- "DNS:ca.example.org"
|
||||
- "IP:1.2.3.4"
|
||||
authority_cert_serial_number: 12345
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: authority_cert_issuer_sn_2
|
||||
|
||||
- name: Generate CSR with authority cert issuer / serial number (change issuer)
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_acisn.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
authority_cert_issuer:
|
||||
- "IP:1.2.3.4"
|
||||
- "DNS:ca.example.org"
|
||||
authority_cert_serial_number: 12345
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: authority_cert_issuer_sn_3
|
||||
|
||||
- name: Generate CSR with authority cert issuer / serial number (change serial number)
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_acisn.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
authority_cert_issuer:
|
||||
- "IP:1.2.3.4"
|
||||
- "DNS:ca.example.org"
|
||||
authority_cert_serial_number: 54321
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: authority_cert_issuer_sn_4
|
||||
|
||||
- name: Generate CSR with authority cert issuer / serial number (remove)
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_acisn.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
register: authority_cert_issuer_sn_5
|
||||
|
||||
- name: Generate CSR with everything
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_everything.csr'
|
||||
|
@ -396,7 +569,15 @@
|
|||
- "pathlen:23"
|
||||
basic_constraints_critical: yes
|
||||
ocsp_must_staple: yes
|
||||
subject_key_identifier: '{{ "00:11:22:33" if select_crypto_backend != "pyopenssl" else omit }}'
|
||||
authority_key_identifier: '{{ "44:55:66:77" if select_crypto_backend != "pyopenssl" else omit }}'
|
||||
authority_cert_issuer: '{{ value_for_authority_cert_issuer if select_crypto_backend != "pyopenssl" else omit }}'
|
||||
authority_cert_serial_number: '{{ 12345 if select_crypto_backend != "pyopenssl" else omit }}'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
vars:
|
||||
value_for_authority_cert_issuer:
|
||||
- "DNS:ca.example.org"
|
||||
- "IP:1.2.3.4"
|
||||
register: everything_1
|
||||
|
||||
- name: Generate CSR with everything (idempotent, check mode)
|
||||
|
@ -456,7 +637,15 @@
|
|||
- "pathlen:23"
|
||||
basic_constraints_critical: yes
|
||||
ocsp_must_staple: yes
|
||||
subject_key_identifier: '{{ "00:11:22:33" if select_crypto_backend != "pyopenssl" else omit }}'
|
||||
authority_key_identifier: '{{ "44:55:66:77" if select_crypto_backend != "pyopenssl" else omit }}'
|
||||
authority_cert_issuer: '{{ value_for_authority_cert_issuer if select_crypto_backend != "pyopenssl" else omit }}'
|
||||
authority_cert_serial_number: '{{ 12345 if select_crypto_backend != "pyopenssl" else omit }}'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
vars:
|
||||
value_for_authority_cert_issuer:
|
||||
- "DNS:ca.example.org"
|
||||
- "IP:1.2.3.4"
|
||||
check_mode: yes
|
||||
register: everything_2
|
||||
|
||||
|
@ -517,5 +706,13 @@
|
|||
- "pathlen:23"
|
||||
basic_constraints_critical: yes
|
||||
ocsp_must_staple: yes
|
||||
subject_key_identifier: '{{ "00:11:22:33" if select_crypto_backend != "pyopenssl" else omit }}'
|
||||
authority_key_identifier: '{{ "44:55:66:77" if select_crypto_backend != "pyopenssl" else omit }}'
|
||||
authority_cert_issuer: '{{ value_for_authority_cert_issuer if select_crypto_backend != "pyopenssl" else omit }}'
|
||||
authority_cert_serial_number: '{{ 12345 if select_crypto_backend != "pyopenssl" else omit }}'
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
vars:
|
||||
value_for_authority_cert_issuer:
|
||||
- "DNS:ca.example.org"
|
||||
- "IP:1.2.3.4"
|
||||
register: everything_3
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
select_crypto_backend: pyopenssl
|
||||
|
||||
- import_tasks: ../tests/validate.yml
|
||||
vars:
|
||||
select_crypto_backend: pyopenssl
|
||||
|
||||
when: pyopenssl_version.stdout is version('0.15', '>=')
|
||||
|
||||
|
@ -36,5 +38,7 @@
|
|||
select_crypto_backend: cryptography
|
||||
|
||||
- import_tasks: ../tests/validate.yml
|
||||
vars:
|
||||
select_crypto_backend: pyopenssl
|
||||
|
||||
when: cryptography_version.stdout is version('1.3', '>=')
|
||||
|
|
|
@ -125,6 +125,36 @@
|
|||
that:
|
||||
- output_broken is changed
|
||||
|
||||
- name: Verify that subject key identifier handling works
|
||||
assert:
|
||||
that:
|
||||
- subject_key_identifier_1 is changed
|
||||
- subject_key_identifier_2 is not changed
|
||||
- subject_key_identifier_3 is changed
|
||||
- subject_key_identifier_4 is changed
|
||||
- subject_key_identifier_5 is not changed
|
||||
- subject_key_identifier_6 is not changed
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
|
||||
- name: Verify that authority key identifier handling works
|
||||
assert:
|
||||
that:
|
||||
- authority_key_identifier_1 is changed
|
||||
- authority_key_identifier_2 is not changed
|
||||
- authority_key_identifier_3 is changed
|
||||
- authority_key_identifier_4 is changed
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
|
||||
- name: Verify that authority cert issuer / serial number handling works
|
||||
assert:
|
||||
that:
|
||||
- authority_cert_issuer_sn_1 is changed
|
||||
- authority_cert_issuer_sn_2 is not changed
|
||||
- authority_cert_issuer_sn_3 is changed
|
||||
- authority_cert_issuer_sn_4 is changed
|
||||
- authority_cert_issuer_sn_5 is changed
|
||||
when: select_crypto_backend != 'pyopenssl'
|
||||
|
||||
- name: Check backup
|
||||
assert:
|
||||
that:
|
||||
|
|
|
@ -15,6 +15,19 @@
|
|||
- "['organizationalUnitName', 'Crypto Department'] in result.subject_ordered"
|
||||
- "['organizationalUnitName', 'ACME Department'] in result.subject_ordered"
|
||||
|
||||
- name: Check SubjectKeyIdentifier and AuthorityKeyIdentifier
|
||||
assert:
|
||||
that:
|
||||
- result.subject_key_identifier == "00:11:22:33"
|
||||
- result.authority_key_identifier == "44:55:66:77"
|
||||
- result.authority_cert_issuer == expected_authority_cert_issuer
|
||||
- result.authority_cert_serial_number == 12345
|
||||
vars:
|
||||
expected_authority_cert_issuer:
|
||||
- "DNS:ca.example.org"
|
||||
- "IP:1.2.3.4"
|
||||
when: select_crypto_backend != 'pyopenssl' and cryptography_version.stdout is version('1.3', '>=')
|
||||
|
||||
- name: Update result list
|
||||
set_fact:
|
||||
info_results: "{{ info_results + [result] }}"
|
||||
|
@ -35,6 +48,18 @@
|
|||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: result
|
||||
|
||||
- name: Check AuthorityKeyIdentifier
|
||||
assert:
|
||||
that:
|
||||
- result.authority_key_identifier is none
|
||||
- result.authority_cert_issuer == expected_authority_cert_issuer
|
||||
- result.authority_cert_serial_number == 12345
|
||||
vars:
|
||||
expected_authority_cert_issuer:
|
||||
- "DNS:ca.example.org"
|
||||
- "IP:1.2.3.4"
|
||||
when: select_crypto_backend != 'pyopenssl' and cryptography_version.stdout is version('1.3', '>=')
|
||||
|
||||
- name: Update result list
|
||||
set_fact:
|
||||
info_results: "{{ info_results + [result] }}"
|
||||
|
@ -45,6 +70,14 @@
|
|||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
register: result
|
||||
|
||||
- name: Check AuthorityKeyIdentifier
|
||||
assert:
|
||||
that:
|
||||
- result.authority_key_identifier == "44:55:66:77"
|
||||
- result.authority_cert_issuer is none
|
||||
- result.authority_cert_serial_number is none
|
||||
when: select_crypto_backend != 'pyopenssl' and cryptography_version.stdout is version('1.3', '>=')
|
||||
|
||||
- name: Update result list
|
||||
set_fact:
|
||||
info_results: "{{ info_results + [result] }}"
|
||||
|
|
|
@ -69,6 +69,14 @@
|
|||
- "pathlen:23"
|
||||
basic_constraints_critical: yes
|
||||
ocsp_must_staple: yes
|
||||
subject_key_identifier: '{{ "00:11:22:33" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
authority_key_identifier: '{{ "44:55:66:77" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
authority_cert_issuer: '{{ value_for_authority_cert_issuer if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
authority_cert_serial_number: '{{ 12345 if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
vars:
|
||||
value_for_authority_cert_issuer:
|
||||
- "DNS:ca.example.org"
|
||||
- "IP:1.2.3.4"
|
||||
|
||||
- name: Generate CSR 2
|
||||
openssl_csr:
|
||||
|
@ -90,12 +98,19 @@
|
|||
- "IP:DEAD:BEEF::1"
|
||||
basic_constraints:
|
||||
- "CA:FALSE"
|
||||
authority_cert_issuer: '{{ value_for_authority_cert_issuer if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
authority_cert_serial_number: '{{ 12345 if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
vars:
|
||||
value_for_authority_cert_issuer:
|
||||
- "DNS:ca.example.org"
|
||||
- "IP:1.2.3.4"
|
||||
|
||||
- name: Generate CSR 4
|
||||
openssl_csr:
|
||||
path: '{{ output_dir }}/csr_4.csr'
|
||||
privatekey_path: '{{ output_dir }}/privatekey.pem'
|
||||
useCommonNameForSAN: no
|
||||
authority_key_identifier: '{{ "44:55:66:77" if cryptography_version.stdout is version("1.3", ">=") else omit }}'
|
||||
|
||||
- name: Prepare result list
|
||||
set_fact:
|
||||
|
@ -132,7 +147,14 @@
|
|||
- name: Compare results
|
||||
assert:
|
||||
that:
|
||||
- item.0 == item.1
|
||||
- ' (item.0 | dict2items | rejectattr("key", "in", keys_to_ignore) | list | items2dict)
|
||||
== (item.1 | dict2items | rejectattr("key", "in", keys_to_ignore) | list | items2dict)'
|
||||
quiet: yes
|
||||
loop: "{{ pyopenssl_info_results | zip(cryptography_info_results) | list }}"
|
||||
when: pyopenssl_version.stdout is version('0.15', '>=') and cryptography_version.stdout is version('1.3', '>=')
|
||||
vars:
|
||||
keys_to_ignore:
|
||||
- subject_key_identifier
|
||||
- authority_key_identifier
|
||||
- authority_cert_issuer
|
||||
- authority_cert_serial_number
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
def compatibility_in_test(a, b):
|
||||
return a in b
|
||||
|
||||
|
||||
class TestModule:
|
||||
''' Ansible math jinja2 tests '''
|
||||
|
||||
def tests(self):
|
||||
return {
|
||||
'in': compatibility_in_test,
|
||||
}
|
Loading…
Reference in a new issue