Compare commits

..
1 Commits
Author SHA1 Message Date
CSRBot e14fd800cc chore(deps): update dependency markdownlint-cli to ^0.48.0
Ansible Linter / ansible-lint (push) Successful in 1m29s
Lint Markdown files / markdown-lint (push) Successful in 11s
Ansible Linter / ansible-lint (pull_request) Successful in 1m15s
Lint Markdown files / markdown-lint (pull_request) Successful in 10s
2026-06-02 18:00:57 +00:00
45 changed files with 498 additions and 753 deletions
+20
View File
@@ -0,0 +1,20 @@
name: Ansible Linter
on:
pull_request:
types: [ "opened", "reopened", "synchronize" ]
push:
branches: [ '**' ]
tags-ignore: [ '**' ]
jobs:
ansible-lint:
runs-on:
- ubuntu-latest
steps:
- uses: actions/checkout@v6.0.3
- name: Run ansible-lint
uses: ansible/ansible-lint@v26.4.0
with:
args: "--config-file .ansible-lint"
setup_python: "true"
-22
View File
@@ -1,22 +0,0 @@
name: Ansible Linter
on:
pull_request:
types: [ "opened", "reopened", "synchronize" ]
push:
branches: [ '**' ]
tags-ignore: [ '**' ]
jobs:
ansible-lint:
runs-on:
- ubuntu-latest
steps:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
- name: Run ansible-lint
uses: ansible/ansible-lint@665d9e07a1943254d2910faffc106adaf7ea7294 # v26.8.0
with:
args: "--config-file .ansible-lint"
# The molecule scenario is linted as well, so its collections are required beside the ones of the role.
requirements_file: "molecule/default/collections.yml"
setup_python: "true"
@@ -12,7 +12,7 @@ jobs:
runs-on:
- ubuntu-latest
steps:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
- uses: DavidAnson/markdownlint-cli2-action@ded1f9488f68a970bc66ea5619e13e9b52e601cd # v23.2.0
- uses: actions/checkout@v6.0.3
- uses: DavidAnson/markdownlint-cli2-action@v21.0.0
with:
globs: '**/*.md'
-30
View File
@@ -1,30 +0,0 @@
name: Molecule
on:
pull_request:
types: [ "opened", "reopened", "synchronize" ]
push:
branches: [ '**' ]
tags-ignore: [ '**' ]
permissions:
contents: read
jobs:
molecule:
name: Molecule
runs-on: ubuntu-latest-amd64
steps:
# The scenario includes the role by its name, so the directory must be named like the role and not like the
# repository. Its parent is used as roles path.
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
with:
path: certificate_authority
- name: Install molecule
run: |
apt update --yes
apt install --yes python3-pip
pip3 install --break-system-packages molecule docker
- name: Run molecule
run: molecule test
working-directory: certificate_authority
+4 -1
View File
@@ -2,10 +2,13 @@
"ansible.python.interpreterPath": "/bin/python",
"files.associations": {
"**/.gitea/**/*.yml": "yaml",
"**/.gitea/**/*.yaml": "yaml",
"docker-compose*.yml": "dockercompose",
"*.yml": "ansible",
"*.yaml": "ansible",
".yamllint": "yaml",
".yamllint.yml": "yaml"
".yamllint.yml": "yaml",
".yamllint.yaml": "yaml"
},
"rewrap.wrappingColumn": 120
}
+23 -74
View File
@@ -4,20 +4,6 @@ This Ansible role can be used to create a root and intermediate certificate auth
them. Additionally offers the ansible role the feature to import the certificates of the authority into the systems
trust store.
## Requirements
The role relies on the modules of the collection `community.crypto`. On Archlinux the collection `community.general`
is additionally required, because it provides the `pacman` module.
```bash
ansible-galaxy collection install -r requirements.yml
```
Facts must be gathered, because the names of the required python packages, the location of the trust store anchor and
the command to update the trust store are looked up by `ansible_facts['distribution']`, `ansible_facts['os_family']`
and `ansible_facts['architecture']`. Archlinux, Debian and RedHat based distributions are supported. Furthermore the
role writes into `/etc` and updates the systems trust store, so it has to be executed with `become: true`.
## Examples
The following minimal example creates a root and intermediate certificate authority and issues a client certificate from
@@ -27,45 +13,8 @@ the intermediate certificate authority.
certificate_authority_client_skip: false
certificate_authority_client_common_name: "{{ inventory_hostname }}"
certificate_authority_client_subject_alternative_names:
- "DNS:{{ inventory_hostname }}"
- "DNS:san.example.local"
- "IP:10.11.12.13"
```
## Tests
The role is tested with [Molecule](https://ansible.readthedocs.io/projects/molecule/). The scenario starts one docker
container per supported distribution family, applies the role, asserts that a second run reports no change and finally
verifies the issued certificates with `openssl verify`, their file permissions and the anchor in the systems trust
store.
Molecule ships only its `default` driver, therefore `docker` is required besides molecule itself. The collections are
declared in `molecule/default/collections.yml` and installed by molecule.
```bash
pip install molecule docker
```
The complete sequence creates the containers, tests them and removes them afterwards.
```bash
molecule test
```
While working on the role the containers are better kept alive.
```bash
# create the containers and apply the role
molecule converge
# run the assertions of molecule/default/verify.yml against the running containers
molecule verify
# open a shell in one of the containers
molecule login --host certificate-authority-debian
# remove the containers
molecule destroy
- "{{ inventory_hostname }}"
- san.example.local
```
## Parameters
@@ -79,12 +28,12 @@ molecule destroy
| `certificate_authority_root_ca_import` | Import the TLS certificate of the root certificate authority into the systems trust store. | `true` |
| `certificate_authority_root_ca_path` | Directory where the private and public TLS key of the root certificate authority should be stored. | `/etc/ansible-playbook/pki/ca` |
| `certificate_authority_root_ca_common_name` | Common Name (CN) of the root certificate authority. | `Ansible Root CA` |
| `certificate_authority_root_ca_country_name` | Country name of the root certificate authority. For example `US`, `FR` or `DE`. | `""` |
| `certificate_authority_root_ca_country_name` | Common Name (CN) of the root certificate authority. For example `US`, `FR` or `DE`. | `""` |
| `certificate_authority_root_ca_email_address` | E-Mail Address of the root certificate authority owner. | `""` |
| `certificate_authority_root_ca_organization_name` | Organization name of the root certificate authority owner. | `""` |
| `certificate_authority_root_ca_organizational_unit_name` | Organizational unit name of the root certificate authority. | `""` |
| `certificate_authority_root_ca_state_or_province_name` | State or province name where the owner of the root certificate authority is located. | `""` |
| `certificate_authority_root_ca_subject_alternative_names` | Subject Alternative Names (SAN) of the root certificate authority. Example: `DNS:example.local`, `IP:10.11.12.13`. | `[]` |
| `certificate_authority_root_ca_subject_alternative_names` | Subject Alternative Names (SAN) of the root certificate authority. | `[]` |
| `certificate_authority_root_ca_not_after` | Time in the future from now when the TLS certificate should expire | `+3650d` |
| `certificate_authority_root_ca_not_before` | Time in the past from now when the TLS certificate should be valid. | `+0s` |
| `certificate_authority_root_ca_tls_key_content` | Content of a custom used root certificate authority. Will only be imported, when `certificate_authority_root_ca_create: false`. | `""` |
@@ -105,7 +54,7 @@ molecule destroy
| `certificate_authority_intermediate_ca_organization_name` | Organization name of the intermediate certificate authority owner. | `""` |
| `certificate_authority_intermediate_ca_organizational_unit_name` | Organizational unit name of the intermediate certificate authority. | `""` |
| `certificate_authority_intermediate_ca_state_or_province_name` | State or province name where the owner of the intermediate certificate authority is located. | `""` |
| `certificate_authority_intermediate_ca_subject_alternative_names` | Subject Alternative Names (SAN) of the intermediate certificate authority. Example: `DNS:example.local`, `IP:10.11.12.13`. | `[]` |
| `certificate_authority_intermediate_ca_subject_alternative_names` | Subject Alternative Names (SAN) of the intermediate certificate authority. | `[]` |
| `certificate_authority_intermediate_ca_not_after` | Time in the future from now when the TLS certificate should expire | `+1825d` |
| `certificate_authority_intermediate_ca_not_before` | Time in the past from now when the TLS certificate should be valid. | `+0s` |
| `certificate_authority_intermediate_ca_tls_key_content` | Content of a custom used intermediate certificate authority. Will only be imported, when `certificate_authority_intermediate_ca_create: false`. | `""` |
@@ -115,21 +64,21 @@ molecule destroy
### Client Certificate
| Name | Description | Value |
| -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- |
| `certificate_authority_client_skip` | Skip creation or import of a client certificate in general. | `true` |
| `certificate_authority_client_create` | Create client certificate from scratch or import via `certificate_authority_client_tls` prefixed variables. | `true` |
| `certificate_authority_client_path` | Directory where the private and public TLS key of the client certificate authority should be stored. | `/etc/ansible-playbook/pki/client` |
| `certificate_authority_client_common_name` | Common Name (CN) of the client certificate. | `Ansible Client Certificate` |
| `certificate_authority_client_country_name` | Country name of the client certificate. For example `US`, `FR` or `DE`. | `""` |
| `certificate_authority_client_email_address` | E-Mail Address of the client certificate owner. | `""` |
| `certificate_authority_client_organization_name` | Organization name of the client certificate owner. | `""` |
| `certificate_authority_client_organizational_unit_name` | Organizational unit name of the client certificate. | `""` |
| `certificate_authority_client_state_or_province_name` | State or province name where the owner of the client certificate is located. | `""` |
| `certificate_authority_client_subject_alternative_names` | Subject Alternative Names (SAN) of the client certificate. Example: `DNS:example.local`, `IP:10.11.12.13`. | `[]` |
| `certificate_authority_client_not_after` | Time in the future from now when the TLS certificate should expire | `+397d` |
| `certificate_authority_client_not_before` | Time in the past from now when the TLS certificate should be valid. | `+0s` |
| `certificate_authority_client_tls_key_passphrase` | Passphrase for the private key of the generated or imported client certificate. | `""` |
| `certificate_authority_client_tls_key_type` | Algorithm of the private key of the client certificate. | `RSA` |
| `certificate_authority_client_tls_crt_content` | Content of a custom used client certificate. Will only be imported, when `certificate_authority_client_create: false`. | `""` |
| `certificate_authority_client_tls_key_content` | Content of the private key of a custom used client certificate. Will only be imported, when `certificate_authority_client_create: false`. | `""` |
| Name | Description | Value |
| -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ---------------------------------- |
| `certificate_authority_client_skip` | Skip creation or import of a client certificate in general. | `true` |
| `certificate_authority_client_create` | Create client certificate from scratch or import via `certificate_authority_client_tls` prefixed variables. | `true` |
| `certificate_authority_client_path` | Directory where the private and public TLS key of the client certificate authority should be stored. | `/etc/ansible-playbook/pki/client` |
| `certificate_authority_client_common_name` | Common Name (CN) of the client certificate. | `Ansible Client Certificate` |
| `certificate_authority_client_country_name` | Country Name (CN) of the client certificate. For example `US`, `FR` or `DE`. | `""` |
| `certificate_authority_client_email_address` | E-Mail Address of the client certificate owner. | `""` |
| `certificate_authority_client_organization_name` | Organization name of the client certificate owner. | `""` |
| `certificate_authority_client_organizational_unit_name` | Common Name (CN) of the client certificate. | `""` |
| `certificate_authority_client_state_or_province_name` | State or province name where the owner of the client certificate is located. | `""` |
| `certificate_authority_client_subject_alternative_names` | Subject Alternative Names (SAN) of the client certificate. | `[]` |
| `certificate_authority_client_not_after` | Time in the future from now when the TLS certificate should expire | `+397d` |
| `certificate_authority_client_not_before` | Time in the past from now when the TLS certificate should be valid. | `+0s` |
| `certificate_authority_client_tls_key_passphrase` | Passphrase for the private key of the generated or imported client certificate. | `""` |
| `certificate_authority_client_tls_key_type` | Algorithm of the private key of the client certificate. | `RSA` |
| `certificate_authority_client_tls_crt_content` | Passphrase for the private key of the generated or imported client certificate. | `""` |
| `certificate_authority_client_tls_key_content` | Algorithm of the private key of the client certificate | `""` |
@@ -10,12 +10,12 @@ certificate_authority_root_ca_import: true
## @param certificate_authority_root_ca_path Directory where the private and public TLS key of the root certificate authority should be stored.
## @param certificate_authority_root_ca_common_name Common Name (CN) of the root certificate authority.
## @param certificate_authority_root_ca_country_name Country name of the root certificate authority. For example `US`, `FR` or `DE`.
## @param certificate_authority_root_ca_country_name Common Name (CN) of the root certificate authority. For example `US`, `FR` or `DE`.
## @param certificate_authority_root_ca_email_address E-Mail Address of the root certificate authority owner.
## @param certificate_authority_root_ca_organization_name Organization name of the root certificate authority owner.
## @param certificate_authority_root_ca_organizational_unit_name Organizational unit name of the root certificate authority.
## @param certificate_authority_root_ca_state_or_province_name State or province name where the owner of the root certificate authority is located.
## @param certificate_authority_root_ca_subject_alternative_names Subject Alternative Names (SAN) of the root certificate authority. Example: `DNS:example.local`, `IP:10.11.12.13`.
## @param certificate_authority_root_ca_subject_alternative_names Subject Alternative Names (SAN) of the root certificate authority.
## @param certificate_authority_root_ca_not_after Time in the future from now when the TLS certificate should expire
## @param certificate_authority_root_ca_not_before Time in the past from now when the TLS certificate should be valid.
certificate_authority_root_ca_path: "/etc/ansible-playbook/pki/ca"
@@ -53,7 +53,7 @@ certificate_authority_intermediate_ca_create: true
## @param certificate_authority_intermediate_ca_organization_name Organization name of the intermediate certificate authority owner.
## @param certificate_authority_intermediate_ca_organizational_unit_name Organizational unit name of the intermediate certificate authority.
## @param certificate_authority_intermediate_ca_state_or_province_name State or province name where the owner of the intermediate certificate authority is located.
## @param certificate_authority_intermediate_ca_subject_alternative_names Subject Alternative Names (SAN) of the intermediate certificate authority. Example: `DNS:example.local`, `IP:10.11.12.13`.
## @param certificate_authority_intermediate_ca_subject_alternative_names Subject Alternative Names (SAN) of the intermediate certificate authority.
## @param certificate_authority_intermediate_ca_not_after Time in the future from now when the TLS certificate should expire
## @param certificate_authority_intermediate_ca_not_before Time in the past from now when the TLS certificate should be valid.
certificate_authority_intermediate_ca_path: "/etc/ansible-playbook/pki/intermediate"
@@ -86,12 +86,12 @@ certificate_authority_client_create: true
## @param certificate_authority_client_path Directory where the private and public TLS key of the client certificate authority should be stored.
## @param certificate_authority_client_common_name Common Name (CN) of the client certificate.
## @param certificate_authority_client_country_name Country name of the client certificate. For example `US`, `FR` or `DE`.
## @param certificate_authority_client_country_name Country Name (CN) of the client certificate. For example `US`, `FR` or `DE`.
## @param certificate_authority_client_email_address E-Mail Address of the client certificate owner.
## @param certificate_authority_client_organization_name Organization name of the client certificate owner.
## @param certificate_authority_client_organizational_unit_name Organizational unit name of the client certificate.
## @param certificate_authority_client_organizational_unit_name Common Name (CN) of the client certificate.
## @param certificate_authority_client_state_or_province_name State or province name where the owner of the client certificate is located.
## @param certificate_authority_client_subject_alternative_names Subject Alternative Names (SAN) of the client certificate. Example: `DNS:example.local`, `IP:10.11.12.13`.
## @param certificate_authority_client_subject_alternative_names Subject Alternative Names (SAN) of the client certificate.
## @param certificate_authority_client_not_after Time in the future from now when the TLS certificate should expire
## @param certificate_authority_client_not_before Time in the past from now when the TLS certificate should be valid.
certificate_authority_client_path: "/etc/ansible-playbook/pki/client"
@@ -110,7 +110,7 @@ certificate_authority_client_not_before: "+0s"
certificate_authority_client_tls_key_passphrase: ""
certificate_authority_client_tls_key_type: "RSA"
## @param certificate_authority_client_tls_crt_content Content of a custom used client certificate. Will only be imported, when `certificate_authority_client_create: false`.
## @param certificate_authority_client_tls_key_content Content of the private key of a custom used client certificate. Will only be imported, when `certificate_authority_client_create: false`.
## @param certificate_authority_client_tls_crt_content Passphrase for the private key of the generated or imported client certificate.
## @param certificate_authority_client_tls_key_content Algorithm of the private key of the client certificate
certificate_authority_client_tls_crt_content: ""
certificate_authority_client_tls_key_content: ""
-8
View File
@@ -1,8 +0,0 @@
---
- name: Update systems SSL/TLS trust store
ansible.builtin.command:
cmd: "{{ certificate_authority_trust_store_update_command }}"
changed_when: true
when: certificate_authority_root_ca_import is defined and
certificate_authority_root_ca_import
@@ -29,7 +29,7 @@ argument_specs:
type: str
default: "Ansible Root CA"
certificate_authority_root_ca_country_name:
description: "Country name of the root certificate authority. For example US, FR or DE."
description: "Common Name (CN) of the root certificate authority. For example US, FR or DE."
type: str
default: ""
certificate_authority_root_ca_email_address:
@@ -49,7 +49,7 @@ argument_specs:
type: str
default: ""
certificate_authority_root_ca_subject_alternative_names:
description: "Subject Alternative Names (SAN) of the root certificate authority. Example: DNS:example.local, IP:10.11.12.13."
description: "Subject Alternative Names (SAN) of the root certificate authority."
type: list
elements: str
default: []
@@ -121,7 +121,7 @@ argument_specs:
type: str
default: ""
certificate_authority_intermediate_ca_subject_alternative_names:
description: "Subject Alternative Names (SAN) of the intermediate certificate authority. Example: DNS:example.local, IP:10.11.12.13."
description: "Subject Alternative Names (SAN) of the intermediate certificate authority."
type: list
elements: str
default: []
@@ -173,7 +173,7 @@ argument_specs:
type: str
default: "Ansible Client Certificate"
certificate_authority_client_country_name:
description: "Country name of the client certificate. For example US, FR or DE."
description: "Country Name (CN) of the client certificate. For example US, FR or DE."
type: str
default: ""
certificate_authority_client_email_address:
@@ -185,7 +185,7 @@ argument_specs:
type: str
default: ""
certificate_authority_client_organizational_unit_name:
description: "Organizational unit name of the client certificate."
description: "Common Name (CN) of the client certificate."
type: str
default: ""
certificate_authority_client_state_or_province_name:
@@ -193,7 +193,7 @@ argument_specs:
type: str
default: ""
certificate_authority_client_subject_alternative_names:
description: "Subject Alternative Names (SAN) of the client certificate. Example: DNS:example.local, IP:10.11.12.13."
description: "Subject Alternative Names (SAN) of the client certificate."
type: list
elements: str
default: []
@@ -219,10 +219,10 @@ argument_specs:
- DSA
- ECC
certificate_authority_client_tls_crt_content:
description: "Content of a custom used client certificate. Will only be imported, when certificate_authority_client_create: false."
description: "Passphrase for the private key of the generated or imported client certificate."
type: str
default: ""
certificate_authority_client_tls_key_content:
description: "Content of the private key of a custom used client certificate. Will only be imported, when certificate_authority_client_create: false."
description: "Algorithm of the private key of the client certificate"
type: str
default: ""
+1 -1
View File
@@ -2,7 +2,7 @@ dependencies: []
galaxy_info:
author: "Markus Pesch"
company: "Cryptic Systems"
description: "Role to create and manage an existing PKI infrastructure"
description: "Role to create and managed an existing PKI infrastructure"
galaxy_tags:
- ca
- ssl
-6
View File
@@ -1,6 +0,0 @@
---
collections:
- name: community.crypto
- name: community.docker
- name: community.general
-19
View File
@@ -1,19 +0,0 @@
---
- name: Converge
hosts: all
# Passphrases are fixtures, they exercise the protected code paths of the role.
vars:
certificate_authority_root_ca_common_name: "Molecule Root CA"
certificate_authority_root_ca_tls_key_passphrase: "molecule-root-ca"
certificate_authority_intermediate_ca_common_name: "Molecule Intermediate CA"
certificate_authority_intermediate_ca_tls_key_passphrase: "molecule-intermediate-ca"
certificate_authority_client_skip: false
certificate_authority_client_common_name: "molecule.example.local"
certificate_authority_client_subject_alternative_names:
- "DNS:molecule.example.local"
- "IP:10.11.12.13"
tasks:
- name: Include the role certificate_authority
ansible.builtin.include_role:
name: certificate_authority
-25
View File
@@ -1,25 +0,0 @@
---
- name: Create
hosts: localhost
gather_facts: false
tasks:
- name: Start a container per platform
community.docker.docker_container:
name: "{{ item.name }}"
image: "{{ item.image }}"
command: "sleep infinity"
state: started
loop: "{{ molecule_yml.platforms }}"
loop_control:
label: "{{ item.name }}"
- name: Write the instance config
ansible.builtin.copy:
content: |
{% for platform in molecule_yml.platforms %}
- instance: {{ platform.name }}
connection: community.docker.docker
{% endfor %}
dest: "{{ molecule_instance_config }}"
mode: "0600"
-19
View File
@@ -1,19 +0,0 @@
---
- name: Destroy
hosts: localhost
gather_facts: false
tasks:
- name: Remove the container of every platform
community.docker.docker_container:
name: "{{ item.name }}"
state: absent
loop: "{{ molecule_yml.platforms }}"
loop_control:
label: "{{ item.name }}"
- name: Empty the instance config
ansible.builtin.copy:
content: "[]"
dest: "{{ molecule_instance_config }}"
mode: "0600"
-24
View File
@@ -1,24 +0,0 @@
---
driver:
name: default
options:
managed: true
login_cmd_template: "docker exec --interactive --tty {instance} bash"
platforms:
- name: certificate-authority-archlinux
image: docker.io/library/archlinux:base
- name: certificate-authority-debian
image: docker.io/library/debian:13
- name: certificate-authority-fedora
image: registry.fedoraproject.org/fedora:43
provisioner:
name: ansible
# The role under test is the project directory itself, so its parent has to be on the roles path.
env:
ANSIBLE_ROLES_PATH: "${MOLECULE_PROJECT_DIRECTORY}/.."
config_options:
defaults:
interpreter_python: auto_silent
-22
View File
@@ -1,22 +0,0 @@
---
- name: Prepare
hosts: all
gather_facts: false
vars:
# The base images ship neither a python interpreter for ansible nor the tools the role shells out to.
_bootstrap: |
set -eu
if command -v pacman > /dev/null; then
pacman --sync --refresh --noconfirm ca-certificates gawk openssl python
elif command -v apt-get > /dev/null; then
apt-get update
apt-get install --yes ca-certificates gawk openssl python3
else
dnf install --assumeyes ca-certificates gawk openssl python3
fi
tasks:
# The raw command is wrapped explicitly, because the bootstrap relies on shell builtins.
- name: Bootstrap the python interpreter and the tools required by the role
ansible.builtin.raw: "/bin/sh -c {{ _bootstrap | quote }}"
changed_when: true
-4
View File
@@ -1,4 +0,0 @@
---
# The role has no role dependencies, but molecule warns about the missing file.
roles: []
-88
View File
@@ -1,88 +0,0 @@
---
- name: Verify
hosts: all
vars:
_root_ca_path: "/etc/ansible-playbook/pki/ca"
_intermediate_ca_path: "/etc/ansible-playbook/pki/intermediate"
_client_path: "/etc/ansible-playbook/pki/client"
# cert.pem and cert-req.pem are left out on purpose, the role does not pin their mode.
_expected_modes:
/etc/ansible-playbook/pki/ca: "0755"
/etc/ansible-playbook/pki/ca/privkey.pem: "0600"
/etc/ansible-playbook/pki/ca/all.pem: "0600"
/etc/ansible-playbook/pki/intermediate: "0755"
/etc/ansible-playbook/pki/intermediate/privkey.pem: "0600"
/etc/ansible-playbook/pki/intermediate/chain.pem: "0644"
/etc/ansible-playbook/pki/intermediate/fullchain.pem: "0644"
/etc/ansible-playbook/pki/intermediate/all.pem: "0600"
/etc/ansible-playbook/pki/client: "0755"
/etc/ansible-playbook/pki/client/privkey.pem: "0600"
/etc/ansible-playbook/pki/client/chain.pem: "0644"
/etc/ansible-playbook/pki/client/fullchain.pem: "0644"
/etc/ansible-playbook/pki/client/all.pem: "0600"
_trust_store_anchor:
Archlinux: "/etc/ca-certificates/trust-source/anchors/Molecule_Root_CA.pem"
Debian: "/usr/local/share/ca-certificates/Molecule_Root_CA.crt"
RedHat: "/etc/pki/ca-trust/source/anchors/Molecule_Root_CA.pem"
tasks:
- name: Stat the generated files
ansible.builtin.stat:
path: "{{ item.key }}"
register: _pki_files
loop: "{{ _expected_modes | dict2items }}"
loop_control:
label: "{{ item.key }}"
- name: Assert that the generated files exist with the expected mode
ansible.builtin.assert:
that:
- item.stat.exists
- item.stat.mode == item.item.value
fail_msg: "{{ item.item.key }} has mode {{ item.stat.mode | default('none') }} instead of {{ item.item.value }}"
loop: "{{ _pki_files.results }}"
loop_control:
label: "{{ item.item.key }}"
- name: Verify the client certificate against the root certificate authority
ansible.builtin.command:
cmd: >-
openssl verify
-CAfile {{ _root_ca_path }}/cert.pem
-untrusted {{ _intermediate_ca_path }}/cert.pem
{{ _client_path }}/cert.pem
changed_when: false
- name: Read the fullchain file of the client
ansible.builtin.slurp:
src: "{{ _client_path }}/fullchain.pem"
register: _client_fullchain
- name: Assert that the fullchain of the client holds the complete chain and ends with a newline
vars:
_content: "{{ _client_fullchain.content | b64decode }}"
ansible.builtin.assert:
that:
- _content | regex_findall('BEGIN CERTIFICATE') | length == 3
- _content.endswith('\n')
fail_msg: "unexpected content in {{ _client_path }}/fullchain.pem"
- name: Read the subject alternative names of the client certificate
community.crypto.x509_certificate_info:
path: "{{ _client_path }}/cert.pem"
register: _client_cert_info
- name: Assert that the requested subject alternative names are present
ansible.builtin.assert:
that: _client_cert_info.subject_alt_name | sort == ['DNS:molecule.example.local', 'IP:10.11.12.13']
fail_msg: "unexpected subject alternative names {{ _client_cert_info.subject_alt_name }}"
- name: Stat the anchor in the systems trust store
ansible.builtin.stat:
path: "{{ _trust_store_anchor[ansible_facts['os_family']] }}"
register: _anchor
- name: Assert that the root certificate authority was imported into the systems trust store
ansible.builtin.assert:
that: _anchor.stat.exists
fail_msg: "{{ _trust_store_anchor[ansible_facts['os_family']] }} is missing"
+87 -117
View File
@@ -8,7 +8,7 @@
"license": "MIT",
"devDependencies": {
"@bitnami/readme-generator-for-helm": "^2.5.0",
"markdownlint-cli": "^0.49.0"
"markdownlint-cli": "^0.48.0"
},
"engines": {
"node": ">=16.0.0",
@@ -64,9 +64,9 @@
"license": "MIT"
},
"node_modules/ansi-regex": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
"integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
"version": "6.1.0",
"resolved": "https://repo-nexus.orbis.dedalus.com/nexus/repository/npm-all/ansi-regex/-/ansi-regex-6.1.0.tgz",
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -280,9 +280,9 @@
"license": "ISC"
},
"node_modules/get-east-asian-width": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz",
"integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==",
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz",
"integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==",
"dev": true,
"license": "MIT",
"engines": {
@@ -315,9 +315,9 @@
}
},
"node_modules/ignore": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz",
"integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==",
"version": "7.0.5",
"resolved": "https://repo-nexus.orbis.dedalus.com/nexus/repository/npm-all/ignore/-/ignore-7.0.5.tgz",
"integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -344,13 +344,13 @@
"license": "ISC"
},
"node_modules/ini": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/ini/-/ini-7.0.0.tgz",
"integrity": "sha512-ifK0CgjALofS5bkrcTy4RaQ9Vx2Knf/eLeIO+NaswQEpH1UblrtTSCIvN71qQDMq0PeQ/SSPojvEJp9vvvfr+w==",
"version": "4.1.3",
"resolved": "https://repo-nexus.orbis.dedalus.com/nexus/repository/npm-all/ini/-/ini-4.1.3.tgz",
"integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==",
"dev": true,
"license": "ISC",
"engines": {
"node": "^22.22.2 || ^24.15.0 || >=26.0.0"
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/is-alphabetical": {
@@ -402,26 +402,16 @@
}
},
"node_modules/js-yaml": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.2.1.tgz",
"integrity": "sha512-zfLtNfQqxVqq3uaTqSkh4x4hZw3KHobGUA0fJUj4wawW8bsQLTVqpHdXSIzidh7o+4lEW36tANuAGdaFx6Zgnw==",
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/puzrin"
},
{
"type": "github",
"url": "https://github.com/sponsors/nodeca"
}
],
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.mjs"
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/jsonc-parser": {
@@ -469,20 +459,10 @@
}
},
"node_modules/linkify-it": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.2.tgz",
"integrity": "sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==",
"version": "5.0.0",
"resolved": "https://repo-nexus.orbis.dedalus.com/nexus/repository/npm-all/linkify-it/-/linkify-it-5.0.0.tgz",
"integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/puzrin"
},
{
"type": "github",
"url": "https://github.com/sponsors/markdown-it"
}
],
"license": "MIT",
"dependencies": {
"uc.micro": "^2.0.0"
@@ -496,25 +476,15 @@
"license": "MIT"
},
"node_modules/markdown-it": {
"version": "14.3.0",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.3.0.tgz",
"integrity": "sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw==",
"version": "14.1.1",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz",
"integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/puzrin"
},
{
"type": "github",
"url": "https://github.com/sponsors/markdown-it"
}
],
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1",
"entities": "^4.5.0",
"linkify-it": "^5.0.2",
"entities": "^4.4.0",
"linkify-it": "^5.0.0",
"mdurl": "^2.0.0",
"punycode.js": "^2.3.1",
"uc.micro": "^2.1.0"
@@ -538,9 +508,9 @@
}
},
"node_modules/markdownlint": {
"version": "0.41.1",
"resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.41.1.tgz",
"integrity": "sha512-qHKeU2E1bdyNAT077go2FVTNXvYcktN5IHtF6XyeD1l0PClxzSp2tUApAV14ORI8DGX4H9bNKZEzelZp4qn8IA==",
"version": "0.40.0",
"resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.40.0.tgz",
"integrity": "sha512-UKybllYNheWac61Ia7T6fzuQNDZimFIpCg2w6hHjgV1Qu0w1TV0LlSgryUGzM0bkKQCBhy2FDhEELB73Kb0kAg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -552,40 +522,40 @@
"micromark-extension-gfm-table": "2.1.1",
"micromark-extension-math": "3.1.0",
"micromark-util-types": "2.0.2",
"string-width": "8.2.1"
"string-width": "8.1.0"
},
"engines": {
"node": ">=22"
"node": ">=20"
},
"funding": {
"url": "https://github.com/sponsors/DavidAnson"
}
},
"node_modules/markdownlint-cli": {
"version": "0.49.1",
"resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.49.1.tgz",
"integrity": "sha512-qpYqJbSYf3jv57bdnFmCaZ/Wlu6IYHp2b6SOKrKBJ7OnPrDHIKmx4NERWH49QH9viTI6yO6raVDDn5nrf60VQQ==",
"version": "0.48.0",
"resolved": "https://registry.npmjs.org/markdownlint-cli/-/markdownlint-cli-0.48.0.tgz",
"integrity": "sha512-NkZQNu2E0Q5qLEEHwWj674eYISTLD4jMHkBzDobujXd1kv+yCxi8jOaD/rZoQNW1FBBMMGQpuW5So8B51N/e0A==",
"dev": true,
"license": "MIT",
"dependencies": {
"commander": "~15.0.0",
"commander": "~14.0.3",
"deep-extend": "~0.6.0",
"ignore": "~7.0.6",
"js-yaml": "~5.2.1",
"ignore": "~7.0.5",
"js-yaml": "~4.1.1",
"jsonc-parser": "~3.3.1",
"jsonpointer": "~5.0.1",
"markdown-it": "~14.3.0",
"markdownlint": "~0.41.1",
"minimatch": "~10.2.5",
"run-con": "~1.3.3",
"smol-toml": "~1.7.0",
"tinyglobby": "~0.2.17"
"markdown-it": "~14.1.1",
"markdownlint": "~0.40.0",
"minimatch": "~10.2.4",
"run-con": "~1.3.2",
"smol-toml": "~1.6.0",
"tinyglobby": "~0.2.15"
},
"bin": {
"markdownlint": "markdownlint.js"
},
"engines": {
"node": ">=22"
"node": ">=20"
}
},
"node_modules/markdownlint-cli/node_modules/balanced-match": {
@@ -599,9 +569,9 @@
}
},
"node_modules/markdownlint-cli/node_modules/brace-expansion": {
"version": "5.0.7",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz",
"integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==",
"version": "5.0.6",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
"integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -612,13 +582,13 @@
}
},
"node_modules/markdownlint-cli/node_modules/commander": {
"version": "15.0.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-15.0.0.tgz",
"integrity": "sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg==",
"version": "14.0.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz",
"integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=22.12.0"
"node": ">=20"
}
},
"node_modules/markdownlint-cli/node_modules/minimatch": {
@@ -637,6 +607,23 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/markdownlint/node_modules/string-width": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.0.tgz",
"integrity": "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==",
"dev": true,
"license": "MIT",
"dependencies": {
"get-east-asian-width": "^1.3.0",
"strip-ansi": "^7.1.0"
},
"engines": {
"node": ">=20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/mdurl": {
"version": "2.0.0",
"resolved": "https://repo-nexus.orbis.dedalus.com/nexus/repository/npm-all/mdurl/-/mdurl-2.0.0.tgz",
@@ -1251,9 +1238,9 @@
}
},
"node_modules/picomatch": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
"integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1284,14 +1271,14 @@
}
},
"node_modules/run-con": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/run-con/-/run-con-1.3.3.tgz",
"integrity": "sha512-Lb7OKM9aaykzyoNiHGhSVCjZsvbyy6qDMp2vDXL+MoCfz3GfNJtHYH7uYsU3QNMyInBk++xx+EZ8xZ8Sxs5fNQ==",
"version": "1.3.2",
"resolved": "https://repo-nexus.orbis.dedalus.com/nexus/repository/npm-all/run-con/-/run-con-1.3.2.tgz",
"integrity": "sha512-CcfE+mYiTcKEzg0IqS08+efdnH0oJ3zV0wSUFBNrMHMuxCtXvBCLzCJHatwuXDcu/RlhjTziTo/a1ruQik6/Yg==",
"dev": true,
"license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
"dependencies": {
"deep-extend": "^0.6.0",
"ini": "~7.0.0",
"ini": "~4.1.0",
"minimist": "^1.2.8",
"strip-json-comments": "~3.1.1"
},
@@ -1300,9 +1287,9 @@
}
},
"node_modules/smol-toml": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.7.0.tgz",
"integrity": "sha512-aqVvWoyO21L23mb+drl4RmMXbf6N7FdHjAhTRA9ZBL7apWBgfWC16KjrASI+1p9GAroljyMHj6fK67i0UiTNvQ==",
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.1.tgz",
"integrity": "sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
@@ -1312,31 +1299,14 @@
"url": "https://github.com/sponsors/cyyynthia"
}
},
"node_modules/string-width": {
"version": "8.2.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.1.tgz",
"integrity": "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==",
"dev": true,
"license": "MIT",
"dependencies": {
"get-east-asian-width": "^1.5.0",
"strip-ansi": "^7.1.2"
},
"engines": {
"node": ">=20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/strip-ansi": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz",
"integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==",
"version": "7.1.0",
"resolved": "https://repo-nexus.orbis.dedalus.com/nexus/repository/npm-all/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^6.2.2"
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
@@ -1359,14 +1329,14 @@
}
},
"node_modules/tinyglobby": {
"version": "0.2.17",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
"integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
"version": "0.2.15",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"fdir": "^6.5.0",
"picomatch": "^4.0.4"
"picomatch": "^4.0.3"
},
"engines": {
"node": ">=12.0.0"
@@ -1377,7 +1347,7 @@
},
"node_modules/uc.micro": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
"resolved": "https://repo-nexus.orbis.dedalus.com/nexus/repository/npm-all/uc.micro/-/uc.micro-2.1.0.tgz",
"integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
"dev": true,
"license": "MIT"
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "certificate-authority-ansible-role",
"homepage": "https://git.cryptic.systems/volker.raschek/certificate-authority-ansible-role.git",
"homepage": "https://git.cryptic.systems/volker.raschel/certificate-authority-ansible-role.git",
"license": "MIT",
"private": true,
"engineStrict": true,
@@ -10,10 +10,10 @@
},
"scripts": {
"readme:lint": "markdownlint *.md -f",
"readme:parameters": "readme-generator -v defaults/main.yml -r README.md"
"readme:parameters": "readme-generator -v defaults/main.yaml -r README.md"
},
"devDependencies": {
"@bitnami/readme-generator-for-helm": "^2.5.0",
"markdownlint-cli": "^0.49.0"
"markdownlint-cli": "^0.48.0"
}
}
-5
View File
@@ -1,5 +0,0 @@
---
collections:
- name: community.crypto
- name: community.general
+112
View File
@@ -0,0 +1,112 @@
---
- name: Create directory to store tls keys and certificates of the client
ansible.builtin.file:
path: "{{ certificate_authority_client_path }}"
owner: "root"
group: "root"
mode: "0700"
state: directory
- name: Create unprotected client certificate
ansible.builtin.include_tasks: client_certificate_unprotected.yaml
when: certificate_authority_client_create is defined and
certificate_authority_client_create and
certificate_authority_client_tls_key_passphrase is defined and
certificate_authority_client_tls_key_passphrase | length <= 0
- name: Create passphrase protected client certificate
ansible.builtin.include_tasks: client_certificate_unprotected.yaml
when: certificate_authority_client_create is defined and
certificate_authority_client_create and
certificate_authority_client_tls_key_passphrase is defined and
certificate_authority_client_tls_key_passphrase | length > 0
- name: Import client certificate
ansible.builtin.include_tasks: client_certificate_import.yaml
when: certificate_authority_client_create is defined and
not certificate_authority_client_create
- name: Create certificate chain file
block:
- name: Check if intermediate certificate exists
ansible.builtin.stat:
path: "{{ certificate_authority_intermediate_ca_path }}/cert.pem"
register: _stat_result
- name: Concatenate client certificate and intermediate certificate
vars:
_chain_files:
- "{{ certificate_authority_client_path }}/cert.pem"
- "{{ certificate_authority_intermediate_ca_path }}/cert.pem"
ansible.builtin.command:
cmd: awk 1 {{ _chain_files | join(' ') }}
register: chain_content
changed_when: chain_content.rc == 0
when: _stat_result.stat.exists is defined and
_stat_result.stat.exists
- name: Create concatenated chain file
ansible.builtin.copy:
content: "{{ chain_content.stdout_lines | join('\n') }}"
dest: "{{ certificate_authority_client_path }}/chain.pem"
owner: "root"
group: "root"
mode: "0644"
remote_src: true
when: _stat_result.stat.exists is defined and
_stat_result.stat.exists
- name: Create certificate fullchain file
block:
- name: Check if intermediate chain exists
ansible.builtin.stat:
path: "{{ certificate_authority_intermediate_ca_path }}/chain.pem"
register: _stat_result
- name: Concatenate client certificate and intermediate chain file
vars:
_chain_files:
- "{{ certificate_authority_client_path }}/cert.pem"
- "{{ certificate_authority_intermediate_ca_path }}/chain.pem"
ansible.builtin.command:
cmd: awk 1 {{ _chain_files | join(' ') }}
register: chain_content
changed_when: chain_content.rc == 0
when: _stat_result.stat.exists is defined and
_stat_result.stat.exists
- name: Create concatenated fullchain file
ansible.builtin.copy:
content: "{{ chain_content.stdout_lines | join('\n') }}"
dest: "{{ certificate_authority_client_path }}/fullchain.pem"
owner: "root"
group: "root"
mode: "0644"
remote_src: true
when: _stat_result.stat.exists is defined and
_stat_result.stat.exists
- name: Create file with private key and fullchain file of the client
block:
- name: Check if fullchain exists
ansible.builtin.stat:
path: "{{ certificate_authority_client_path }}/fullchain.pem"
register: _stat_result
- name: Concatenate private key and fullchain file of the client
vars:
_chain_files:
- "{{ certificate_authority_client_path }}/privkey.pem"
- "{{ certificate_authority_client_path }}/fullchain.pem"
ansible.builtin.command:
cmd: awk 1 {{ _chain_files | join(' ') }}
register: chain_content
changed_when: chain_content.rc == 0
when: _stat_result.stat.exists is defined and
_stat_result.stat.exists
- name: Create concatenated file
ansible.builtin.copy:
content: "{{ chain_content.stdout_lines | join('\n') }}"
dest: "{{ certificate_authority_client_path }}/all.pem"
owner: "root"
group: "root"
mode: "0600"
remote_src: true
when: _stat_result.stat.exists is defined and
_stat_result.stat.exists
-72
View File
@@ -1,72 +0,0 @@
---
- name: Create directory to store tls keys and certificates of the client
ansible.builtin.file:
path: "{{ certificate_authority_client_path }}"
owner: "root"
group: "root"
mode: "0755"
state: directory
- name: Verify that the signing intermediate Certificate Authority (CA) is available
when: certificate_authority_client_create is defined and
certificate_authority_client_create
block:
- name: Check private key of the intermediate Certificate Authority (CA)
ansible.builtin.stat:
path: "{{ certificate_authority_intermediate_ca_path }}/privkey.pem"
register: _intermediate_ca_privkey
- name: Assert that the private key of the intermediate Certificate Authority (CA) exists
ansible.builtin.assert:
that: _intermediate_ca_privkey.stat.exists
fail_msg: >-
Signing the client certificate requires
{{ certificate_authority_intermediate_ca_path }}/privkey.pem. Either unset
certificate_authority_intermediate_ca_skip so the intermediate certificate authority is
created or imported, or point certificate_authority_intermediate_ca_path to an existing one.
- name: Create unprotected client certificate
ansible.builtin.include_tasks: client_certificate_unprotected.yml
when: certificate_authority_client_create is defined and
certificate_authority_client_create and
certificate_authority_client_tls_key_passphrase is defined and
certificate_authority_client_tls_key_passphrase | length <= 0
- name: Create passphrase protected client certificate
ansible.builtin.include_tasks: client_certificate_protected.yml
when: certificate_authority_client_create is defined and
certificate_authority_client_create and
certificate_authority_client_tls_key_passphrase is defined and
certificate_authority_client_tls_key_passphrase | length > 0
- name: Import client certificate
ansible.builtin.include_tasks: client_certificate_import.yml
when: certificate_authority_client_create is defined and
not certificate_authority_client_create
- name: Create certificate chain file
ansible.builtin.include_tasks: concatenate.yml
vars:
_concat_sources:
- "{{ certificate_authority_client_path }}/cert.pem"
- "{{ certificate_authority_intermediate_ca_path }}/cert.pem"
_concat_dest: "{{ certificate_authority_client_path }}/chain.pem"
_concat_mode: "0644"
- name: Create certificate fullchain file
ansible.builtin.include_tasks: concatenate.yml
vars:
_concat_sources:
- "{{ certificate_authority_client_path }}/cert.pem"
- "{{ certificate_authority_intermediate_ca_path }}/chain.pem"
_concat_dest: "{{ certificate_authority_client_path }}/fullchain.pem"
_concat_mode: "0644"
- name: Create file with private key and fullchain file of the client
ansible.builtin.include_tasks: concatenate.yml
vars:
_concat_sources:
- "{{ certificate_authority_client_path }}/privkey.pem"
- "{{ certificate_authority_client_path }}/fullchain.pem"
_concat_dest: "{{ certificate_authority_client_path }}/all.pem"
_concat_mode: "0600"
@@ -3,7 +3,7 @@
- name: Import private key of a client
ansible.builtin.copy:
content: "{{ certificate_authority_client_tls_key_content }}"
dest: "{{ certificate_authority_client_path }}/privkey.pem"
dest: "{{ certificate_authority_client_ca_path }}/privkey.pem"
owner: "root"
group: "root"
mode: "0600"
@@ -12,7 +12,7 @@
- name: Import certificate of a client
ansible.builtin.copy:
content: "{{ certificate_authority_client_tls_crt_content }}"
dest: "{{ certificate_authority_client_path }}/cert.pem"
dest: "{{ certificate_authority_client_tls_crt_content }}/cert.pem"
owner: "root"
group: "root"
mode: "0644"
@@ -3,12 +3,11 @@
- name: Create private key for client
community.crypto.openssl_privatekey:
path: "{{ certificate_authority_client_path }}/privkey.pem"
mode: "0600"
type: "{{ certificate_authority_client_tls_key_type }}"
passphrase: "{{ certificate_authority_client_tls_key_passphrase }}"
cipher: auto
- name: Create a certificate signing request (CSR) for client certificate
- name: Create a certificate signing request (CSR) for client certificate without subject alternative names (SANs)
community.crypto.openssl_csr:
common_name: "{{ certificate_authority_client_common_name }}"
countryName: "{{ certificate_authority_client_country_name }}"
@@ -22,7 +21,28 @@
privatekey_passphrase: "{{ certificate_authority_client_tls_key_passphrase }}"
privatekey_path: "{{ certificate_authority_client_path }}/privkey.pem"
state_or_province_name: "{{ certificate_authority_client_state_or_province_name }}"
subject_alt_name: "{{ certificate_authority_client_subject_alternative_names if certificate_authority_client_subject_alternative_names | length > 0 else omit }}"
when: |
certificate_authority_client_subject_alternative_names is not defined or
(certificate_authority_client_subject_alternative_names is defined and
certificate_authority_client_subject_alternative_names | length <= 0)
- name: Create a certificate signing request (CSR) for client certificate with subject alternative names (SANs)
community.crypto.openssl_csr:
common_name: "{{ certificate_authority_client_common_name }}"
countryName: "{{ certificate_authority_client_country_name }}"
email_address: "{{ certificate_authority_client_email_address }}"
extendedKeyUsage:
- clientAuth
- serverAuth
organization_name: "{{ certificate_authority_client_organization_name }}"
organizational_unit_name: "{{ certificate_authority_client_organizational_unit_name }}"
path: "{{ certificate_authority_client_path }}/cert-req.pem"
privatekey_path: "{{ certificate_authority_client_path }}/privkey.pem"
privatekey_passphrase: "{{ certificate_authority_client_tls_key_passphrase }}"
state_or_province_name: "{{ certificate_authority_client_state_or_province_name }}"
subject_alt_name: "{{ certificate_authority_client_subject_alternative_names | map('regex_replace', '^', 'DNS:') | list | join(',') | quote }}"
when: certificate_authority_client_subject_alternative_names is defined and
certificate_authority_client_subject_alternative_names | length > 0
- name: Create signed client certificate - unprotected intermediate Certificate Authority (CA)
community.crypto.x509_certificate:
@@ -3,10 +3,28 @@
- name: Create private key for client
community.crypto.openssl_privatekey:
path: "{{ certificate_authority_client_path }}/privkey.pem"
mode: "0600"
type: "{{ certificate_authority_client_tls_key_type }}"
- name: Create a certificate signing request (CSR) for client certificate
- name: Create a certificate signing request (CSR) for client certificate without subject alternative names (SANs)
community.crypto.openssl_csr:
common_name: "{{ certificate_authority_client_common_name }}"
countryName: "{{ certificate_authority_client_country_name }}"
email_address: "{{ certificate_authority_client_email_address }}"
extendedKeyUsage:
- clientAuth
- serverAuth
organization_name: "{{ certificate_authority_client_organization_name }}"
organizational_unit_name: "{{ certificate_authority_client_organizational_unit_name }}"
path: "{{ certificate_authority_client_path }}/cert-req.pem"
privatekey_passphrase: "{{ certificate_authority_client_tls_key_passphrase }}"
privatekey_path: "{{ certificate_authority_client_path }}/privkey.pem"
state_or_province_name: "{{ certificate_authority_client_state_or_province_name }}"
when: |
certificate_authority_client_subject_alternative_names is not defined or
(certificate_authority_client_subject_alternative_names is defined and
certificate_authority_client_subject_alternative_names | length <= 0)
- name: Create a certificate signing request (CSR) for client certificate with subject alternative names (SANs)
community.crypto.openssl_csr:
common_name: "{{ certificate_authority_client_common_name }}"
countryName: "{{ certificate_authority_client_country_name }}"
@@ -19,7 +37,9 @@
path: "{{ certificate_authority_client_path }}/cert-req.pem"
privatekey_path: "{{ certificate_authority_client_path }}/privkey.pem"
state_or_province_name: "{{ certificate_authority_client_state_or_province_name }}"
subject_alt_name: "{{ certificate_authority_client_subject_alternative_names if certificate_authority_client_subject_alternative_names | length > 0 else omit }}"
subject_alt_name: "{{ certificate_authority_client_subject_alternative_names | map('regex_replace', '^', 'DNS:') | list | join(',') | quote }}"
when: certificate_authority_client_subject_alternative_names is defined and
certificate_authority_client_subject_alternative_names | length > 0
- name: Create signed client certificate - unprotected intermediate Certificate Authority (CA)
community.crypto.x509_certificate:
-24
View File
@@ -1,24 +0,0 @@
---
# awk 1 prints every line and thereby normalizes source files whose last line lacks a newline.
- name: Check the source files of {{ _concat_dest }}
ansible.builtin.stat:
path: "{{ item }}"
register: _concat_stat
loop: "{{ _concat_sources }}"
- name: Read the source files of {{ _concat_dest }}
ansible.builtin.command:
cmd: "awk 1 {{ _concat_sources | join(' ') }}"
register: _concat_content
changed_when: false
when: _concat_stat.results | rejectattr('stat.exists') | list | length == 0
- name: Write {{ _concat_dest }}
ansible.builtin.copy:
content: "{{ _concat_content.stdout }}\n"
dest: "{{ _concat_dest }}"
owner: "root"
group: "root"
mode: "{{ _concat_mode }}"
when: _concat_content is not skipped
@@ -0,0 +1,112 @@
---
- name: Create directory to store tls keys and certificates of the intermediate CA
ansible.builtin.file:
path: "{{ certificate_authority_intermediate_ca_path }}"
owner: "root"
group: "root"
mode: "0700"
state: "directory"
- name: Create unprotected intermediate Certificate Authority (CA)
ansible.builtin.include_tasks: intermediate_certificate_authority_unprotected.yaml
when: certificate_authority_intermediate_ca_create is defined and
certificate_authority_intermediate_ca_create and
certificate_authority_intermediate_ca_tls_key_passphrase is defined and
certificate_authority_intermediate_ca_tls_key_passphrase | length <= 0
- name: Create passphrase protected intermediate Certificate Authority (CA)
ansible.builtin.include_tasks: intermediate_certificate_authority_protected.yaml
when: certificate_authority_intermediate_ca_create is defined and
certificate_authority_intermediate_ca_create and
certificate_authority_intermediate_ca_tls_key_passphrase is defined and
certificate_authority_intermediate_ca_tls_key_passphrase | length > 0
- name: Import intermediate Certificate Authority (CA)
ansible.builtin.include_tasks: intermediate_certificate_authority_import.yaml
when: certificate_authority_intermediate_ca_create is defined and
not certificate_authority_intermediate_ca_create
- name: Create certificate chain file
block:
- name: Check if root certificate exists
ansible.builtin.stat:
path: "{{ certificate_authority_root_ca_path }}/cert.pem"
register: _stat_result
- name: Concatenate intermediate certificate and root certificate
vars:
_chain_files:
- "{{ certificate_authority_intermediate_ca_path }}/cert.pem"
- "{{ certificate_authority_root_ca_path }}/cert.pem"
ansible.builtin.command:
cmd: awk 1 {{ _chain_files | join(' ') }}
register: chain_content
changed_when: chain_content.rc == 0
when: _stat_result.stat.exists is defined and
_stat_result.stat.exists
- name: Create concatenated chain file
ansible.builtin.copy:
content: "{{ chain_content.stdout_lines | join('\n') }}"
dest: "{{ certificate_authority_intermediate_ca_path }}/chain.pem"
owner: "root"
group: "root"
mode: "0644"
remote_src: true
when: _stat_result.stat.exists is defined and
_stat_result.stat.exists
- name: Create certificate fullchain file
block:
- name: Check if root chain exists
ansible.builtin.stat:
path: "{{ certificate_authority_root_ca_path }}/chain.pem"
register: _stat_result
- name: Concatenate intermediate certificate and root chain file
vars:
_chain_files:
- "{{ certificate_authority_intermediate_ca_path }}/cert.pem"
- "{{ certificate_authority_root_ca_path }}/chain.pem"
ansible.builtin.command:
cmd: awk 1 {{ _chain_files | join(' ') }}
register: chain_content
changed_when: chain_content.rc == 0
when: _stat_result.stat.exists is defined and
_stat_result.stat.exists
- name: Create concatenated fullchain file
ansible.builtin.copy:
content: "{{ chain_content.stdout_lines | join('\n') }}"
dest: "{{ certificate_authority_intermediate_ca_path }}/fullchain.pem"
owner: "root"
group: "root"
mode: "0644"
remote_src: true
when: _stat_result.stat.exists is defined and
_stat_result.stat.exists
- name: Create file with private key and fullchain file of intermediate Certificate Authority (CA)
block:
- name: Check if private key exists
ansible.builtin.stat:
path: "{{ certificate_authority_intermediate_ca_path }}/privkey.pem"
register: _stat_result
- name: Concatenate private key and fullchain file of intermediate Certificate Authority (CA)
vars:
_chain_files:
- "{{ certificate_authority_intermediate_ca_path }}/privkey.pem"
- "{{ certificate_authority_intermediate_ca_path }}/fullchain.pem"
ansible.builtin.command:
cmd: awk 1 {{ _chain_files | join(' ') }}
register: chain_content
changed_when: chain_content.rc == 0
when: _stat_result.stat.exists is defined and
_stat_result.stat.exists
- name: Create concatenated file
ansible.builtin.copy:
content: "{{ chain_content.stdout_lines | join('\n') }}"
dest: "{{ certificate_authority_intermediate_ca_path }}/all.pem"
owner: "root"
group: "root"
mode: "0600"
remote_src: true
when: _stat_result.stat.exists is defined and
_stat_result.stat.exists
@@ -1,72 +0,0 @@
---
- name: Create directory to store tls keys and certificates of the intermediate CA
ansible.builtin.file:
path: "{{ certificate_authority_intermediate_ca_path }}"
owner: "root"
group: "root"
mode: "0755"
state: "directory"
- name: Verify that the signing root Certificate Authority (CA) is available
when: certificate_authority_intermediate_ca_create is defined and
certificate_authority_intermediate_ca_create
block:
- name: Check private key of the root Certificate Authority (CA)
ansible.builtin.stat:
path: "{{ certificate_authority_root_ca_path }}/privkey.pem"
register: _root_ca_privkey
- name: Assert that the private key of the root Certificate Authority (CA) exists
ansible.builtin.assert:
that: _root_ca_privkey.stat.exists
fail_msg: >-
Signing the intermediate certificate authority requires
{{ certificate_authority_root_ca_path }}/privkey.pem. Either unset
certificate_authority_root_ca_skip so the root certificate authority is created or
imported, or point certificate_authority_root_ca_path to an existing one.
- name: Create unprotected intermediate Certificate Authority (CA)
ansible.builtin.include_tasks: intermediate_certificate_authority_unprotected.yml
when: certificate_authority_intermediate_ca_create is defined and
certificate_authority_intermediate_ca_create and
certificate_authority_intermediate_ca_tls_key_passphrase is defined and
certificate_authority_intermediate_ca_tls_key_passphrase | length <= 0
- name: Create passphrase protected intermediate Certificate Authority (CA)
ansible.builtin.include_tasks: intermediate_certificate_authority_protected.yml
when: certificate_authority_intermediate_ca_create is defined and
certificate_authority_intermediate_ca_create and
certificate_authority_intermediate_ca_tls_key_passphrase is defined and
certificate_authority_intermediate_ca_tls_key_passphrase | length > 0
- name: Import intermediate Certificate Authority (CA)
ansible.builtin.include_tasks: intermediate_certificate_authority_import.yml
when: certificate_authority_intermediate_ca_create is defined and
not certificate_authority_intermediate_ca_create
- name: Create certificate chain file
ansible.builtin.include_tasks: concatenate.yml
vars:
_concat_sources:
- "{{ certificate_authority_intermediate_ca_path }}/cert.pem"
- "{{ certificate_authority_root_ca_path }}/cert.pem"
_concat_dest: "{{ certificate_authority_intermediate_ca_path }}/chain.pem"
_concat_mode: "0644"
- name: Create certificate fullchain file
ansible.builtin.include_tasks: concatenate.yml
vars:
_concat_sources:
- "{{ certificate_authority_intermediate_ca_path }}/cert.pem"
- "{{ certificate_authority_root_ca_path }}/chain.pem"
_concat_dest: "{{ certificate_authority_intermediate_ca_path }}/fullchain.pem"
_concat_mode: "0644"
- name: Create file with private key and fullchain file of intermediate Certificate Authority (CA)
ansible.builtin.include_tasks: concatenate.yml
vars:
_concat_sources:
- "{{ certificate_authority_intermediate_ca_path }}/privkey.pem"
- "{{ certificate_authority_intermediate_ca_path }}/fullchain.pem"
_concat_dest: "{{ certificate_authority_intermediate_ca_path }}/all.pem"
_concat_mode: "0600"
@@ -4,7 +4,6 @@
community.crypto.openssl_privatekey:
passphrase: "{{ certificate_authority_intermediate_ca_tls_key_passphrase }}"
path: "{{ certificate_authority_intermediate_ca_path }}/privkey.pem"
mode: "0600"
type: "{{ certificate_authority_intermediate_ca_tls_key_type }}"
cipher: auto
@@ -21,7 +20,6 @@
privatekey_passphrase: "{{ certificate_authority_intermediate_ca_tls_key_passphrase }}"
privatekey_path: "{{ certificate_authority_intermediate_ca_path }}/privkey.pem"
state_or_province_name: "{{ certificate_authority_intermediate_ca_state_or_province_name }}"
subject_alt_name: "{{ certificate_authority_intermediate_ca_subject_alternative_names if certificate_authority_intermediate_ca_subject_alternative_names | length > 0 else omit }}"
use_common_name_for_san: false
- name: Create signed client certificate - unprotected root Certificate Authority (CA)
@@ -3,7 +3,6 @@
- name: Create private key for intermediate CA
community.crypto.openssl_privatekey:
path: "{{ certificate_authority_intermediate_ca_path }}/privkey.pem"
mode: "0600"
type: "{{ certificate_authority_intermediate_ca_tls_key_type }}"
- name: Create a certificate signing request (CSR) for intermediate CA
@@ -18,7 +17,6 @@
path: "{{ certificate_authority_intermediate_ca_path }}/cert-req.pem"
privatekey_path: "{{ certificate_authority_intermediate_ca_path }}/privkey.pem"
state_or_province_name: "{{ certificate_authority_intermediate_ca_state_or_province_name }}"
subject_alt_name: "{{ certificate_authority_intermediate_ca_subject_alternative_names if certificate_authority_intermediate_ca_subject_alternative_names | length > 0 else omit }}"
use_common_name_for_san: false
- name: Create signed client certificate - unprotected root Certificate Authority (CA)
+26
View File
@@ -0,0 +1,26 @@
---
- name: Upgrade python package manager pip
ansible.builtin.pip:
name: pip
state: present
- name: Install required python library cryptography
ansible.builtin.pip:
name: cryptography>=1.2.3
state: present
- name: Create or import a root Certificate Authority (CA)
ansible.builtin.include_tasks: root_certificate_authority.yaml
when: certificate_authority_root_ca_skip is defined and
not certificate_authority_root_ca_skip
- name: Create or import a intermediate Certificate Authority (CA)
ansible.builtin.include_tasks: intermediate_certificate_authority.yaml
when: certificate_authority_intermediate_ca_skip is defined and
not certificate_authority_intermediate_ca_skip
- name: Create or import a client certificate
ansible.builtin.include_tasks: client_certificate.yaml
when: certificate_authority_client_skip is defined and
not certificate_authority_client_skip
-34
View File
@@ -1,34 +0,0 @@
---
- name: Include OS-specific variables
ansible.builtin.include_vars: "{{ lookup('first_found', params) }}"
vars:
params:
files:
- "{{ ansible_facts['distribution'] }}_{{ ansible_facts['architecture'] }}.yml"
- "{{ ansible_facts['distribution'] }}.yml"
- "{{ ansible_facts['os_family'] }}_{{ ansible_facts['architecture'] }}.yml"
- "{{ ansible_facts['os_family'] }}.yml"
- main.yml
paths:
- vars
- name: Install required python libraries
ansible.builtin.package:
name: "{{ certificate_authority_python_packages }}"
state: present
- name: Create or import a root Certificate Authority (CA)
ansible.builtin.include_tasks: root_certificate_authority.yml
when: certificate_authority_root_ca_skip is defined and
not certificate_authority_root_ca_skip
- name: Create or import a intermediate Certificate Authority (CA)
ansible.builtin.include_tasks: intermediate_certificate_authority.yml
when: certificate_authority_intermediate_ca_skip is defined and
not certificate_authority_intermediate_ca_skip
- name: Create or import a client certificate
ansible.builtin.include_tasks: client_certificate.yml
when: certificate_authority_client_skip is defined and
not certificate_authority_client_skip
@@ -5,25 +5,25 @@
path: "{{ certificate_authority_root_ca_path }}"
owner: "root"
group: "root"
mode: "0755"
mode: "0700"
state: "directory"
- name: Create unprotected root Certificate Authority (CA)
ansible.builtin.include_tasks: root_certificate_authority_unprotected.yml
ansible.builtin.include_tasks: root_certificate_authority_unprotected.yaml
when: certificate_authority_root_ca_create is defined and
certificate_authority_root_ca_create and
certificate_authority_root_ca_tls_key_passphrase is defined and
certificate_authority_root_ca_tls_key_passphrase | length <= 0
- name: Create passphrase protected root Certificate Authority (CA)
ansible.builtin.include_tasks: root_certificate_authority_protected.yml
ansible.builtin.include_tasks: root_certificate_authority_protected.yaml
when: certificate_authority_root_ca_create is defined and
certificate_authority_root_ca_create and
certificate_authority_root_ca_tls_key_passphrase is defined and
certificate_authority_root_ca_tls_key_passphrase | length > 0
- name: Import protected root Certificate Authority (CA)
ansible.builtin.include_tasks: root_certificate_authority_import.yml
ansible.builtin.include_tasks: root_certificate_authority_import.yaml
when: certificate_authority_root_ca_create is defined and
not certificate_authority_root_ca_create
@@ -38,21 +38,47 @@
- fullchain.pem
- name: Create file with private key and fullchain file of root Certificate Authority (CA)
ansible.builtin.include_tasks: concatenate.yml
vars:
_concat_sources:
- "{{ certificate_authority_root_ca_path }}/privkey.pem"
- "{{ certificate_authority_root_ca_path }}/fullchain.pem"
_concat_dest: "{{ certificate_authority_root_ca_path }}/all.pem"
_concat_mode: "0600"
block:
- name: Check if private key exists
ansible.builtin.stat:
path: "{{ certificate_authority_root_ca_path }}/privkey.pem"
register: _stat_result
- name: Concatenate private key and fullchain file of root Certificate Authority (CA)
vars:
_chain_files:
- "{{ certificate_authority_root_ca_path }}/privkey.pem"
- "{{ certificate_authority_root_ca_path }}/fullchain.pem"
ansible.builtin.command:
cmd: awk 1 {{ _chain_files | join(' ') }}
register: chain_content
changed_when: chain_content.rc == 0
when: _stat_result.stat.exists is defined and
_stat_result.stat.exists
- name: Create concatenated file
ansible.builtin.copy:
content: "{{ chain_content.stdout_lines | join('\n') }}"
dest: "{{ certificate_authority_root_ca_path }}/all.pem"
owner: "root"
group: "root"
mode: "0600"
remote_src: true
when: _stat_result.stat.exists is defined and
_stat_result.stat.exists
- name: Import certificate of root Certificate Authority (CA) into systems trust store
ansible.builtin.file:
src: "{{ certificate_authority_root_ca_path }}/cert.pem"
dest: "{{ certificate_authority_trust_store_anchor }}"
owner: root
group: root
state: link
notify: Update systems SSL/TLS trust store
when: certificate_authority_root_ca_import is defined and
certificate_authority_root_ca_import
block:
- name: Create symolic link
ansible.builtin.file:
src: "{{ certificate_authority_root_ca_path }}/cert.pem"
dest: "/etc/pki/ca-trust/source/anchors/{{ certificate_authority_root_ca_common_name | replace(' ', '_') }}.pem"
owner: root
group: root
state: link
- name: Update systems SSL/TLS trust store
ansible.builtin.command:
cmd: /usr/bin/update-ca-trust
register: _update_ca_trust
changed_when: _update_ca_trust.rc == 0
failed_when: _update_ca_trust.rc > 0
@@ -16,5 +16,4 @@
owner: "root"
group: "root"
mode: "0644"
notify: Update systems SSL/TLS trust store
when: certificate_authority_root_ca_tls_crt_content | length > 0
@@ -4,7 +4,6 @@
community.crypto.openssl_privatekey:
passphrase: "{{ certificate_authority_root_ca_tls_key_passphrase }}"
path: "{{ certificate_authority_root_ca_path }}/privkey.pem"
mode: "0600"
type: "{{ certificate_authority_root_ca_tls_key_type }}"
cipher: auto
@@ -21,7 +20,6 @@
privatekey_passphrase: "{{ certificate_authority_root_ca_tls_key_passphrase }}"
privatekey_path: "{{ certificate_authority_root_ca_path }}/privkey.pem"
state_or_province_name: "{{ certificate_authority_root_ca_state_or_province_name }}"
subject_alt_name: "{{ certificate_authority_root_ca_subject_alternative_names if certificate_authority_root_ca_subject_alternative_names | length > 0 else omit }}"
use_common_name_for_san: false
- name: Create self-signed certificate for root CA
@@ -33,4 +31,3 @@
provider: selfsigned
selfsigned_not_after: "{{ certificate_authority_root_ca_not_after }}"
selfsigned_not_before: "{{ certificate_authority_root_ca_not_before }}"
notify: Update systems SSL/TLS trust store
@@ -3,7 +3,6 @@
- name: Create private key for root CA
community.crypto.openssl_privatekey:
path: "{{ certificate_authority_root_ca_path }}/privkey.pem"
mode: "0600"
type: "{{ certificate_authority_root_ca_tls_key_type }}"
- name: Create a certificate signing request (CSR) for root CA
@@ -18,7 +17,6 @@
path: "{{ certificate_authority_root_ca_path }}/cert-req.pem"
privatekey_path: "{{ certificate_authority_root_ca_path }}/privkey.pem"
state_or_province_name: "{{ certificate_authority_root_ca_state_or_province_name }}"
subject_alt_name: "{{ certificate_authority_root_ca_subject_alternative_names if certificate_authority_root_ca_subject_alternative_names | length > 0 else omit }}"
use_common_name_for_san: false
- name: Create self-signed certificate for root CA
@@ -29,4 +27,3 @@
provider: selfsigned
selfsigned_not_after: "{{ certificate_authority_root_ca_not_after }}"
selfsigned_not_before: "{{ certificate_authority_root_ca_not_before }}"
notify: Update systems SSL/TLS trust store
-7
View File
@@ -1,7 +0,0 @@
---
certificate_authority_python_packages:
- python-cryptography
certificate_authority_trust_store_anchor: "/etc/ca-certificates/trust-source/anchors/{{ certificate_authority_root_ca_common_name | replace(' ', '_') }}.pem"
certificate_authority_trust_store_update_command: "/usr/bin/update-ca-trust"
-8
View File
@@ -1,8 +0,0 @@
---
certificate_authority_python_packages:
- python3-cryptography
# Debian based distributions only consider anchors with the file extension crt.
certificate_authority_trust_store_anchor: "/usr/local/share/ca-certificates/{{ certificate_authority_root_ca_common_name | replace(' ', '_') }}.crt"
certificate_authority_trust_store_update_command: "/usr/sbin/update-ca-certificates"
-7
View File
@@ -1,7 +0,0 @@
---
certificate_authority_python_packages:
- python3-cryptography
certificate_authority_trust_store_anchor: "/etc/pki/ca-trust/source/anchors/{{ certificate_authority_root_ca_common_name | replace(' ', '_') }}.pem"
certificate_authority_trust_store_update_command: "/usr/bin/update-ca-trust"
-6
View File
@@ -1,6 +0,0 @@
---
# Fallback for distributions without a dedicated vars file. Overridden by the
# os-specific file included in tasks/main.yml.
certificate_authority_python_packages:
- python3-cryptography