openssl_csr: allow to specify CRL distribution endpoints (#167)

* Improve error messages for name decoding (not all names appear in SANs).

* Refactor DN parsing, add relative DN parsing code.

* Allow to specify CRL distribution points.

* Add changelog fragment.

* Fix typo.

* Make sure value argument to x509.NameAttribute is a text.

* Update changelogs/fragments/167-openssl_csr-crl-distribution-points.yml

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>

* Add example.

Co-authored-by: Andrew Klychkov <aaklychkov@mail.ru>
pull/178/head
Felix Fontein 2021-01-26 09:57:40 +01:00 committed by GitHub
parent a7c06b2ec4
commit d8ccebce60
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 306 additions and 43 deletions

View File

@ -0,0 +1,2 @@
minor_changes:
- "openssl_csr, openssl_csr_pipe - allow to specify CRL distribution endpoints with ``crl_distribution_points`` (https://github.com/ansible-collections/community.crypto/issues/147, https://github.com/ansible-collections/community.crypto/pull/167)."

View File

@ -260,6 +260,48 @@ options:
- The C(AuthorityKeyIdentifier) will only be added if at least one of I(authority_key_identifier), - 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. I(authority_cert_issuer) and I(authority_cert_serial_number) is specified.
type: int type: int
crl_distribution_points:
description:
- Allows to specify one or multiple CRL distribution points.
- Only supported by the C(cryptography) backend.
type: list
elements: dict
suboptions:
full_name:
description:
- Describes how the CRL can be retrieved.
- Mutually exclusive with I(relative_name).
- "Example: C(URI:https://ca.example.com/revocations.crl)."
type: list
elements: str
relative_name:
description:
- Describes how the CRL can be retrieved relative to the CRL issuer.
- Mutually exclusive with I(full_name).
- "Example: C(/CN=example.com)."
- Can only be used when cryptography >= 1.6 is installed.
type: list
elements: str
crl_issuer:
description:
- Information about the issuer of the CRL.
type: list
elements: str
reasons:
description:
- List of reasons that this distribution point can be used for when performing revocation checks.
type: list
elements: str
choices:
- key_compromise
- ca_compromise
- affiliation_changed
- superseded
- cessation_of_operation
- certificate_hold
- privilege_withdrawn
- aa_compromise
version_added: 1.4.0
notes: notes:
- If the certificate signing request already exists it will be checked whether subjectAltName, - If the certificate signing request already exists it will be checked whether subjectAltName,
keyUsage, extendedKeyUsage and basicConstraints only contain the requested values, whether keyUsage, extendedKeyUsage and basicConstraints only contain the requested values, whether

View File

@ -152,6 +152,36 @@ def _parse_hex(bytesstr):
return data return data
DN_COMPONENT_START_RE = re.compile(r'^ *([a-zA-z0-9]+) *= *')
def _parse_dn_component(name, sep=',', sep_str='\\', decode_remainder=True):
m = DN_COMPONENT_START_RE.match(name)
if not m:
raise OpenSSLObjectError('cannot start part in "{0}"'.format(name))
oid = cryptography_name_to_oid(m.group(1))
idx = len(m.group(0))
decoded_name = []
if decode_remainder:
length = len(name)
while idx < length:
i = idx
while i < length and name[i] not in sep_str:
i += 1
if i > idx:
decoded_name.append(name[idx:i])
idx = i
while idx + 1 < length and name[idx] == '\\':
decoded_name.append(name[idx + 1])
idx += 2
if idx < length and name[idx] == sep:
break
else:
decoded_name.append(name[idx:])
idx = len(name)
return x509.NameAttribute(oid, ''.join(decoded_name)), name[idx:]
def _parse_dn(name): def _parse_dn(name):
''' '''
Parse a Distinguished Name. Parse a Distinguished Name.
@ -166,29 +196,12 @@ def _parse_dn(name):
name = name[1:] name = name[1:]
sep_str = sep + '\\' sep_str = sep + '\\'
result = [] result = []
start_re = re.compile(r'^ *([a-zA-z0-9]+) *= *')
while name: while name:
m = start_re.match(name) try:
if not m: attribute, name = _parse_dn_component(name, sep=sep, sep_str=sep_str)
raise OpenSSLObjectError('Error while parsing distinguished name "{0}": cannot start part in "{1}"'.format(original_name, name)) except OpenSSLObjectError as e:
oid = cryptography_name_to_oid(m.group(1)) raise OpenSSLObjectError('Error while parsing distinguished name "{0}": {1}'.format(original_name, e))
idx = len(m.group(0)) result.append(attribute)
decoded_name = []
length = len(name)
while idx < length:
i = idx
while i < length and name[i] not in sep_str:
i += 1
if i > idx:
decoded_name.append(name[idx:i])
idx = i
while idx + 1 < length and name[idx] == '\\':
decoded_name.append(name[idx + 1])
idx += 2
if idx < length and name[idx] == sep:
break
result.append(x509.NameAttribute(oid, ''.join(decoded_name)))
name = name[idx:]
if name: if name:
if name[0] != sep or len(name) < 2: if name[0] != sep or len(name) < 2:
raise OpenSSLObjectError('Error while parsing distinguished name "{0}": unexpected end of string'.format(original_name)) raise OpenSSLObjectError('Error while parsing distinguished name "{0}": unexpected end of string'.format(original_name))
@ -196,9 +209,19 @@ def _parse_dn(name):
return result return result
def cryptography_get_name(name): def cryptography_parse_relative_distinguished_name(rdn):
names = []
for part in rdn:
try:
names.append(_parse_dn_component(to_text(part), decode_remainder=False)[0])
except OpenSSLObjectError as e:
raise OpenSSLObjectError('Error while parsing relative distinguished name "{0}": {1}'.format(part, e))
return cryptography.x509.RelativeDistinguishedName(names)
def cryptography_get_name(name, what='Subject Alternative Name'):
''' '''
Given a name string, returns a cryptography x509.Name object. Given a name string, returns a cryptography x509.GeneralName object.
Raises an OpenSSLObjectError if the name is unknown or cannot be parsed. Raises an OpenSSLObjectError if the name is unknown or cannot be parsed.
''' '''
try: try:
@ -216,7 +239,7 @@ def cryptography_get_name(name):
if name.startswith('RID:'): if name.startswith('RID:'):
m = re.match(r'^([0-9]+(?:\.[0-9]+)*)$', to_text(name[4:])) m = re.match(r'^([0-9]+(?:\.[0-9]+)*)$', to_text(name[4:]))
if not m: if not m:
raise OpenSSLObjectError('Cannot parse Subject Alternative Name "{0}"'.format(name)) raise OpenSSLObjectError('Cannot parse {what} "{name}"'.format(name=name, what=what))
return x509.RegisteredID(x509.oid.ObjectIdentifier(m.group(1))) return x509.RegisteredID(x509.oid.ObjectIdentifier(m.group(1)))
if name.startswith('otherName:'): if name.startswith('otherName:'):
# otherName can either be a raw ASN.1 hex string or in the format that OpenSSL works with. # otherName can either be a raw ASN.1 hex string or in the format that OpenSSL works with.
@ -228,9 +251,9 @@ def cryptography_get_name(name):
# defailts on the format expected. # defailts on the format expected.
name = to_text(name[10:], errors='surrogate_or_strict') name = to_text(name[10:], errors='surrogate_or_strict')
if ';' not in name: if ';' not in name:
raise OpenSSLObjectError('Cannot parse Subject Alternative Name otherName "{0}", must be in the ' raise OpenSSLObjectError('Cannot parse {what} otherName "{name}", must be in the '
'format "otherName:<OID>;<ASN.1 OpenSSL Encoded String>" or ' 'format "otherName:<OID>;<ASN.1 OpenSSL Encoded String>" or '
'"otherName:<OID>;<hex string>"'.format(name)) '"otherName:<OID>;<hex string>"'.format(name=name, what=what))
oid, value = name.split(';', 1) oid, value = name.split(';', 1)
b_value = serialize_asn1_string_as_der(value) b_value = serialize_asn1_string_as_der(value)
@ -238,10 +261,10 @@ def cryptography_get_name(name):
if name.startswith('dirName:'): if name.startswith('dirName:'):
return x509.DirectoryName(x509.Name(_parse_dn(to_text(name[8:])))) return x509.DirectoryName(x509.Name(_parse_dn(to_text(name[8:]))))
except Exception as e: except Exception as e:
raise OpenSSLObjectError('Cannot parse Subject Alternative Name "{0}": {1}'.format(name, e)) raise OpenSSLObjectError('Cannot parse {what} "{name}": {error}'.format(name=name, what=what, error=e))
if ':' not in name: if ':' not in name:
raise OpenSSLObjectError('Cannot parse Subject Alternative Name "{0}" (forgot "DNS:" prefix?)'.format(name)) raise OpenSSLObjectError('Cannot parse {what} "{name}" (forgot "DNS:" prefix?)'.format(name=name, what=what))
raise OpenSSLObjectError('Cannot parse Subject Alternative Name "{0}" (potentially unsupported by cryptography backend)'.format(name)) raise OpenSSLObjectError('Cannot parse {what} "{name}" (potentially unsupported by cryptography backend)'.format(name=name, what=what))
def _dn_escape_value(value): def _dn_escape_value(value):
@ -258,7 +281,7 @@ def _dn_escape_value(value):
def cryptography_decode_name(name): def cryptography_decode_name(name):
''' '''
Given a cryptography x509.Name object, returns a string. Given a cryptography x509.GeneralName object, returns a string.
Raises an OpenSSLObjectError if the name is not supported. Raises an OpenSSLObjectError if the name is not supported.
''' '''
if isinstance(name, x509.DNSName): if isinstance(name, x509.DNSName):

View File

@ -36,6 +36,11 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto.cryptograp
cryptography_name_to_oid, cryptography_name_to_oid,
cryptography_key_needs_digest_for_signing, cryptography_key_needs_digest_for_signing,
cryptography_parse_key_usage_params, cryptography_parse_key_usage_params,
cryptography_parse_relative_distinguished_name,
)
from ansible_collections.community.crypto.plugins.module_utils.crypto.cryptography_crl import (
REVOCATION_REASON_MAP,
) )
from ansible_collections.community.crypto.plugins.module_utils.crypto.pyopenssl_support import ( from ansible_collections.community.crypto.plugins.module_utils.crypto.pyopenssl_support import (
@ -128,6 +133,7 @@ class CertificateSigningRequestBackend(object):
self.authority_key_identifier = module.params['authority_key_identifier'] self.authority_key_identifier = module.params['authority_key_identifier']
self.authority_cert_issuer = module.params['authority_cert_issuer'] self.authority_cert_issuer = module.params['authority_cert_issuer']
self.authority_cert_serial_number = module.params['authority_cert_serial_number'] self.authority_cert_serial_number = module.params['authority_cert_serial_number']
self.crl_distribution_points = module.params['crl_distribution_points']
self.csr = None self.csr = None
self.privatekey = None self.privatekey = None
@ -245,9 +251,10 @@ class CertificateSigningRequestBackend(object):
# Implementation with using pyOpenSSL # Implementation with using pyOpenSSL
class CertificateSigningRequestPyOpenSSLBackend(CertificateSigningRequestBackend): class CertificateSigningRequestPyOpenSSLBackend(CertificateSigningRequestBackend):
def __init__(self, module): def __init__(self, module):
if module.params['create_subject_key_identifier']: for o in ('create_subject_key_identifier', ):
module.fail_json(msg='You cannot use create_subject_key_identifier with the pyOpenSSL backend!') if module.params[o]:
for o in ('subject_key_identifier', 'authority_key_identifier', 'authority_cert_issuer', 'authority_cert_serial_number'): module.fail_json(msg='You cannot use {0} with the pyOpenSSL backend!'.format(o))
for o in ('subject_key_identifier', 'authority_key_identifier', 'authority_cert_issuer', 'authority_cert_serial_number', 'crl_distribution_points'):
if module.params[o] is not None: if module.params[o] is not None:
module.fail_json(msg='You cannot use {0} with the pyOpenSSL backend!'.format(o)) module.fail_json(msg='You cannot use {0} with the pyOpenSSL backend!'.format(o))
super(CertificateSigningRequestPyOpenSSLBackend, self).__init__(module, 'pyopenssl') super(CertificateSigningRequestPyOpenSSLBackend, self).__init__(module, 'pyopenssl')
@ -409,6 +416,39 @@ class CertificateSigningRequestPyOpenSSLBackend(CertificateSigningRequestBackend
return _check_subject(self.existing_csr) and _check_extensions(self.existing_csr) and _check_signature(self.existing_csr) return _check_subject(self.existing_csr) and _check_extensions(self.existing_csr) and _check_signature(self.existing_csr)
def parse_crl_distribution_points(module, crl_distribution_points):
result = []
for index, parse_crl_distribution_point in enumerate(crl_distribution_points):
try:
params = dict(
full_name=None,
relative_name=None,
crl_issuer=None,
reasons=None,
)
if parse_crl_distribution_point['full_name'] is not None:
params['full_name'] = [cryptography_get_name(name, 'full name') for name in parse_crl_distribution_point['full_name']]
if parse_crl_distribution_point['relative_name'] is not None:
try:
params['relative_name'] = cryptography_parse_relative_distinguished_name(parse_crl_distribution_point['relative_name'])
except Exception:
# If cryptography's version is < 1.6, the error is probably caused by that
if CRYPTOGRAPHY_VERSION < LooseVersion('1.6'):
raise OpenSSLObjectError('Cannot specify relative_name for cryptography < 1.6')
raise
if parse_crl_distribution_point['crl_issuer'] is not None:
params['crl_issuer'] = [cryptography_get_name(name, 'CRL issuer') for name in parse_crl_distribution_point['crl_issuer']]
if parse_crl_distribution_point['reasons'] is not None:
reasons = []
for reason in parse_crl_distribution_point['reasons']:
reasons.append(REVOCATION_REASON_MAP[reason])
params['reasons'] = frozenset(reasons)
result.append(cryptography.x509.DistributionPoint(**params))
except OpenSSLObjectError as e:
raise OpenSSLObjectError('Error while parsing CRL distribution point #{index}: {error}'.format(index=index, error=e))
return result
# Implementation with using cryptography # Implementation with using cryptography
class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBackend): class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBackend):
def __init__(self, module): def __init__(self, module):
@ -417,6 +457,9 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack
if self.version != 1: if self.version != 1:
module.warn('The cryptography backend only supports version 1. (The only valid value according to RFC 2986.)') module.warn('The cryptography backend only supports version 1. (The only valid value according to RFC 2986.)')
if self.crl_distribution_points:
self.crl_distribution_points = parse_crl_distribution_points(module, self.crl_distribution_points)
def generate_csr(self): def generate_csr(self):
"""(Re-)Generate CSR.""" """(Re-)Generate CSR."""
self._ensure_private_key_loaded() self._ensure_private_key_loaded()
@ -460,8 +503,8 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack
if self.name_constraints_permitted or self.name_constraints_excluded: if self.name_constraints_permitted or self.name_constraints_excluded:
try: try:
csr = csr.add_extension(cryptography.x509.NameConstraints( csr = csr.add_extension(cryptography.x509.NameConstraints(
[cryptography_get_name(name) for name in self.name_constraints_permitted], [cryptography_get_name(name, 'name constraints permitted') for name in self.name_constraints_permitted],
[cryptography_get_name(name) for name in self.name_constraints_excluded], [cryptography_get_name(name, 'name constraints excluded') for name in self.name_constraints_excluded],
), critical=self.name_constraints_critical) ), critical=self.name_constraints_critical)
except TypeError as e: except TypeError as e:
raise OpenSSLObjectError('Error while parsing name constraint: {0}'.format(e)) raise OpenSSLObjectError('Error while parsing name constraint: {0}'.format(e))
@ -477,12 +520,18 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack
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 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 issuers = None
if self.authority_cert_issuer is not None: if self.authority_cert_issuer is not None:
issuers = [cryptography_get_name(n) for n in self.authority_cert_issuer] issuers = [cryptography_get_name(n, 'authority cert issuer') for n in self.authority_cert_issuer]
csr = csr.add_extension( csr = csr.add_extension(
cryptography.x509.AuthorityKeyIdentifier(self.authority_key_identifier, issuers, self.authority_cert_serial_number), cryptography.x509.AuthorityKeyIdentifier(self.authority_key_identifier, issuers, self.authority_cert_serial_number),
critical=False critical=False
) )
if self.crl_distribution_points:
csr = csr.add_extension(
cryptography.x509.CRLDistributionPoints(self.crl_distribution_points),
critical=False
)
digest = None digest = None
if cryptography_key_needs_digest_for_signing(self.privatekey): if cryptography_key_needs_digest_for_signing(self.privatekey):
digest = select_message_digest(self.digest) digest = select_message_digest(self.digest)
@ -606,8 +655,8 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack
current_nc_ext = _find_extension(extensions, cryptography.x509.NameConstraints) current_nc_ext = _find_extension(extensions, cryptography.x509.NameConstraints)
current_nc_perm = [str(altname) for altname in current_nc_ext.value.permitted_subtrees] if current_nc_ext else [] current_nc_perm = [str(altname) for altname in current_nc_ext.value.permitted_subtrees] if current_nc_ext else []
current_nc_excl = [str(altname) for altname in current_nc_ext.value.excluded_subtrees] if current_nc_ext else [] current_nc_excl = [str(altname) for altname in current_nc_ext.value.excluded_subtrees] if current_nc_ext else []
nc_perm = [str(cryptography_get_name(altname)) for altname in self.name_constraints_permitted] nc_perm = [str(cryptography_get_name(altname, 'name constraints permitted')) for altname in self.name_constraints_permitted]
nc_excl = [str(cryptography_get_name(altname)) for altname in self.name_constraints_excluded] nc_excl = [str(cryptography_get_name(altname, 'name constraints excluded')) for altname in self.name_constraints_excluded]
if set(nc_perm) != set(current_nc_perm) or set(nc_excl) != set(current_nc_excl): if set(nc_perm) != set(current_nc_perm) or set(nc_excl) != set(current_nc_excl):
return False return False
if nc_perm or nc_excl: if nc_perm or nc_excl:
@ -636,7 +685,7 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack
aci = None aci = None
csr_aci = None csr_aci = None
if self.authority_cert_issuer is not None: if self.authority_cert_issuer is not None:
aci = [str(cryptography_get_name(n)) for n in self.authority_cert_issuer] aci = [str(cryptography_get_name(n, 'authority cert issuer')) for n in self.authority_cert_issuer]
if ext.value.authority_cert_issuer is not None: if ext.value.authority_cert_issuer is not None:
csr_aci = [str(n) for n in ext.value.authority_cert_issuer] csr_aci = [str(n) for n in ext.value.authority_cert_issuer]
return (ext.value.key_identifier == self.authority_key_identifier return (ext.value.key_identifier == self.authority_key_identifier
@ -645,12 +694,21 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack
else: else:
return ext is None return ext is None
def _check_crl_distribution_points(extensions):
ext = _find_extension(extensions, cryptography.x509.CRLDistributionPoints)
if self.crl_distribution_points is None:
return ext is None
if not ext:
return False
return list(ext.value) == self.crl_distribution_points
def _check_extensions(csr): def _check_extensions(csr):
extensions = csr.extensions extensions = csr.extensions
return (_check_subjectAltName(extensions) and _check_keyUsage(extensions) and return (_check_subjectAltName(extensions) and _check_keyUsage(extensions) and
_check_extenededKeyUsage(extensions) and _check_basicConstraints(extensions) and _check_extenededKeyUsage(extensions) and _check_basicConstraints(extensions) and
_check_ocspMustStaple(extensions) and _check_subject_key_identifier(extensions) and _check_ocspMustStaple(extensions) and _check_subject_key_identifier(extensions) and
_check_authority_key_identifier(extensions) and _check_nameConstraints(extensions)) _check_authority_key_identifier(extensions) and _check_nameConstraints(extensions) and
_check_crl_distribution_points(extensions))
def _check_signature(csr): def _check_signature(csr):
if not csr.is_signature_valid: if not csr.is_signature_valid:
@ -750,6 +808,26 @@ def get_csr_argument_spec():
authority_key_identifier=dict(type='str'), authority_key_identifier=dict(type='str'),
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'),
crl_distribution_points=dict(
type='list',
elements='dict',
options=dict(
full_name=dict(type='list', elements='str'),
relative_name=dict(type='list', elements='str'),
crl_issuer=dict(type='list', elements='str'),
reasons=dict(type='list', elements='str', choices=[
'key_compromise',
'ca_compromise',
'affiliation_changed',
'superseded',
'cessation_of_operation',
'certificate_hold',
'privilege_withdrawn',
'aa_compromise',
]),
),
mutually_exclusive=[('full_name', 'relative_name')]
),
select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'cryptography', 'pyopenssl']), select_crypto_backend=dict(type='str', default='auto', choices=['auto', 'cryptography', 'pyopenssl']),
), ),
required_together=[ required_together=[

View File

@ -142,6 +142,21 @@ EXAMPLES = r'''
extended_key_usage: extended_key_usage:
- clientAuth - clientAuth
subject_alt_name: otherName:1.3.6.1.4.1.311.20.2.3;UTF8:username@localhost subject_alt_name: otherName:1.3.6.1.4.1.311.20.2.3;UTF8:username@localhost
- name: Generate an OpenSSL Certificate Signing Request with a CRL distribution point
community.crypto.openssl_csr:
path: /etc/ssl/csr/www.ansible.com.csr
privatekey_path: /etc/ssl/private/ansible.com.pem
common_name: www.ansible.com
crl_distribution_points:
- full_name:
- "URI:https://ca.example.com/revocations.crl"
crl_issuer:
- "URI:https://ca.example.com/"
reasons:
- key_compromise
- ca_compromise
- cessation_of_operation
''' '''
RETURN = r''' RETURN = r'''

View File

@ -502,7 +502,7 @@ class CRL(OpenSSLObject):
result['serial_number'] = rc['serial_number'] result['serial_number'] = rc['serial_number']
# All other options # All other options
if rc['issuer']: if rc['issuer']:
result['issuer'] = [cryptography_get_name(issuer) for issuer in rc['issuer']] result['issuer'] = [cryptography_get_name(issuer, 'issuer') for issuer in rc['issuer']]
result['issuer_critical'] = rc['issuer_critical'] result['issuer_critical'] = rc['issuer_critical']
result['revocation_date'] = get_relative_time_option( result['revocation_date'] = get_relative_time_option(
rc['revocation_date'], rc['revocation_date'],
@ -648,7 +648,7 @@ class CRL(OpenSSLObject):
if entry['issuer'] is not None: if entry['issuer'] is not None:
revoked_cert = revoked_cert.add_extension( revoked_cert = revoked_cert.add_extension(
x509.CertificateIssuer([ x509.CertificateIssuer([
cryptography_get_name(name) for name in entry['issuer'] cryptography_get_name(name, 'issuer') for name in entry['issuer']
]), ]),
entry['issuer_critical'] entry['issuer_critical']
) )

View File

@ -902,3 +902,96 @@
ignore_errors: yes ignore_errors: yes
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', '>=')
- name: "({{ select_crypto_backend }}) CRL distribution endpoints (for cryptography >= 1.6)"
block:
- name: "({{ select_crypto_backend }}) Create CSR with CRL distribution endpoints"
openssl_csr:
path: '{{ output_dir }}/csr_crl_d_e.csr'
privatekey_path: '{{ output_dir }}/privatekey.pem'
subject:
commonName: www.ansible.com
crl_distribution_points:
- full_name:
- "URI:https://ca.example.com/revocations.crl"
crl_issuer:
- "URI:https://ca.example.com/"
reasons:
- key_compromise
- ca_compromise
- cessation_of_operation
- relative_name:
- CN=ca.example.com
reasons:
- certificate_hold
- {}
select_crypto_backend: '{{ select_crypto_backend }}'
register: crl_distribution_endpoints_1
- name: "({{ select_crypto_backend }}) Create CSR with CRL distribution endpoints (idempotence)"
openssl_csr:
path: '{{ output_dir }}/csr_crl_d_e.csr'
privatekey_path: '{{ output_dir }}/privatekey.pem'
subject:
commonName: www.ansible.com
crl_distribution_points:
- full_name:
- "URI:https://ca.example.com/revocations.crl"
crl_issuer:
- "URI:https://ca.example.com/"
reasons:
- key_compromise
- ca_compromise
- cessation_of_operation
- relative_name:
- CN=ca.example.com
reasons:
- certificate_hold
- {}
select_crypto_backend: '{{ select_crypto_backend }}'
register: crl_distribution_endpoints_2
- name: "({{ select_crypto_backend }}) Create CSR with CRL distribution endpoints (change)"
openssl_csr:
path: '{{ output_dir }}/csr_crl_d_e.csr'
privatekey_path: '{{ output_dir }}/privatekey.pem'
subject:
commonName: www.ansible.com
crl_distribution_points:
- full_name:
- "URI:https://ca.example.com/revocations.crl"
crl_issuer:
- "URI:https://ca.example.com/"
reasons:
- key_compromise
- ca_compromise
- cessation_of_operation
- relative_name:
- CN=ca.example.com
reasons:
- certificate_hold
select_crypto_backend: '{{ select_crypto_backend }}'
register: crl_distribution_endpoints_3
- name: "({{ select_crypto_backend }}) Create CSR with CRL distribution endpoints (no endpoints)"
openssl_csr:
path: '{{ output_dir }}/csr_crl_d_e.csr'
privatekey_path: '{{ output_dir }}/privatekey.pem'
subject:
commonName: www.ansible.com
select_crypto_backend: '{{ select_crypto_backend }}'
register: crl_distribution_endpoints_4
- name: "({{ select_crypto_backend }}) Create CSR with CRL distribution endpoints"
openssl_csr:
path: '{{ output_dir }}/csr_crl_d_e.csr'
privatekey_path: '{{ output_dir }}/privatekey.pem'
subject:
commonName: www.ansible.com
crl_distribution_points:
- full_name:
- "URI:https://ca.example.com/revocations.crl"
select_crypto_backend: '{{ select_crypto_backend }}'
register: crl_distribution_endpoints_5
when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('1.6', '>=')

View File

@ -334,3 +334,13 @@
- generate_csr_ed25519_ed448_idempotent.results[0] is not changed - generate_csr_ed25519_ed448_idempotent.results[0] is not changed
- generate_csr_ed25519_ed448_idempotent.results[1] is not changed - generate_csr_ed25519_ed448_idempotent.results[1] is not changed
when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.8', '>=') and generate_csr_ed25519_ed448_privatekey is not failed when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('2.8', '>=') and generate_csr_ed25519_ed448_privatekey is not failed
- name: "({{ select_crypto_backend }}) Verify CRL distribution endpoints (for cryptography >= 1.6)"
assert:
that:
- crl_distribution_endpoints_1 is changed
- crl_distribution_endpoints_2 is not changed
- crl_distribution_endpoints_3 is changed
- crl_distribution_endpoints_4 is changed
- crl_distribution_endpoints_5 is changed
when: select_crypto_backend == 'cryptography' and cryptography_version.stdout is version('1.6', '>=')