Skip to content

Commit 016280d

Browse files
k-s-deanmnasiadka
andauthored
Adds the ability to write certs as a pem bundle or individual files (#36)
* Adds the ability to write out certs and keys as either a pem bundle or individually Co-authored-by: Michal Nasiadka <[email protected]>
1 parent 33e6c28 commit 016280d

File tree

7 files changed

+169
-33
lines changed

7 files changed

+169
-33
lines changed

roles/vault_pki/README.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,29 +21,32 @@ Role variables
2121
* Mandatory if `vault_pki_root_create` equals `true`
2222
* `vault_pki_root_ca_name`: The name of the RootCA to create (string)
2323
* `vault_pki_root_ca_common_name`: The common name of the RootCA (default: vault_pki_root_ca_name)
24-
* `vault_pki_write_root_ca_to_file`: whether to write the root CA certificate to a file for importing into a systems trust store (default: `false`)
2524
* `vault_pki_root_default_lease_ttl`: The default time in hours before expiry of the root CA certificate (default: "43830h")
2625
* `vault_pki_root_max_lease_ttl`: The max time in hours that is allowed before expiry of the root CA certificate (default: "43830h")
2726
* `vault_pki_root_ttl`: The time in hours before the root CA certificate expires (default: "43830h")
2827
* `vault_pki_root_key_bits`: The key bits for the root RSA private key (default: 4096)
28+
* `vault_pki_write_root_ca_to_file`: whether to write the root CA certificate to a file for importing into a systems trust store (default: `false`)
2929
---
3030
* Vault Create Intermediate
3131
* `vault_pki_intermediate_create`: whether to create an intermediate CA or not (default: `true`)
32+
* `vault_pki_intermediate_default_lease_ttl`: The default time in hours before expiry of the intermediate CA certificate (default: "43830h")
3233
* `vault_pki_intermediate_import`: whether to import a pre-existing intermediate pem bundle (default: `false`)
3334
* `vault_pki_intermediate_export`: whether to export the generated intermediate pem bundle (default: `false`)
3435
* Mandatory if `vault_pki_intermediate_create` equals `true`
3536
* `vault_pki_intermediate_ca_name`: The name of the Intermediate CA to create
3637
* `vault_pki_intermediate_ca_common_name`: The common name of the Intermediate CA (default: `vault_pki_intermediate_ca_name`)
3738
* Mandatory if `vault_pki_intermediate_import`: equals `true`
3839
* `vault_pki_intermediate_ca_bundle`: Concatenated certificate, intermediate and private key
39-
* `vault_pki_intermediate_default_lease_ttl`: The default time in hours before expiry of the intermediate CA certificate (default: "43830h")
40-
* `vault_pki_intermediate_max_lease_ttl`: The max time in hours that is allowed before expiry of the intermediate CA certificate (default: "43830h")
41-
* `vault_pki_intermediate_ttl`: The time in hours before the intermediate CA certificate expires (default: "43830h")
4240
* `vault_pki_intermediate_key_bits`: The key bits for the intermediate RSA private key (default: 4096)
41+
* `vault_pki_intermediate_max_lease_ttl`: The max time in hours that is allowed before expiry of the intermediate CA certificate (default: "43830h")
4342
* `vault_pki_intermediate_roles`: Certificate Roles to create for the intermediate CA. List of Dicts containing `{name: <role_name>, config: { <pki_option>: <value> ...}`
43+
* `vault_pki_intermediate_ttl`: The time in hours before the intermediate CA certificate expires (default: "43830h")
44+
* `vault_pki_write_int_ca_to_file`: Whether to write out the intermediate CA to file (default: `false`)
4445
---
4546
* Certificate Output
47+
* `vault_pki_certificate_subject`: The certificate subject parameters e.g. `ttl` `ip_sans`. List of Dicts containing `{role: <name of Certificate role>, common_name: <common name of certificate>, extra_params: {ttl: <value>, alt_sans: <value>, ip_sans: <value> }}`
48+
* `vault_pki_certificates_directory`: directory to output certificate files to.
4649
* `vault_pki_generate_certificates`: whether to generate leaf certificates or not (default: `false`)
50+
* `vault_pki_overwrite_certificates`: whether to overwrite certificates (default: `false`)
4751
* `vault_pki_write_certificates_host:` The host on which certificates will be written to. (default: "localhost")
48-
* `vault_pki_certificates_directory`: directory to output certificate files to.
49-
* `vault_pki_certificate_subject`: The certificate subject parameters e.g. `ttl` `ip_sans`. List of Dicts containing `{role: <name of Certificate role>, common_name: <common name of certificate>, extra_params: {ttl: <value>, alt_sans: <value>, ip_sans: <value> }}`
52+
* `vault_pki_write_pem_bundle`: output the generated certificate and private key into a single file (default: `true`)

roles/vault_pki/defaults/main.yml

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,40 @@
11
---
2-
vault_pki_root_create: true
2+
# Allow vault_vip_url and vault_vip_address for backwards compatibility.
3+
vault_api_addr: "{{ vault_protocol ~ '://' ~ vault_vip_address ~ ':8200' }}"
4+
vault_bind_address: "127.0.0.1"
5+
vault_protocol: "https"
6+
vault_vip_address: "{{ vault_vip_url | default(vault_bind_address) }}"
7+
8+
vault_pki_certificates_directory: ""
9+
310
vault_pki_root_ca_name: ""
411
vault_pki_root_ca_common_name: "{{ vault_pki_root_ca_name }}"
5-
vault_pki_write_root_ca_to_file: false
12+
vault_pki_root_create: true
613
vault_pki_root_default_lease_ttl: "43830h"
14+
vault_pki_root_key_bits: 4096
715
vault_pki_root_max_lease_ttl: "43830h"
816
vault_pki_root_ttl: "43830h"
9-
vault_pki_root_key_bits: 4096
10-
17+
vault_pki_write_root_ca_to_file: false
1118

12-
vault_pki_intermediate_create: true
13-
vault_pki_intermediate_import: false
14-
vault_pki_intermediate_export: false
1519
vault_pki_intermediate_ca_name: ""
1620
vault_pki_intermediate_ca_common_name: "{{ vault_pki_intermediate_ca_name }}"
1721
vault_pki_intermediate_ca_bundle: ""
22+
vault_pki_intermediate_create: true
1823
vault_pki_intermediate_default_lease_ttl: "43830h"
24+
vault_pki_intermediate_import: false
25+
vault_pki_intermediate_export: false
26+
vault_pki_intermediate_key_bits: 4096
1927
vault_pki_intermediate_max_lease_ttl: "43830h"
2028
vault_pki_intermediate_ttl: "43830h"
21-
vault_pki_intermediate_key_bits: 4096
29+
vault_pki_write_int_ca_to_file: false
2230

2331
vault_pki_intermediate_roles: {}
2432

2533
vault_pki_generate_certificates: false
34+
vault_pki_write_pem_bundle: true
2635

36+
vault_pki_overwrite_certificates: false
2737
vault_pki_write_certificates_host: "localhost"
28-
vault_pki_write_certificates_directory: ""
2938
vault_pki_write_certificate_files: false
3039

3140
vault_pki_certificate_subject: []
Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
11
---
2+
- name: "Check if Cert already exists in certificates directory"
3+
stat:
4+
path: "{{ vault_pki_certificates_directory }}/{{ item.common_name | replace(' ', '-') }}.crt"
5+
register: cert_stat_file
6+
delegate_to: "{{ vault_pki_write_certificates_host }}"
7+
loop: "{{ vault_pki_certificate_subject }}"
8+
loop_control:
9+
label: "{{ item.common_name }}"
10+
when: vault_pki_write_certificate_files | bool
11+
212
- name: "Generate Certificate"
313
hashivault_pki_cert_issue:
414
url: "{{ vault_api_addr }}"
@@ -9,11 +19,14 @@
919
role: "{{ item.role }}"
1020
extra_params: "{{ item.extra_params }}"
1121
loop: "{{ vault_pki_certificate_subject }}"
12-
register: certificate_data
22+
loop_control:
23+
label: "{{ item.common_name }}"
24+
register: cert_data
1325

1426
- name: "Write out certificate pem_bundle"
1527
vars:
16-
cert_name: "{{ item.item.common_name if item.item.common_name | length > 0 else item.item.extra_params.ip_sans }}"
28+
cert_name: "{{ item.item.common_name if item.item.common_name | default() | length > 0 else item.item.extra_params.ip_sans | default() }}"
29+
cert_file: "{{ cert_stat_file.results | selectattr('item.common_name', 'match', item.item.common_name) | first }}"
1730
copy:
1831
content: |
1932
{{ item.data.certificate }}
@@ -22,5 +35,47 @@
2235
dest: "{{ vault_pki_certificates_directory }}/{{ cert_name | replace(' ', '-') }}.pem"
2336
mode: 0600
2437
delegate_to: "{{ vault_pki_write_certificates_host }}"
25-
loop: "{{ certificate_data.results }}"
26-
when: vault_pki_write_certificate_files | bool
38+
loop: "{{ cert_data.results }}"
39+
loop_control:
40+
label: "{{ cert_name | default() }}"
41+
when:
42+
- vault_pki_write_pem_bundle | bool
43+
- vault_pki_write_certificate_files | bool
44+
- not cert_file.stat.exists or vault_pki_overwrite_certificates | bool
45+
46+
- name: "Write out certificate"
47+
vars:
48+
cert_name: "{{ item.item.common_name if item.item.common_name | default() | length > 0 else item.item.extra_params.ip_sans | default() }}"
49+
cert_file: "{{ cert_stat_file.results | selectattr('item.common_name', 'match', item.item.common_name) | first }}"
50+
copy:
51+
content: |
52+
{{ item.data.certificate }}
53+
{{ item.data.issuing_ca }}
54+
dest: "{{ vault_pki_certificates_directory }}/{{ cert_name | replace(' ', '-') }}.crt"
55+
mode: 0600
56+
delegate_to: "{{ vault_pki_write_certificates_host }}"
57+
loop: "{{ cert_data.results }}"
58+
loop_control:
59+
label: "{{ cert_name | default() }}"
60+
when:
61+
- not vault_pki_write_pem_bundle | bool
62+
- vault_pki_write_certificate_files | bool
63+
- not cert_file.stat.exists or vault_pki_overwrite_certificates | bool
64+
65+
- name: "Write out key"
66+
vars:
67+
cert_name: "{{ item.item.common_name if item.item.common_name | default() | length > 0 else item.item.extra_params.ip_sans | default() }}"
68+
cert_file: "{{ cert_stat_file.results | selectattr('item.common_name', 'match', item.item.common_name) | first }}"
69+
copy:
70+
content: |
71+
{{ item.data.private_key }}
72+
dest: "{{ vault_pki_certificates_directory }}/{{ cert_name | replace(' ', '-') }}.key"
73+
mode: 0600
74+
delegate_to: "{{ vault_pki_write_certificates_host }}"
75+
loop: "{{ cert_data.results }}"
76+
loop_control:
77+
label: "{{ cert_name | default() }}"
78+
when:
79+
- not vault_pki_write_pem_bundle | bool
80+
- vault_pki_write_certificate_files | bool
81+
- not cert_file.stat.exists or vault_pki_overwrite_certificates | bool

roles/vault_pki/tasks/intermediate.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737
common_name: "{{ vault_pki_intermediate_ca_common_name }}"
3838
type: intermediate
3939
register: intermediate_ca_csr_signed
40+
when:
41+
- intermediate_ca_csr.changed
42+
- intermediate_ca_csr.data is defined
4043

4144
- name: "Set Intermediate as signed"
4245
hashivault_pki_set_signed:
@@ -62,6 +65,18 @@
6265
{{ intermediate_ca_csr.data.private_key }}
6366
when:
6467
- vault_pki_intermediate_export | bool
68+
- intermediate_ca_csr.changed
69+
- intermediate_ca_csr.data is defined
70+
71+
- name: "Write out Intermediate CA to file"
72+
copy:
73+
content: |
74+
{{ intermediate_ca_csr_signed.data.certificate }}
75+
dest: "{{ vault_pki_certificates_directory }}/{{ vault_pki_intermediate_ca_name | replace(' ', '-') }}.pem"
76+
mode: 0600
77+
delegate_to: "{{ vault_pki_write_certificates_host }}"
78+
when:
79+
- vault_pki_write_int_ca_to_file | bool
6580

6681
- name: "Write out Intermediate Certs and keys to file"
6782
copy:
@@ -74,6 +89,9 @@
7489
delegate_to: "{{ vault_pki_write_certificates_host }}"
7590
when:
7691
- vault_pki_intermediate_export | bool
92+
- intermediate_ca_csr.changed
93+
- intermediate_ca_csr.data is defined
94+
- intermediate_ca_csr_signed.data is defined
7795

7896
when: not vault_pki_intermediate_import | bool
7997

roles/vault_pki/tasks/prechecks.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
fail:
44
msg: "variable {{ item.name }} is not set"
55
when:
6+
- vars[item.name] is defined
67
- vars[item.name] | length == 0
78
- item.when
89
loop:

roles/vault_pki/tasks/root.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,5 @@
3333
mode: 0600
3434
delegate_to: "{{ vault_pki_write_certificates_host }}"
3535
when:
36+
- root_ca_data.data.certificate is defined
3637
- vault_pki_write_root_ca_to_file | bool

tests/test_vault.yml

Lines changed: 63 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
vars:
66
vault_config_dir: "/etc/vault"
77
vault_log_keys: true
8+
vault_protocol: http
89
vault_set_keys_fact: true
910
vault_write_keys_file: true
1011
tasks:
@@ -22,20 +23,27 @@
2223
name: vault
2324

2425
- name: Unseal vault
25-
import_role:
26+
include_role:
2627
name: vault_unseal
2728
vars:
2829
vault_unseal_keys: "{{ vault_keys.keys_base64 }}"
29-
vault_protocol: "http"
3030

31-
- name: Configure PKI
32-
import_role:
31+
- name: Configure PKI - create root/intermediate and generate certificates
32+
include_role:
3333
name: vault_pki
3434
vars:
35-
vault_token: "{{ vault_keys.root_token }}"
36-
vault_pki_root_ca_name: "OS-TLS-ROOT"
35+
vault_pki_certificate_subject:
36+
- role: 'ServerCert'
37+
common_name: "OS-CERT-TEST"
38+
extra_params:
39+
ttl: "8760h"
40+
ip_sans: "127.0.0.1"
41+
alt_names: "example.com"
42+
exclude_cn_from_sans: true
43+
vault_pki_certificates_directory: "/tmp/"
44+
vault_pki_generate_certificates: true
3745
vault_pki_intermediate_ca_name: "OS-TLS-INT"
38-
vault_pki_generate_certificates: True
46+
vault_pki_intermediate_create: true
3947
vault_pki_intermediate_roles:
4048
- name: "ServerCert"
4149
config:
@@ -51,17 +59,58 @@
5159
locality: ["Bristol"]
5260
organization: ["StackHPC"]
5361
ou: ["HPC"]
62+
vault_pki_root_ca_name: "OS-TLS-ROOT"
63+
vault_pki_root_create: true
64+
vault_pki_write_certificate_files: true
65+
vault_pki_write_int_ca_to_file: true
66+
vault_pki_write_pem_bundle: false
67+
vault_pki_write_root_ca_to_file: true
68+
vault_token: "{{ vault_keys.root_token }}"
69+
70+
- name: Configure PKI - generate certificate pem bundle
71+
include_role:
72+
name: vault_pki
73+
vars:
5474
vault_pki_certificate_subject:
55-
- role: 'ServerCert'
56-
common_name: "OS-CERT-TEST"
57-
extra_params:
58-
ttl: "8760h"
59-
ip_sans: "127.0.0.1"
60-
alt_names: "example.com"
61-
exclude_cn_from_sans: true
6275
- role: 'ServerCert'
6376
common_name: "OS-CERT-TEST2"
6477
extra_params:
6578
ttl: "8760h"
6679
ip_sans: "192.168.38.72"
6780
exclude_cn_from_sans: true
81+
vault_pki_certificates_directory: "/tmp/"
82+
vault_pki_generate_certificates: true
83+
vault_pki_intermediate_ca_name: "OS-TLS-INT"
84+
vault_pki_intermediate_create: false
85+
vault_pki_root_ca_name: "OS-TLS-ROOT"
86+
vault_pki_root_create: false
87+
vault_pki_write_certificate_files: true
88+
vault_pki_write_pem_bundle: true
89+
vault_token: "{{ vault_keys.root_token }}"
90+
91+
- name: Validate if certificates exist
92+
stat:
93+
path: "/tmp/{{ item }}"
94+
register: stat_result
95+
failed_when: not stat_result.stat.exists
96+
loop:
97+
- OS-CERT-TEST.crt
98+
- OS-CERT-TEST2.pem
99+
100+
- name: concatenate CAs
101+
shell: |
102+
cat /tmp/OS-TLS-ROOT.pem /tmp/OS-TLS-INT.pem > /tmp/CA-CHAIN.pem
103+
args:
104+
executable: /bin/bash
105+
become: true
106+
107+
- name: verify certificate chain
108+
command: |
109+
openssl verify -CAfile /tmp/CA-CHAIN.pem
110+
/tmp/{{ item }}
111+
register: verify_result
112+
failed_when: verify_result.rc != 0
113+
loop:
114+
- OS-CERT-TEST.crt
115+
- OS-CERT-TEST2.pem
116+

0 commit comments

Comments
 (0)