Allow to specify subject (for CSRs) and issuer (for CRLs) ordered (#316)
* Allow to specify subject (for CSRs) and issuer (for CRLs) ordered.
* Forgot import.
* Apply suggestions from code review
Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
* Apply suggestions from code review
Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
* Fix typo.
* Simplify error handling, reject empty values outright.
* Document d497231e1c
.
Co-authored-by: Ajpantuso <ajpantuso@gmail.com>
pull/328/head
parent
ecbd44df22
commit
589e7c72ef
|
@ -0,0 +1,9 @@
|
|||
minor_changes:
|
||||
- "acme_certificate - the ``subject`` and ``issuer`` fields in in the ``select_chain`` entries are now more strictly validated (https://github.com/ansible-collections/community.crypto/pull/316)."
|
||||
- "openssl_csr, openssl_csr_pipe - there is now stricter validation of the values of the ``subject`` option (https://github.com/ansible-collections/community.crypto/pull/316)."
|
||||
- "openssl_csr, openssl_csr_pipe - provide a new ``subject_ordered`` option if the order of the components in the subject is of importance (https://github.com/ansible-collections/community.crypto/issues/291, https://github.com/ansible-collections/community.crypto/pull/316)."
|
||||
- "x509_crl - there is now stricter validation of the values of the ``issuer`` option (https://github.com/ansible-collections/community.crypto/pull/316)."
|
||||
- "x509_crl - provide a new ``issuer_ordered`` option if the order of the components in the issuer is of importance (https://github.com/ansible-collections/community.crypto/issues/291, https://github.com/ansible-collections/community.crypto/pull/316)."
|
||||
breaking_changes:
|
||||
- "openssl_csr, openssl_csr_pipe, x509_crl - the ``subject`` respectively ``issuer`` fields no longer ignore empty values, but instead fail when encountering them (https://github.com/ansible-collections/community.crypto/pull/316)."
|
||||
- "x509_crl - for idempotency checks, the ``issuer`` order is ignored. If order is important, use the new ``issuer_ordered`` option (https://github.com/ansible-collections/community.crypto/pull/316)."
|
|
@ -52,7 +52,20 @@ options:
|
|||
description:
|
||||
- Key/value pairs that will be present in the subject name field of the certificate signing request.
|
||||
- If you need to specify more than one value with the same key, use a list as value.
|
||||
- If the order of the components is important, use I(subject_ordered).
|
||||
- Mutually exclusive with I(subject_ordered).
|
||||
type: dict
|
||||
subject_ordered:
|
||||
description:
|
||||
- A list of dictionaries, where every dictionary must contain one key/value pair. This key/value pair
|
||||
will be present in the subject name field of the certificate signing request.
|
||||
- If you want to specify more than one value with the same key in a row, you can use a list as value.
|
||||
- Mutually exclusive with I(subject), and any other subject field option, such as I(country_name),
|
||||
I(state_or_province_name), I(locality_name), I(organization_name), I(organizational_unit_name),
|
||||
I(common_name), or I(email_address).
|
||||
type: list
|
||||
elements: dict
|
||||
version_added: 2.0.0
|
||||
country_name:
|
||||
description:
|
||||
- The countryName field of the certificate signing request subject.
|
||||
|
|
|
@ -118,11 +118,11 @@ class CryptographyChainMatcher(ChainMatcher):
|
|||
self.issuer = []
|
||||
if criterium.subject:
|
||||
self.subject = [
|
||||
(cryptography_name_to_oid(k), to_native(v)) for k, v in parse_name_field(criterium.subject)
|
||||
(cryptography_name_to_oid(k), to_native(v)) for k, v in parse_name_field(criterium.subject, 'subject')
|
||||
]
|
||||
if criterium.issuer:
|
||||
self.issuer = [
|
||||
(cryptography_name_to_oid(k), to_native(v)) for k, v in parse_name_field(criterium.issuer)
|
||||
(cryptography_name_to_oid(k), to_native(v)) for k, v in parse_name_field(criterium.issuer, 'issuer')
|
||||
]
|
||||
self.subject_key_identifier = CryptographyChainMatcher._parse_key_identifier(
|
||||
criterium.subject_key_identifier, 'subject_key_identifier', criterium.index, module)
|
||||
|
|
|
@ -16,7 +16,7 @@ from distutils.version import LooseVersion
|
|||
|
||||
from ansible.module_utils import six
|
||||
from ansible.module_utils.basic import missing_required_lib
|
||||
from ansible.module_utils.common.text.converters import to_bytes, to_text
|
||||
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
|
||||
|
||||
from ansible_collections.community.crypto.plugins.module_utils.crypto.basic import (
|
||||
OpenSSLObjectError,
|
||||
|
@ -27,6 +27,7 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto.support im
|
|||
load_privatekey,
|
||||
load_certificate_request,
|
||||
parse_name_field,
|
||||
parse_ordered_name_field,
|
||||
select_message_digest,
|
||||
)
|
||||
|
||||
|
@ -119,6 +120,7 @@ class CertificateSigningRequestBackend(object):
|
|||
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.ordered_subject = False
|
||||
self.subject = [
|
||||
('C', module.params['country_name']),
|
||||
('ST', module.params['state_or_province_name']),
|
||||
|
@ -128,11 +130,19 @@ class CertificateSigningRequestBackend(object):
|
|||
('CN', module.params['common_name']),
|
||||
('emailAddress', module.params['email_address']),
|
||||
]
|
||||
|
||||
if module.params['subject']:
|
||||
self.subject = self.subject + parse_name_field(module.params['subject'])
|
||||
self.subject = [(entry[0], entry[1]) for entry in self.subject if entry[1]]
|
||||
|
||||
try:
|
||||
if module.params['subject']:
|
||||
self.subject = self.subject + parse_name_field(module.params['subject'], 'subject')
|
||||
if module.params['subject_ordered']:
|
||||
if self.subject:
|
||||
raise CertificateSigningRequestError('subject_ordered cannot be combined with any other subject field')
|
||||
self.subject = parse_ordered_name_field(module.params['subject_ordered'], 'subject_ordered')
|
||||
self.ordered_subject = True
|
||||
except ValueError as exc:
|
||||
raise CertificateSigningRequestError(to_native(exc))
|
||||
|
||||
self.using_common_name_for_san = False
|
||||
if not self.subjectAltName and module.params['use_common_name_for_san']:
|
||||
for sub in self.subject:
|
||||
|
@ -401,7 +411,10 @@ class CertificateSigningRequestCryptographyBackend(CertificateSigningRequestBack
|
|||
def _check_subject(csr):
|
||||
subject = [(cryptography_name_to_oid(entry[0]), to_text(entry[1])) for entry in self.subject]
|
||||
current_subject = [(sub.oid, sub.value) for sub in csr.subject]
|
||||
return set(subject) == set(current_subject)
|
||||
if self.ordered_subject:
|
||||
return subject == current_subject
|
||||
else:
|
||||
return set(subject) == set(current_subject)
|
||||
|
||||
def _find_extension(extensions, exttype):
|
||||
return next(
|
||||
|
@ -592,6 +605,7 @@ def get_csr_argument_spec():
|
|||
privatekey_passphrase=dict(type='str', no_log=True),
|
||||
version=dict(type='int', default=1, choices=[1]),
|
||||
subject=dict(type='dict'),
|
||||
subject_ordered=dict(type='list', elements='dict'),
|
||||
country_name=dict(type='str', aliases=['C', 'countryName']),
|
||||
state_or_province_name=dict(type='str', aliases=['ST', 'stateOrProvinceName']),
|
||||
locality_name=dict(type='str', aliases=['L', 'localityName']),
|
||||
|
@ -645,6 +659,7 @@ def get_csr_argument_spec():
|
|||
],
|
||||
mutually_exclusive=[
|
||||
['privatekey_path', 'privatekey_content'],
|
||||
['subject', 'subject_ordered'],
|
||||
],
|
||||
required_one_of=[
|
||||
['privatekey_path', 'privatekey_content'],
|
||||
|
|
|
@ -237,16 +237,43 @@ def load_certificate_request(path, content=None, backend='cryptography'):
|
|||
raise OpenSSLObjectError(exc)
|
||||
|
||||
|
||||
def parse_name_field(input_dict):
|
||||
def parse_name_field(input_dict, name_field_name=None):
|
||||
"""Take a dict with key: value or key: list_of_values mappings and return a list of tuples"""
|
||||
error_str = '{key}' if name_field_name is None else '{key} in {name}'
|
||||
|
||||
result = []
|
||||
for key, value in input_dict.items():
|
||||
if isinstance(value, list):
|
||||
for entry in value:
|
||||
if not isinstance(entry, six.string_types):
|
||||
raise TypeError(('Values %s must be strings' % error_str).format(key=key, name=name_field_name))
|
||||
if not entry:
|
||||
raise ValueError(('Values for %s must not be empty strings' % error_str).format(key=key))
|
||||
result.append((key, entry))
|
||||
elif isinstance(value, six.string_types):
|
||||
if not value:
|
||||
raise ValueError(('Value for %s must not be an empty string' % error_str).format(key=key))
|
||||
result.append((key, value))
|
||||
else:
|
||||
raise TypeError(('Value for %s must be either a string or a list of strings' % error_str).format(key=key))
|
||||
return result
|
||||
|
||||
|
||||
def parse_ordered_name_field(input_list, name_field_name):
|
||||
"""Take a dict with key: value or key: list_of_values mappings and return a list of tuples"""
|
||||
|
||||
result = []
|
||||
for key in input_dict:
|
||||
if isinstance(input_dict[key], list):
|
||||
for entry in input_dict[key]:
|
||||
result.append((key, entry))
|
||||
else:
|
||||
result.append((key, input_dict[key]))
|
||||
for index, entry in enumerate(input_list):
|
||||
if len(entry) != 1:
|
||||
raise ValueError(
|
||||
'Entry #{index} in {name} must be a dictionary with exactly one key-value pair'.format(
|
||||
name=name_field_name, index=index + 1))
|
||||
try:
|
||||
result.extend(parse_name_field(entry, name_field_name=name_field_name))
|
||||
except (TypeError, ValueError) as exc:
|
||||
raise ValueError(
|
||||
'Error while processing entry #{index} in {name}: {error}'.format(
|
||||
name=name_field_name, index=index + 1, error=exc))
|
||||
return result
|
||||
|
||||
|
||||
|
|
|
@ -580,9 +580,12 @@ class ACMECertificateClient(object):
|
|||
|
||||
if self.module.params['select_chain']:
|
||||
for criterium_idx, criterium in enumerate(self.module.params['select_chain']):
|
||||
self.select_chain_matcher.append(
|
||||
self.client.backend.create_chain_matcher(
|
||||
Criterium(criterium, index=criterium_idx)))
|
||||
try:
|
||||
self.select_chain_matcher.append(
|
||||
self.client.backend.create_chain_matcher(
|
||||
Criterium(criterium, index=criterium_idx)))
|
||||
except ValueError as exc:
|
||||
self.module.warn('Error while parsing criterium: {error}. Ignoring criterium.'.format(error=exc))
|
||||
|
||||
# Make sure account exists
|
||||
modify_account = module.params['modify_account']
|
||||
|
|
|
@ -92,8 +92,21 @@ options:
|
|||
description:
|
||||
- Key/value pairs that will be present in the issuer name field of the CRL.
|
||||
- If you need to specify more than one value with the same key, use a list as value.
|
||||
- Required if I(state) is C(present).
|
||||
- If the order of the components is important, use I(issuer_ordered).
|
||||
- One of I(issuer) and I(issuer_ordered) is required if I(state) is C(present).
|
||||
- Mutually exclusive with I(issuer_ordered).
|
||||
type: dict
|
||||
issuer_ordered:
|
||||
description:
|
||||
- A list of dictionaries, where every dictionary must contain one key/value pair.
|
||||
This key/value pair will be present in the issuer name field of the CRL.
|
||||
- If you want to specify more than one value with the same key in a row, you can
|
||||
use a list as value.
|
||||
- One of I(issuer) and I(issuer_ordered) is required if I(state) is C(present).
|
||||
- Mutually exclusive with I(issuer).
|
||||
type: list
|
||||
elements: dict
|
||||
version_added: 2.0.0
|
||||
|
||||
last_update:
|
||||
description:
|
||||
|
@ -386,6 +399,7 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto.support im
|
|||
load_privatekey,
|
||||
load_certificate,
|
||||
parse_name_field,
|
||||
parse_ordered_name_field,
|
||||
get_relative_time_option,
|
||||
select_message_digest,
|
||||
)
|
||||
|
@ -462,8 +476,15 @@ class CRL(OpenSSLObject):
|
|||
self.privatekey_content = self.privatekey_content.encode('utf-8')
|
||||
self.privatekey_passphrase = module.params['privatekey_passphrase']
|
||||
|
||||
self.issuer = parse_name_field(module.params['issuer'])
|
||||
self.issuer = [(entry[0], entry[1]) for entry in self.issuer if entry[1]]
|
||||
try:
|
||||
if module.params['issuer_ordered']:
|
||||
self.issuer_ordered = True
|
||||
self.issuer = parse_ordered_name_field(module.params['issuer_ordered'], 'issuer_ordered')
|
||||
else:
|
||||
self.issuer_ordered = False
|
||||
self.issuer = parse_name_field(module.params['issuer'], 'issuer')
|
||||
except (TypeError, ValueError) as exc:
|
||||
module.fail_json(msg=to_native(exc))
|
||||
|
||||
self.last_update = get_relative_time_option(module.params['last_update'], 'last_update')
|
||||
self.next_update = get_relative_time_option(module.params['next_update'], 'next_update')
|
||||
|
@ -616,7 +637,11 @@ class CRL(OpenSSLObject):
|
|||
return False
|
||||
|
||||
want_issuer = [(cryptography_name_to_oid(entry[0]), entry[1]) for entry in self.issuer]
|
||||
if want_issuer != [(sub.oid, sub.value) for sub in self.crl.issuer]:
|
||||
is_issuer = [(sub.oid, sub.value) for sub in self.crl.issuer]
|
||||
if not self.issuer_ordered:
|
||||
want_issuer = set(want_issuer)
|
||||
is_issuer = set(is_issuer)
|
||||
if want_issuer != is_issuer:
|
||||
return False
|
||||
|
||||
old_entries = [self._compress_entry(cryptography_decode_revoked_certificate(cert)) for cert in self.crl]
|
||||
|
@ -782,6 +807,7 @@ def main():
|
|||
privatekey_content=dict(type='str', no_log=True),
|
||||
privatekey_passphrase=dict(type='str', no_log=True),
|
||||
issuer=dict(type='dict'),
|
||||
issuer_ordered=dict(type='list', elements='dict'),
|
||||
last_update=dict(type='str', default='+0s'),
|
||||
next_update=dict(type='str'),
|
||||
digest=dict(type='str', default='sha256'),
|
||||
|
@ -815,10 +841,12 @@ def main():
|
|||
),
|
||||
required_if=[
|
||||
('state', 'present', ['privatekey_path', 'privatekey_content'], True),
|
||||
('state', 'present', ['issuer', 'next_update', 'revoked_certificates'], False),
|
||||
('state', 'present', ['issuer', 'issuer_ordered'], True),
|
||||
('state', 'present', ['next_update', 'revoked_certificates'], False),
|
||||
],
|
||||
mutually_exclusive=(
|
||||
['privatekey_path', 'privatekey_content'],
|
||||
['issuer', 'issuer_ordered'],
|
||||
),
|
||||
supports_check_mode=True,
|
||||
add_file_common_args=True,
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
openssl_csr:
|
||||
path: '{{ remote_tmp_dir }}/csr.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.ansible.com
|
||||
subject_ordered:
|
||||
- commonName: www.ansible.com
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
return_content: yes
|
||||
register: generate_csr_idempotent
|
||||
|
@ -517,23 +517,23 @@
|
|||
openssl_csr:
|
||||
path: '{{ remote_tmp_dir }}/csr_everything.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
commonName: www.example.com
|
||||
C: de
|
||||
L: Somewhere
|
||||
ST: Zürich
|
||||
streetAddress: Welcome Street N° 5
|
||||
O: Ansiblé
|
||||
organizationalUnitName: Crÿpto Depârtment ☺
|
||||
serialNumber: "1234"
|
||||
SN: Last Name Which Happens To Be A Very Løng String With A Lot Of Spaces, Jr.
|
||||
GN: First Name
|
||||
title: Chïeff
|
||||
pseudonym: test
|
||||
UID: asdf
|
||||
emailAddress: test@example.com
|
||||
postalAddress: 1234 Somewhere
|
||||
postalCode: "1234"
|
||||
subject_ordered:
|
||||
- commonName: www.example.com
|
||||
- C: de
|
||||
- L: Somewhere
|
||||
- ST: Zürich
|
||||
- streetAddress: Welcome Street N° 5
|
||||
- O: Ansiblé
|
||||
- organizationalUnitName: Crÿpto Depârtment ☺
|
||||
- serialNumber: "1234"
|
||||
- SN: Last Name Which Happens To Be A Very Løng String With A Lot Of Spaces, Jr.
|
||||
- GN: First Name
|
||||
- title: Chïeff
|
||||
- pseudonym: test
|
||||
- UID: asdf
|
||||
- emailAddress: test@example.com
|
||||
- postalAddress: 1234 Somewhere
|
||||
- postalCode: "1234"
|
||||
useCommonNameForSAN: no
|
||||
key_usage:
|
||||
- digitalSignature
|
||||
|
@ -602,23 +602,23 @@
|
|||
openssl_csr:
|
||||
path: '{{ remote_tmp_dir }}/csr_everything.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
CN: www.example.com
|
||||
countryName: de
|
||||
L: Somewhere
|
||||
ST: Zürich
|
||||
streetAddress: Welcome Street N° 5
|
||||
organizationName: Ansiblé
|
||||
organizationalUnitName: Crÿpto Depârtment ☺
|
||||
serialNumber: "1234"
|
||||
SN: Last Name Which Happens To Be A Very Løng String With A Lot Of Spaces, Jr.
|
||||
GN: First Name
|
||||
title: Chïeff
|
||||
pseudonym: test
|
||||
UID: asdf
|
||||
emailAddress: test@example.com
|
||||
postalAddress: 1234 Somewhere
|
||||
postalCode: "1234"
|
||||
subject_ordered:
|
||||
- CN: www.example.com
|
||||
- countryName: de
|
||||
- L: Somewhere
|
||||
- ST: Zürich
|
||||
- streetAddress: Welcome Street N° 5
|
||||
- organizationName: Ansiblé
|
||||
- organizationalUnitName: Crÿpto Depârtment ☺
|
||||
- serialNumber: "1234"
|
||||
- SN: Last Name Which Happens To Be A Very Løng String With A Lot Of Spaces, Jr.
|
||||
- GN: First Name
|
||||
- title: Chïeff
|
||||
- pseudonym: test
|
||||
- UID: asdf
|
||||
- emailAddress: test@example.com
|
||||
- postalAddress: 1234 Somewhere
|
||||
- postalCode: "1234"
|
||||
useCommonNameForSAN: no
|
||||
key_usage:
|
||||
- digitalSignature
|
||||
|
@ -689,18 +689,19 @@
|
|||
path: '{{ remote_tmp_dir }}/csr_everything.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject:
|
||||
# Subject has been reordered, but is inside 'subject' and not 'subject_ordered'
|
||||
CN: www.example.com
|
||||
countryName: de
|
||||
L: Somewhere
|
||||
countryName: de
|
||||
ST: Zürich
|
||||
streetAddress: Welcome Street N° 5
|
||||
organizationName: Ansiblé
|
||||
organizationalUnitName: Crÿpto Depârtment ☺
|
||||
organizationName: Ansiblé
|
||||
serialNumber: "1234"
|
||||
SN: Last Name Which Happens To Be A Very Løng String With A Lot Of Spaces, Jr.
|
||||
GN: First Name
|
||||
title: Chïeff
|
||||
pseudonym: test
|
||||
title: Chïeff
|
||||
UID: asdf
|
||||
emailAddress: test@example.com
|
||||
postalAddress: 1234 Somewhere
|
||||
|
@ -769,6 +770,93 @@
|
|||
- "IP:0::0:1:0:0/112"
|
||||
register: everything_3
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Generate CSR with everything (not idempotent, check mode)"
|
||||
openssl_csr:
|
||||
path: '{{ remote_tmp_dir }}/csr_everything.csr'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/privatekey.pem'
|
||||
subject_ordered:
|
||||
# Subject has been reordered, this should force a change
|
||||
- CN: www.example.com
|
||||
- L: Somewhere
|
||||
- countryName: de
|
||||
- ST: Zürich
|
||||
- streetAddress: Welcome Street N° 5
|
||||
- organizationalUnitName: Crÿpto Depârtment ☺
|
||||
- organizationName: Ansiblé
|
||||
- serialNumber: "1234"
|
||||
- SN: Last Name Which Happens To Be A Very Løng String With A Lot Of Spaces, Jr.
|
||||
- GN: First Name
|
||||
- pseudonym: test
|
||||
- title: Chïeff
|
||||
- UID: asdf
|
||||
- emailAddress: test@example.com
|
||||
- postalAddress: 1234 Somewhere
|
||||
- postalCode: "1234"
|
||||
useCommonNameForSAN: no
|
||||
key_usage:
|
||||
- digitalSignature
|
||||
- keyAgreement
|
||||
- Non Repudiation
|
||||
- Key Encipherment
|
||||
- dataEncipherment
|
||||
- Certificate Sign
|
||||
- cRLSign
|
||||
- Encipher Only
|
||||
- decipherOnly
|
||||
key_usage_critical: yes
|
||||
extended_key_usage: '{{ value_for_extended_key_usage }}'
|
||||
subject_alt_name: '{{ value_for_san }}'
|
||||
basic_constraints:
|
||||
- "CA:TRUE"
|
||||
- "pathlen:23"
|
||||
basic_constraints_critical: yes
|
||||
name_constraints_permitted: '{{ value_for_name_constraints_permitted }}'
|
||||
name_constraints_excluded:
|
||||
- "DNS:.org"
|
||||
- "DNS:.example.com"
|
||||
name_constraints_critical: yes
|
||||
ocsp_must_staple: yes
|
||||
subject_key_identifier: 00:11:22:33
|
||||
authority_key_identifier: 44:55:66:77
|
||||
authority_cert_issuer: '{{ value_for_authority_cert_issuer }}'
|
||||
authority_cert_serial_number: 12345
|
||||
select_crypto_backend: '{{ select_crypto_backend }}'
|
||||
vars:
|
||||
value_for_extended_key_usage:
|
||||
- serverAuth # the same as "TLS Web Server Authentication"
|
||||
- TLS Web Server Authentication
|
||||
- TLS Web Client Authentication
|
||||
- Code Signing
|
||||
- E-mail Protection
|
||||
- timeStamping
|
||||
- OCSPSigning
|
||||
- Any Extended Key Usage
|
||||
- qcStatements
|
||||
- DVCS
|
||||
- IPSec User
|
||||
- biometricInfo
|
||||
- 1.2.3.4.5.6
|
||||
value_for_authority_cert_issuer:
|
||||
- "DNS:ca.example.org"
|
||||
- "IP:1.2.3.4"
|
||||
value_for_san:
|
||||
- "DNS:www.ansible.com"
|
||||
- "IP:1.2.3.4"
|
||||
- "IP:::1"
|
||||
- "email:test@example.org"
|
||||
- "URI:https://example.org/test/index.html"
|
||||
- "RID:1.2.3.4"
|
||||
- "otherName:1.2.3.4;0c:07:63:65:72:74:72:65:71"
|
||||
- "otherName:1.3.6.1.4.1.311.20.2.3;UTF8:bob@localhost"
|
||||
- "dirName:CN= example.net, O =Example Net"
|
||||
- "dirName:/CN= example.com/O =Example Com"
|
||||
value_for_name_constraints_permitted:
|
||||
- "DNS:www.example.com"
|
||||
- "IP:1.2.3.0/255.255.255.0"
|
||||
- "IP:0::0:1:0:0/112"
|
||||
register: everything_4
|
||||
check_mode: true
|
||||
|
||||
- name: "({{ select_crypto_backend }}) Get info from CSR with everything"
|
||||
community.crypto.openssl_csr_info:
|
||||
path: '{{ remote_tmp_dir }}/csr_everything.csr'
|
||||
|
|
|
@ -195,6 +195,7 @@
|
|||
- everything_1 is changed
|
||||
- everything_2 is not changed
|
||||
- everything_3 is not changed
|
||||
- everything_4 is changed
|
||||
- everything_info.basic_constraints == [
|
||||
"CA:TRUE",
|
||||
"pathlen:23",
|
||||
|
@ -233,6 +234,25 @@
|
|||
- everything_info.subject.title == "Chïeff"
|
||||
- everything_info.subject.userId == "asdf"
|
||||
- everything_info.subject | length == 16
|
||||
- >
|
||||
everything_info.subject_ordered == [
|
||||
["commonName", "www.example.com"],
|
||||
["countryName", "de"],
|
||||
["localityName", "Somewhere"],
|
||||
["stateOrProvinceName", "Zürich"],
|
||||
["streetAddress", "Welcome Street N° 5"],
|
||||
["organizationName", "Ansiblé"],
|
||||
["organizationalUnitName", "Crÿpto Depârtment ☺"],
|
||||
["serialNumber", "1234"],
|
||||
["surname", "Last Name Which Happens To Be A Very Løng String With A Lot Of Spaces, Jr."],
|
||||
["givenName", "First Name"],
|
||||
["title", "Chïeff"],
|
||||
["pseudonym", "test"],
|
||||
["userId", "asdf"],
|
||||
["emailAddress", "test@example.com"],
|
||||
["postalAddress", "1234 Somewhere"],
|
||||
["postalCode", "1234"],
|
||||
]
|
||||
- everything_info.subject_alt_name_critical == false
|
||||
- everything_info.name_constraints_excluded == [
|
||||
"DNS:.example.com",
|
||||
|
|
|
@ -1,25 +1,4 @@
|
|||
---
|
||||
- name: Create CRL 1 (check mode)
|
||||
x509_crl:
|
||||
path: '{{ remote_tmp_dir }}/ca-crl1.crl'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ca.key'
|
||||
issuer:
|
||||
CN: Ansible
|
||||
last_update: 20191013000000Z
|
||||
next_update: 20191113000000Z
|
||||
revoked_certificates:
|
||||
- path: '{{ remote_tmp_dir }}/cert-1.pem'
|
||||
revocation_date: 20191013000000Z
|
||||
- path: '{{ remote_tmp_dir }}/cert-2.pem'
|
||||
revocation_date: 20191013000000Z
|
||||
reason: key_compromise
|
||||
reason_critical: yes
|
||||
invalidity_date: 20191012000000Z
|
||||
- serial_number: 1234
|
||||
revocation_date: 20191001000000Z
|
||||
check_mode: yes
|
||||
register: crl_1_check
|
||||
|
||||
- name: Create CRL 1 (check mode)
|
||||
x509_crl:
|
||||
path: '{{ remote_tmp_dir }}/ca-crl1.crl'
|
||||
|
@ -283,8 +262,11 @@
|
|||
x509_crl:
|
||||
path: '{{ remote_tmp_dir }}/ca-crl2.crl'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ca.key'
|
||||
issuer:
|
||||
CN: Ansible
|
||||
issuer_ordered:
|
||||
- CN: Ansible
|
||||
- CN: CRL
|
||||
- countryName: US
|
||||
- CN: Test
|
||||
last_update: +0d
|
||||
next_update: +0d
|
||||
revoked_certificates:
|
||||
|
@ -301,8 +283,11 @@
|
|||
x509_crl:
|
||||
path: '{{ remote_tmp_dir }}/ca-crl2.crl'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ca.key'
|
||||
issuer:
|
||||
CN: Ansible
|
||||
issuer_ordered:
|
||||
- CN: Ansible
|
||||
- CN: CRL
|
||||
- countryName: US
|
||||
- CN: Test
|
||||
last_update: +0d
|
||||
next_update: +0d
|
||||
revoked_certificates:
|
||||
|
@ -318,8 +303,11 @@
|
|||
x509_crl:
|
||||
path: '{{ remote_tmp_dir }}/ca-crl2.crl'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ca.key'
|
||||
issuer:
|
||||
CN: Ansible
|
||||
issuer_ordered:
|
||||
- CN: Ansible
|
||||
- CN: CRL
|
||||
- C: US
|
||||
- CN: Test
|
||||
last_update: +0d
|
||||
next_update: +0d
|
||||
revoked_certificates:
|
||||
|
@ -337,8 +325,11 @@
|
|||
x509_crl:
|
||||
path: '{{ remote_tmp_dir }}/ca-crl2.crl'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ca.key'
|
||||
issuer:
|
||||
CN: Ansible
|
||||
issuer_ordered:
|
||||
- CN: Ansible
|
||||
- CN: CRL
|
||||
- countryName: US
|
||||
- CN: Test
|
||||
last_update: +0d
|
||||
next_update: +0d
|
||||
revoked_certificates:
|
||||
|
@ -355,8 +346,11 @@
|
|||
x509_crl:
|
||||
path: '{{ remote_tmp_dir }}/ca-crl2.crl'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ca.key'
|
||||
issuer:
|
||||
CN: Ansible
|
||||
issuer_ordered:
|
||||
- CN: Ansible
|
||||
- CN: CRL
|
||||
- countryName: US
|
||||
- CN: Test
|
||||
last_update: +0d
|
||||
next_update: +0d
|
||||
revoked_certificates:
|
||||
|
@ -370,8 +364,11 @@
|
|||
x509_crl:
|
||||
path: '{{ remote_tmp_dir }}/ca-crl2.crl'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ca.key'
|
||||
issuer:
|
||||
CN: Ansible
|
||||
issuer_ordered:
|
||||
- CN: Ansible
|
||||
- CN: CRL
|
||||
- countryName: US
|
||||
- CN: Test
|
||||
last_update: +0d
|
||||
next_update: +0d
|
||||
revoked_certificates:
|
||||
|
@ -384,8 +381,11 @@
|
|||
x509_crl:
|
||||
path: '{{ remote_tmp_dir }}/ca-crl2.crl'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ca.key'
|
||||
issuer:
|
||||
CN: Ansible
|
||||
issuer_ordered:
|
||||
- CN: Ansible
|
||||
- CN: CRL
|
||||
- countryName: US
|
||||
- CN: Test
|
||||
last_update: +0d
|
||||
next_update: +0d
|
||||
revoked_certificates:
|
||||
|
@ -402,8 +402,11 @@
|
|||
x509_crl:
|
||||
path: '{{ remote_tmp_dir }}/ca-crl2.crl'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ca.key'
|
||||
issuer:
|
||||
CN: Ansible
|
||||
issuer_ordered:
|
||||
- CN: Ansible
|
||||
- CN: CRL
|
||||
- countryName: US
|
||||
- CN: Test
|
||||
last_update: +0d
|
||||
next_update: +0d
|
||||
revoked_certificates:
|
||||
|
@ -419,8 +422,11 @@
|
|||
x509_crl:
|
||||
path: '{{ remote_tmp_dir }}/ca-crl2.crl'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ca.key'
|
||||
issuer:
|
||||
CN: Ansible
|
||||
issuer_ordered:
|
||||
- CN: Ansible
|
||||
- CN: CRL
|
||||
- countryName: US
|
||||
- CN: Test
|
||||
last_update: +0d
|
||||
next_update: +0d
|
||||
revoked_certificates:
|
||||
|
@ -437,8 +443,11 @@
|
|||
x509_crl:
|
||||
path: '{{ remote_tmp_dir }}/ca-crl2.crl'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ca.key'
|
||||
issuer:
|
||||
CN: Ansible
|
||||
issuer_ordered:
|
||||
- CN: Ansible
|
||||
- CN: CRL
|
||||
- countryName: US
|
||||
- CN: Test
|
||||
last_update: +0d
|
||||
next_update: +0d
|
||||
revoked_certificates:
|
||||
|
@ -451,8 +460,67 @@
|
|||
return_content: yes
|
||||
register: crl_2_change
|
||||
|
||||
- name: Read ca-crl2.crl
|
||||
slurp:
|
||||
src: '{{ remote_tmp_dir }}/ca-crl2.crl'
|
||||
register: slurp_crl2_1
|
||||
|
||||
- name: Retrieve CRL 2 infos
|
||||
x509_crl_info:
|
||||
path: '{{ remote_tmp_dir }}/ca-crl2.crl'
|
||||
list_revoked_certificates: false
|
||||
register: crl_2_info_1
|
||||
|
||||
- name: Create CRL 2 (changed order, should be ignored)
|
||||
x509_crl:
|
||||
path: '{{ remote_tmp_dir }}/ca-crl2.crl'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ca.key'
|
||||
issuer:
|
||||
countryName: US
|
||||
CN:
|
||||
- Ansible
|
||||
- CRL
|
||||
- Test
|
||||
last_update: +0d
|
||||
next_update: +0d
|
||||
revoked_certificates:
|
||||
- path: '{{ remote_tmp_dir }}/cert-2.pem'
|
||||
reason: key_compromise
|
||||
reason_critical: yes
|
||||
invalidity_date: 20191012000000Z
|
||||
ignore_timestamps: true
|
||||
mode: update
|
||||
return_content: yes
|
||||
register: crl_2_change_order_ignore
|
||||
|
||||
- name: Create CRL 2 (changed order)
|
||||
x509_crl:
|
||||
path: '{{ remote_tmp_dir }}/ca-crl2.crl'
|
||||
privatekey_path: '{{ remote_tmp_dir }}/ca.key'
|
||||
issuer_ordered:
|
||||
- CN: Ansible
|
||||
- countryName: US
|
||||
- CN: CRL
|
||||
- CN: Test
|
||||
last_update: +0d
|
||||
next_update: +0d
|
||||
revoked_certificates:
|
||||
- path: '{{ remote_tmp_dir }}/cert-2.pem'
|
||||
reason: key_compromise
|
||||
reason_critical: yes
|
||||
invalidity_date: 20191012000000Z
|
||||
ignore_timestamps: true
|
||||
mode: update
|
||||
return_content: yes
|
||||
register: crl_2_change_order
|
||||
|
||||
- name: Read ca-crl2.crl
|
||||
slurp:
|
||||
src: '{{ remote_tmp_dir }}/ca-crl2.crl'
|
||||
register: slurp_crl2_2
|
||||
|
||||
- name: Retrieve CRL 2 infos again
|
||||
x509_crl_info:
|
||||
path: '{{ remote_tmp_dir }}/ca-crl2.crl'
|
||||
list_revoked_certificates: false
|
||||
register: crl_2_info_2
|
||||
|
|
|
@ -66,11 +66,6 @@
|
|||
that:
|
||||
- crl_1_format_idem.crl | b64decode == content.content | b64decode
|
||||
|
||||
- name: Read ca-crl2.crl
|
||||
slurp:
|
||||
src: '{{ remote_tmp_dir }}/ca-crl2.crl'
|
||||
register: slurp
|
||||
|
||||
- name: Validate CRL 2
|
||||
assert:
|
||||
that:
|
||||
|
@ -84,9 +79,26 @@
|
|||
- crl_2_idem_update is not changed
|
||||
- crl_2_change_check is changed
|
||||
- crl_2_change is changed
|
||||
- crl_2_change.crl == (slurp.content | b64decode)
|
||||
- crl_2_change.crl == (slurp_crl2_1.content | b64decode)
|
||||
- crl_2_change_order_ignore is not changed
|
||||
- crl_2_change_order is changed
|
||||
- crl_2_change_order.crl == (slurp_crl2_2.content | b64decode)
|
||||
|
||||
- name: Validate CRL 2 info
|
||||
assert:
|
||||
that:
|
||||
- "'revoked_certificates' not in crl_2_info_1"
|
||||
- >
|
||||
crl_2_info_1.issuer_ordered == [
|
||||
['commonName', 'Ansible'],
|
||||
['commonName', 'CRL'],
|
||||
['countryName', 'US'],
|
||||
['commonName', 'Test'],
|
||||
]
|
||||
- >
|
||||
crl_2_info_2.issuer_ordered == [
|
||||
['commonName', 'Ansible'],
|
||||
['countryName', 'US'],
|
||||
['commonName', 'CRL'],
|
||||
['commonName', 'Test'],
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue