Files
ansible-role-certificate-au…/tasks/client_certificate.yaml
T
volker.raschekandCopilot 95ea71394e fix: make issued certificates readable for unprivileged consumers
The pki directories were created with mode 0700, so cert.pem, chain.pem and fullchain.pem stayed
unreachable for every non root process although they are declared as 0644. That defeats the main purpose of
the role, which is handing a certificate to a service such as nginx or postgres.

The directories are opened up to 0755. To keep that safe, the mode of the private keys is now pinned
explicitly to 0600 instead of relying on the default of community.crypto.openssl_privatekey.

Co-authored-by: Copilot <copilot@github.com>
2026-09-07 22:30:23 +02:00

127 lines
5.0 KiB
YAML

---
- 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.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_protected.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: false
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"
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: false
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"
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: false
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"
when: _stat_result.stat.exists is defined and
_stat_result.stat.exists