Skip to content
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ ansible-galaxy collection install -vv -r meta/collection-requirements.yml

## Variables

Type, required-field, and choice validation is enforced by
`meta/argument_specs.yml`. Role tasks enforce cross-field validation.

| Parameter | Description | Type | Required | Default |
|-------------------------|----------------------------------------------------------------------------------------------------------------|:----:|:--------:|-------------------|
| certificate_wait | If the task should wait for the certificate to be issued. | bool | no | yes |
Expand Down
182 changes: 182 additions & 0 deletions meta/argument_specs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
# SPDX-License-Identifier: MIT
---
argument_specs:
main:
short_description: The certificate role.
description: >
The certificate role allows you to issue and manage TLS/SSL
certificates using various CA providers such as self-sign and IPA.

This role will install necessary packages, configure the certificate
provider, and issue or renew certificates as specified in
`certificate_requests`. It can also manage system trust store
entries via `certificate_trust`.
options:
certificate_requests:
type: list
elements: dict
description: >
A list of certificate request specifications. Each item describes
a certificate to be issued or renewed. Defaults to an empty list.
options:
name:
type: str
required: true
description: >
The name of the certificate. A full path can be used to
choose the directory where files will be stored.
ca:
type: str
required: true
description: >
The CA that will issue the certificate (e.g. self-sign, ipa).
dns:
type: raw

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are dns, email, and ip using type raw? Is it because they can be null?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its because these fields can accept a string or a list of strings.

description: >
A domain name or list of domain names to include in the
certificate Subject Alternative Name (SAN).
email:
type: raw
description: >
An email address or list of email addresses to include in the
certificate Subject Alternative Name (SAN).
ip:
type: raw
description: >
An IP address or list of IP addresses to include in the
certificate Subject Alternative Name (SAN).
auto_renew:
type: bool
description: >
Whether the certificate should be renewed automatically
before it expires. Defaults to `true`.
owner:
type: str
description: >
The user name or user id for the certificate and key files.
group:
type: str
description: >
The group name or group id for the certificate and key files.
mode:
type: raw
description: >
The file system permissions for the certificate and key
files. Accepts a string (e.g. '0644') or an integer.
key_size:
type: int
description: >
The key size in bits.
common_name:
type: str
description: >
The Common Name requested for the certificate subject.
country:
type: str
description: >
The country code requested for the certificate subject.
state:
type: str
description: >
The state requested for the certificate subject.
locality:
type: str
description: >
The locality requested for the certificate subject.
organization:
type: str
description: >
The organization requested for the certificate subject.
organizational_unit:
type: str
description: >
The organizational unit requested for the certificate subject.
contact_email:
type: str
description: >
The contact email requested for the certificate subject.
key_usage:
type: list
elements: str
Comment thread
richm marked this conversation as resolved.
choices:
- digitalSignature
- nonRepudiation
- keyEncipherment
- dataEncipherment
- keyAgreement
- keyCertSign
- cRLSign
- encipherOnly
- decipherOnly
description: >
The allowed Key Usage extensions for the certificate.
Defaults to `digitalSignature` and `keyEncipherment`.
extended_key_usage:
type: list
elements: str
description: >
The Extended Key Usage attributes for the certificate.
Defaults to `id-kp-serverAuth` and `id-kp-clientAuth`.
run_before:
type: str
description: >
A command to run before saving the certificate.
run_after:
type: str
description: >
A command to run after saving the certificate.
principal:
type: raw
description: >
A Kerberos principal or list of Kerberos principals.
provider:
type: str
description: >
The underlying method used to request and manage the
certificate. Defaults to `certmonger`.
issuer:
type: str
description: >
The issuer certificate nickname or template name.
certificate_wait:
type: bool
description: >
Whether the task should wait for the certificate to be issued.
Defaults to `true`.
certificate_trust:
type: list
elements: dict
description: >
A list of certificates to install into or remove from the system
trust store. Defaults to an empty list.
options:
name:
type: str
required: true
description: >
The base file name of the trust anchor.
content:
type: str
description: >
The inline PEM content of the certificate.
src:
type: str
description: >
The path of a certificate file to copy to the trust store.
remote_src:
type: bool
description: >
If true, `src` is a path on the managed host rather than
the controller.
url:
type: str
description: >
The URL to download the certificate from.
state:
type: str
choices:
- present
- absent
description: >
Whether the trust anchor should be present or absent.
Defaults to `present`.
78 changes: 78 additions & 0 deletions tasks/assert_role_vars.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# SPDX-License-Identifier: MIT
---
- name: Assert dns is a string or list of strings
ansible.builtin.assert:
that:
- >-
item.dns is string
or (item.dns is sequence and item.dns is not mapping
and item.dns | reject('string') | list | length == 0)
fail_msg: >-
certificate_requests[{{ idx }}].dns must be a string or list of
strings, got {{ item.dns | type_debug }}
loop: "{{ certificate_requests }}"
loop_control:
index_var: idx
label: "{{ item.name | d('unnamed') }}"
when: item.dns is defined

- name: Assert email is a string or list of strings
ansible.builtin.assert:
that:
- >-
item.email is string
or (item.email is sequence and item.email is not mapping
and item.email | reject('string') | list | length == 0)
fail_msg: >-
certificate_requests[{{ idx }}].email must be a string or list of
strings, got {{ item.email | type_debug }}
loop: "{{ certificate_requests }}"
loop_control:
index_var: idx
label: "{{ item.name | d('unnamed') }}"
when: item.email is defined

- name: Assert ip is a string or list of strings
ansible.builtin.assert:
that:
- >-
item.ip is string
or (item.ip is sequence and item.ip is not mapping
and item.ip | reject('string') | list | length == 0)
fail_msg: >-
certificate_requests[{{ idx }}].ip must be a string or list of
strings, got {{ item.ip | type_debug }}
loop: "{{ certificate_requests }}"
loop_control:
index_var: idx
label: "{{ item.name | d('unnamed') }}"
when: item.ip is defined

- name: Assert principal is a string or list of strings
ansible.builtin.assert:
that:
- >-
item.principal is string
or (item.principal is sequence and item.principal is not mapping
and item.principal | reject('string') | list | length == 0)
fail_msg: >-
certificate_requests[{{ idx }}].principal must be a string or list of
strings, got {{ item.principal | type_debug }}
loop: "{{ certificate_requests }}"
loop_control:
index_var: idx
label: "{{ item.name | d('unnamed') }}"
when: item.principal is defined

- name: Assert mode is a string or integer
ansible.builtin.assert:
that:
- (item.mode | type_debug) in ['str', 'int', 'unicode']
fail_msg: >-
certificate_requests[{{ idx }}].mode must be a string or integer,
got {{ item.mode | type_debug }}
loop: "{{ certificate_requests }}"
loop_control:
index_var: idx
label: "{{ item.name | d('unnamed') }}"
when: item.mode is defined
4 changes: 4 additions & 0 deletions tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
- name: Set version specific variables
include_tasks: tasks/set_vars.yml

- name: Validate certificate_requests fields
ansible.builtin.include_tasks: tasks/assert_role_vars.yml
when: certificate_requests | length > 0

- name: Set/reset certificate_is_changed
set_fact:
certificate_is_changed: false
Expand Down
Loading
Loading