Generates SSL certificates on a PKI host and transfers the generated public and private key to the Ansible managed nodes. Optionally, the certificate authoritie's
certificate/s can be transferred as well as the optional Certificate Revocation List certificate/s.
Currently supported operating systems for the PKI host:
Red Hat Enterprise Linux 8, 9
Debian 11, 12
Requirements
This role requires a fully-setup Public Key Infrastructure (PKI). If you are looking for an automated way of setting this up, you can consider my role
public_key_infrastructure.
Role Variables
A note on templating connection variables
This role works with delegations (delegate_to). The SSL key pair generation runs on the host defined in crt_pki_host, so all tasks related to key generation will run on
crt_pki_host. Ansible, however, will try to lookup templated connection variables (such as remote_user) from the host we are delegating to (in this
case crt_pki_host) since Ansible 2.9.10.
There is a lengthy discussion on Ansible's GitHub that discusses this in more detail if you'd like to learn more about it.
What I'd like to point out is, if you make use of host_vars or group_vars, please make sure to define the connection variables (crt_pki_host, crt_pki_host_remote_user
and crt_pki_host_remote_port) in the host_vars of the host defined in crt_pki_host or the corresponding group_vars.
Of course, you can also define them in either host_vars/all or group_vars/all (as usual with Ansible).
Defining them in the inventory_hostname context will not work!
This does not affect users including the role with variables defined via extra_vars, on Play or on Task level, as these variables are valid in every host context.
Mandatory variables
variable
default
required
description
crt_cert_fqdn
unset
true
FQDN1 for the cert. This will be used to define the cert file name.
crt_ca_priv_key_pass
unset
true
Passphrase for the certificate authority (CA) private key
crt_pki_host
unset
true
PKI host - this is where the key generation will happen
crt_pki_host_remote_user
unset
true
Remote user to connect ot the PKI host to
Certificate suffixes
Variable to description
variable
description
crt_priv_key_suffix
Private key suffix
crt_cert_suffix
Certificate (aka public key) suffix
crt_csr_suffix
Certificate Signing Request (CSR) suffix
crt_crl_suffix
Certificate Revocation List (CRL) suffix
Variable to default variable
variable
default variable
crt_priv_key_suffix
_def_crt_priv_key_suffix
crt_cert_suffix
_def_crt_cert_suffix
crt_csr_suffix
_def_crt_csr_suffix
crt_crl_suffix
_def_crt_crl_suffix
Default variable to default value and requirement
default variable
default value
required
_def_crt_priv_key_suffix
key.pem
false
_def_crt_cert_suffix
cert.pem
false
_def_crt_csr_suffix
csr.pem
false
_def_crt_crl_suffix
crl.pem
false
Certificate Authority (CA)
Variable to description
variable
description
crt_ca_root_dir
Root directory of the CA
crt_ca_cert_name
Name of the CA certificate (aka public key)
crt_ca_chain_cert_name
Name of the CA chain certificate (for intermediate CAs)
crt_ca_priv_key_name
Name of the CA private key
crt_ca_priv_key_dir_path
Path of the CA's private keys directory
crt_ca_cert_dir_path
Path of the CA's certificates directory
crt_ca_csr_dir_path
Path of the CA's CSR directory
crt_ca_cert_path
Path of the CA certificate
crt_ca_chain_cert_path
Path of the CA chain certificate (for intermediate CAs)
crt_ca_priv_key_path
Path of the CA private key
crt_ca_fetch_ca_cert
Whether to fetch the CA certificate
crt_ca_fetch_ca_chain_cert
Whether to fetch the CA chain certificate (for intermediate CAs)
Depending on whether crt_combine_ca_crl_certs is set to true, crt_remote_ca_crl_path should either point to a file (when crt_combine_ca_crl_certs: true) or to a
directory (when crt_combine_ca_crl_certs: false).
On crt_combine_ca_crl_certs: true all files specified in crt_ca_crl_certs will be combined to a single file placed at crt_remote_ca_crl_path. Otherwise all downloaded files will be
placed with their original name into crt_remote_ca_crl_path.
Dependencies
This role makes use of the collection community.crypto and which is specified in collections/requirements.yml.
Example Playbook
---
- hosts: 'all'
gather_facts: false
roles:
- 'sscheib.generate_ssl_key_pairs'
vars:
#
# mandatory variables
#
# fully qualified domain name (FQDN) for the cert
crt_cert_fqdn: 'webserver.example.com'
# passphrase for the certificate authority (CA) private key
crt_ca_priv_key_pass: !vault |
$ANSIBLE_VAULT;1.1;AES256
[..]
# PKI host - this is where the key generation will happen
crt_pki_host: 'pki.example.com'
# remote user to connect to the PKI host with
crt_pki_host_remote_user: 'steffen'
#
# optional variables
#
# certificate suffixes
#
# private key suffix
crt_priv_key_suffix: 'key.pem'
# certificate signing request (CSR) suffix
crt_csr_suffix: 'csr.pem'
# certificate (aka public key) suffix
crt_cert_suffix: 'cert.pem'
# certificate revocation list (CRL) suffix
crt_crl_suffix: 'crl.pem'
# certificate authority (CA)
#
# root directory of the CA on the PKI host
crt_ca_root_dir: '/root/ca'
# name of the CA certificate (aka public key)
crt_ca_cert_name: 'ca.{{ crt_cert_suffix }}'
# name of the CA chain certificate (for intermediate CAs)
crt_ca_chain_cert_name: 'ca-chain.{{ crt_cert_suffix }}'
# name of the CA private key
crt_ca_priv_key_name: 'ca.{{ crt_priv_key_suffix }}'
# path of the CA's private keys directory
crt_ca_priv_key_dir_path: '{{ crt_ca_root_dir }}/private'
# path of the CA's certificates directory
crt_ca_cert_dir_path: '{{ crt_ca_root_dir }}/certs'
# path of the CA's CSR directory
crt_ca_csr_dir_path: '{{ crt_ca_root_dir }}/csr'
# path of the CA certificate
crt_ca_cert_path: '{{ crt_ca_cert_dir_path }}/{{ crt_ca_cert_name }}'
# path of the CA chain certificate (for intermediate CAs)
crt_ca_chain_cert_path: '{{ crt_ca_cert_dir_path }}/{{ crt_ca_chain_cert_name }}'
# path of the CA private key
crt_ca_priv_key_path: '{{ crt_ca_cert_dir_path }}/{{ crt_ca_priv_key_name }}'
# whether to fetch the CA certificate
crt_ca_fetch_ca_cert: true
# whether fo fetch the CA chain certificate (for intermediate CAs)
crt_ca_fetch_ca_chain_cert: true
# Certificate Signing Request (CSR)
#
# CSR email
crt_csr_email: 'steffen@example.com'
# CSR organization name (O)
crt_csr_org: 'Example Org'
# CSR organization unit name (OU)
crt_csr_org_unit: 'IT'
# CSR country name (C)
crt_csr_country: 'DE'
# CSR state name (S)
crt_csr_state: 'BW'
# CSR locality name (L)
crt_csr_loc: 'Home'
# CSR common name (usually the FQDN)
crt_csr_common_name: 'webserver.example.com'
# CSR key usage:
crt_csr_key_usage:
- 'digitalSignature'
- 'keyEncipherment'
- 'keyAgreement'
# CSR extended key usage
crt_csr_extended_key_usage:
- 'clientAuth'
- 'serverAuth'
#
# subjectAltName (SAN) should be considered critical
crt_csr_subject_alt_name_critical: true
# whether the common name should be used for the subjectAltName (SAN) if no specific SANs are provided
# as crt_csr_subject_alt_names is populated below, this setting does effectively nothing
crt_csr_use_common_name_for_san: true
# list of subjectAltNames (SANs) to use
crt_csr_subject_alt_names:
- 'DNS:host.example.com'
- 'DNS:alias.example.com'
- 'DNS:anotheralias.example.com'
- 'IP:127.0.0.1'
- 'IP:172.31.13.37'
- 'email:steffen@example.com'
- 'URI:https://host.example.com'
- 'otherName:1.3.6.1.4.1.311.20.2.3;UTF8:steffen@example.com'
- 'RID:1.3.3.7'
# Certificate Revocation List (CRL)
#
# whether to fetch the CRL certificate/s
crt_ca_fetch_ca_crl_cert: true
# whether to combine the CRLs into one CRL file (in case of multiple CRLs to fetch)
crt_combine_ca_crl_certs: true
# destination name of the combined CRL files
crt_crl_dest_name: 'ca-chain.{{ crt_crl_suffix }}'
# Private Key
#
# private key type to generate
crt_priv_key_type: 'RSA'
# private key length/size to generate
crt_priv_key_size: 4096
# whether to force private key regeneration
crt_force_priv_key_generation: false
# General
#
# path on the Ansible controller where to (temporarily) store fetched certificates
crt_local_dest_path: '/tmp/fetched'
# Permissions of the files inside crt_local_dest_path
crt_local_dest_path_owner: 'steffen'
crt_local_dest_path_group: 'steffen'
crt_local_dest_path_mode: '0400'
# whether to quiet assert
crt_quiet_assert: false
# SSH port of the PKI host
crt_pki_host_remote_port: 1905
# whether to remove locally stored temporary certificates (will break idempotency)
crt_remove_temporary_local_certificates: true
# path on the managed node where to store fetched certificates
# private key
crt_remote_private_key_path: '/root/certs/{{ inventory_hostname }}.key.pem'
crt_remote_private_key_owner: 'root'
crt_remote_private_key_group: 'root'
crt_remote_private_key_mode: '0600'
# private key directory
crt_remote_private_key_dir_owner: 'root'
crt_remote_private_key_dir_group: 'root'
crt_remote_private_key_dir_mode: '0600'
# public key
crt_remote_public_key_path: '/root/certs/{{ inventory_hostname }}.cert.pem'
crt_remote_public_key_owner: 'root'
crt_remote_public_key_group: 'root'
crt_remote_public_key_mode: '0600'
# private key directory
crt_remote_public_key_dir_owner: 'root'
crt_remote_public_key_dir_group: 'root'
crt_remote_public_key_dir_mode: '0600'
# certificate authority public key
crt_remote_ca_public_key_path: '/root/certs/ca.cert.pem'
crt_remote_ca_public_key_owner: 'root'
crt_remote_ca_public_key_group: 'root'
crt_remote_ca_public_key_mode: '0600'
# certificate authority public key directory
crt_remote_ca_public_key_dir_owner: 'root'
crt_remote_ca_public_key_dir_group: 'root'
crt_remote_ca_public_key_dir_mode: '0600'
# certificate authority CRL
crt_remote_ca_crl_path: '/root/certs/ca.crl.pem'
crt_remote_ca_crl_owner: 'root'
crt_remote_ca_crl_group: 'root'
crt_remote_ca_crl_mode: '0600'
# certificate authority CRL directory
crt_remote_ca_crl_dir_owner: 'root'
crt_remote_ca_crl_dir_group: 'root'
crt_remote_ca_crl_dir_mode: '0600'
# CA CRL certificates to download
crt_ca_crl_certs:
- '/root/ca/crl/ca.crl.pem'
- '/root/ca/intermediate/intermediate.example.com/crl/intermediate.crl.pem'
...