Setup a Step Client (Machine / Server)
This guide will demonstrate how to setup servers to request x509 certificates from the CA.
A complete playbook file is available at clients-server.yml (link) with example group_vars (link).
The
step_ca_cert
andstep_cert
roles will do the following:Download the CA root certificate and add it to the system’s CA trust store.
Request an x509 certificate from the CA using an ACME provisioner (default) - configure using the
step_cert_list.provisioner
variable.The certificate will automatically renew via a systemd timer,
cert-renewer@[step_cert_list.name].timer
.The systemd renewal timer will attempt to restart the service that matches the
step_cert_list.name
; thus, it is important to name the certificate after the service, e.g. setstep_cert_list.name: docker
for thedocker.service
. You can disable this behavior globally by settingstep_cert_renewal_restart_svc: false
.
This guide assumes a CA is already configured with a ACME provisioner using: Setup a Step CA Server (Non-Production).
Single Certificate
This approach works well for a group of servers in which you only need a single certificate matching the FQDN of the server.
Playbook
- name: Extract Root CA Information
hosts: ca-server
become: true
gather_facts: true
tasks:
- name: Get Root CA Fingerprint
ansible.builtin.command: step certificate fingerprint /etc/step-ca/certs/root_ca.crt
register: ca_fingerprint
changed_when: false
failed_when: ca_fingerprint.rc == 1
- name: Setup Step CA Clients (Servers)
hosts: ca_clients
become: true
gather_facts: true
roles:
- name: Install Step CLI
role: trfore.smallstep.step_cli
- name: Add Step CA Root Certificate to Trust Store
role: trfore.smallstep.step_ca_cert
vars:
step_ca_fingerprint: "{{ hostvars['ca-server'].ca_fingerprint.stdout }}"
step_ca_url: "https://ca.example.com"
- name: Request x509 Certificate
role: trfore.smallstep.step_cert
Multiple Certificates
This approach works well for a single server hosting multiple services.
Playbook
- name: Extract Root CA Information
hosts: ca-server
become: true
gather_facts: true
tasks:
- name: Get Root CA Fingerprint
ansible.builtin.command: step certificate fingerprint /etc/step-ca/certs/root_ca.crt
register: ca_fingerprint
changed_when: false
failed_when: ca_fingerprint.rc == 1
- name: Setup Step CA Clients (Servers)
hosts: host01
become: true
gather_facts: true
roles:
- name: Install Step CLI
role: trfore.smallstep.step_cli
- name: Add Step CA Root Certificate to Trust Store
role: trfore.smallstep.step_ca_cert
vars:
step_ca_fingerprint: "{{ hostvars['ca-server'].ca_fingerprint.stdout }}"
step_ca_url: "https://ca.example.com"
- name: Request x509 Certificate
role: trfore.smallstep.step_cert
vars:
step_cert_list:
- name: "{{ ansible_fqdn }}"
subject: "{{ ansible_fqdn }}"
path: /etc/step/certs/
san_0: "{{ ansible_default_ipv4.address }}" # Add IP address to certificate
provisioner: "acme"
- name: "docker" # Name matches service name
subject: "docker.example.com"
path: /etc/pki/docker.example.com/
provisioner: "acme"
Directory Layout
The following files will be created:
$ tree /etc/step
/etc/step/
`-- certs
|-- host01.example.com.crt
`-- host01.example.com.key
$ tree /etc/pki
/etc/pki
`-- docker.example.com
|-- docker.crt
`-- docker.key
The following timers will be created:
$ systemctl list-timers
NEXT LEFT LAST PASSED UNIT ACTIVATES
Fri XXXX-XX-XX 17:46:10 UTC 1min 18s left n/a n/a cert-renewer@docker.timer cert-renewer@docker.service
Fri XXXX-XX-XX 17:48:04 UTC 3min 12s left n/a n/a cert-renewer@host01.example.com.timer cert-renewer@host01.example.com.service