Skip to content

Commit 3d3962d

Browse files
authored
Merge pull request #1781 from stackhpc/caracal-ca-choice
Backport: Merge Openbao and Hashicorp Vault playbooks
2 parents 8ceac76 + 00db32c commit 3d3962d

13 files changed

+671
-2
lines changed
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
---
2+
- name: Configure AppRole
3+
any_errors_fatal: true
4+
gather_facts: true
5+
hosts: controllers[0]
6+
vars:
7+
secret_store_api_address: https://{{ internal_net_name | net_ip }}:8200
8+
secret_store_ca_cert: "{{ '/etc/pki/tls/certs/ca-bundle.crt' if ansible_facts.os_family == 'RedHat' else '/usr/local/share/ca-certificates/OS-TLS-ROOT.crt' }}"
9+
tasks:
10+
- name: Assert that secrets_barbican_approle_secret_id is defined
11+
ansible.builtin.assert:
12+
that:
13+
- secrets_barbican_approle_secret_id is defined
14+
fail_msg: Please define secrets_barbican_approle_secret_id in your secrets.yml
15+
16+
- name: Include secret store keys
17+
ansible.builtin.include_vars:
18+
file: "{{ kayobe_env_config_path }}/{{ stackhpc_ca_secret_store }}/overcloud-{{ stackhpc_ca_secret_store }}-keys.json"
19+
name: secret_store_keys
20+
21+
- name: Ensure hvac is installed
22+
ansible.builtin.pip:
23+
name: hvac
24+
state: present
25+
extra_args: "{% if pip_upper_constraints_file %}-c {{ pip_upper_constraints_file }}{% endif %}"
26+
virtualenv: "{{ virtualenv_path }}/kayobe"
27+
28+
- name: Ensure AppRole is configured
29+
environment:
30+
https_proxy: ""
31+
block:
32+
- name: Enable AppRole auth module
33+
hashivault_auth_method: # noqa: fqcn
34+
url: "{{ secret_store_api_address }}"
35+
ca_cert: "{{ secret_store_ca_cert }}"
36+
token: "{{ secret_store_keys.root_token }}"
37+
method_type: approle
38+
state: enabled
39+
40+
- name: Enable barbican kv store
41+
hashivault_secret_engine: # noqa: fqcn
42+
url: "{{ secret_store_api_address }}"
43+
ca_cert: "{{ secret_store_ca_cert }}"
44+
token: "{{ secret_store_keys.root_token }}"
45+
name: barbican
46+
backend: kv
47+
description: Barbican kv store
48+
49+
- name: Ensure barbican policy is defined
50+
hashivault_policy: # noqa: fqcn
51+
url: "{{ secret_store_api_address }}"
52+
ca_cert: "{{ secret_store_ca_cert }}"
53+
token: "{{ secret_store_keys.root_token }}"
54+
name: barbican-policy
55+
state: present
56+
rules: |
57+
path "barbican/*" {
58+
capabilities = ["create", "read", "update", "delete", "list"]
59+
}
60+
61+
- name: Ensure barbican AppRole is defined
62+
hashivault_approle_role: # noqa: fqcn
63+
url: "{{ secret_store_api_address }}"
64+
ca_cert: "{{ secret_store_ca_cert }}"
65+
token: "{{ secret_store_keys.root_token }}"
66+
bind_secret_id: true
67+
secret_id_bound_cidrs: "{{ internal_net_name | net_cidr }}"
68+
secret_id_ttl: 0
69+
token_policies: barbican-policy
70+
name: barbican
71+
72+
- name: Get barbican Approle ID
73+
hashivault_approle_role_id: # noqa: fqcn
74+
url: "{{ secret_store_api_address }}"
75+
ca_cert: "{{ secret_store_ca_cert }}"
76+
token: "{{ secret_store_keys.root_token }}"
77+
name: barbican
78+
register: barbican_role_id
79+
80+
- name: Print barbican Approle ID
81+
ansible.builtin.debug:
82+
msg: barbican role id is {{ barbican_role_id.id }}
83+
84+
- name: Write barbican Approle ID to file if requested
85+
delegate_to: localhost
86+
ansible.builtin.copy:
87+
content: "{{ barbican_role_id.id }}"
88+
dest: "{{ stackhpc_barbican_role_id_file_path | default('~/barbican-role-id') }}"
89+
when: stackhpc_write_barbican_role_id_to_file | default(false) | bool
90+
91+
- name: Check if barbican Approle Secret ID is defined
92+
hashivault_approle_role_secret_get: # noqa: fqcn
93+
url: "{{ secret_store_api_address }}"
94+
ca_cert: "{{ secret_store_ca_cert }}"
95+
token: "{{ secret_store_keys.root_token }}"
96+
secret: "{{ secrets_barbican_approle_secret_id }}"
97+
name: barbican
98+
register: barbican_approle_secret_get
99+
100+
- name: Ensure barbican AppRole Secret ID is defined
101+
hashivault_approle_role_secret: # noqa: fqcn
102+
url: "{{ secret_store_api_address }}"
103+
ca_cert: "{{ secret_store_ca_cert }}"
104+
token: "{{ secret_store_keys.root_token }}"
105+
secret: "{{ secrets_barbican_approle_secret_id }}"
106+
name: barbican
107+
when: barbican_approle_secret_get.status == "absent"
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
---
2+
# Required for uri module to work with self-signed certificates and for systems to trust
3+
# the self-signed CA
4+
- name: Install CA on controllers
5+
hosts: controllers
6+
tasks:
7+
- name: Copy the intermediate CA
8+
ansible.builtin.copy:
9+
src: "{{ kayobe_env_config_path }}/{{ stackhpc_ca_secret_store }}/OS-TLS-ROOT.pem"
10+
dest: "{{ '/etc/pki/ca-trust/source/anchors/OS-TLS-ROOT.crt' if ansible_facts.os_family == 'RedHat' else '/usr/local/share/ca-certificates/OS-TLS-ROOT.crt'
11+
}}"
12+
mode: "0644"
13+
become: true
14+
15+
- name: Update system CA
16+
become: true
17+
ansible.builtin.command: "{{ 'update-ca-trust' if ansible_facts.os_family == 'RedHat' else 'update-ca-certificates' }}"
18+
19+
- name: Deploy Secret store on the overcloud
20+
any_errors_fatal: true
21+
gather_facts: true
22+
hosts: controllers
23+
vars:
24+
secret_store_bind_interface: "{{ internal_net_name | net_interface }}"
25+
secret_store_bind_address: "{{ internal_net_name | net_ip }}"
26+
# This is the IP address of the first controller and therefore the leader within
27+
# OpenBao. This could be replaced with the VIP address of the internal network if
28+
# HAProxy has been configured to load balance the OpenBao API.
29+
openbao_raft_leaders:
30+
- "{{ internal_net_name | net_ip(inventory_hostname=groups['controllers'][0]) }}"
31+
tasks:
32+
- name: Set a fact about the virtualenv on the remote system
33+
ansible.builtin.set_fact:
34+
virtualenv: "{{ ansible_python_interpreter | dirname | dirname }}"
35+
when:
36+
- ansible_python_interpreter is defined
37+
- not ansible_python_interpreter.startswith('/bin/')
38+
- not ansible_python_interpreter.startswith('/usr/bin/')
39+
40+
- name: Ensure Python hvac module is installed
41+
ansible.builtin.pip:
42+
name: hvac
43+
state: latest
44+
extra_args: "{% if pip_upper_constraints_file %}-c {{ pip_upper_constraints_file }}{% endif %}"
45+
virtualenv: "{{ virtualenv is defined | ternary(virtualenv, omit) }}"
46+
become: "{{ virtualenv is not defined }}"
47+
48+
- name: Ensure /opt/kayobe/{{ stackhpc_ca_secret_store }} exists
49+
ansible.builtin.file:
50+
path: /opt/kayobe/{{ stackhpc_ca_secret_store }}
51+
state: directory
52+
53+
- name: Template out TLS key and cert
54+
ansible.builtin.copy:
55+
# Within the OpenBao container these uids & gids map to the openbao user
56+
src: "{{ kayobe_env_config_path }}/{{ stackhpc_ca_secret_store }}/{{ item }}"
57+
dest: /opt/kayobe/{{ stackhpc_ca_secret_store }}/{{ item }}
58+
owner: 100
59+
group: 1000
60+
mode: "0600"
61+
loop:
62+
- "{% if kolla_internal_fqdn != kolla_internal_vip_address %}{{ kolla_internal_fqdn }}{% else %}overcloud{% endif %}.crt"
63+
- "{% if kolla_internal_fqdn != kolla_internal_vip_address %}{{ kolla_internal_fqdn }}{% else %}overcloud{% endif %}.key"
64+
- "OS-TLS-INT.crt"
65+
become: true
66+
67+
- name: Apply vault role
68+
ansible.builtin.import_role:
69+
name: stackhpc.hashicorp.vault
70+
vars:
71+
hashicorp_registry_url: "{{ overcloud_hashicorp_registry_url }}"
72+
hashicorp_registry_username: "{{ overcloud_hashicorp_registry_username }}"
73+
hashicorp_registry_password: "{{ overcloud_hashicorp_registry_password }}"
74+
consul_docker_image: "{{ overcloud_consul_docker_image }}"
75+
consul_docker_tag: "{{ overcloud_consul_docker_tag }}"
76+
consul_bind_interface: "{{ secret_store_bind_interface }}"
77+
vault_bind_address: "{{ secret_store_bind_address }}"
78+
vault_config_dir: /opt/kayobe/vault
79+
vault_cluster_name: overcloud
80+
vault_ca_cert: "{{ '/etc/pki/tls/certs/ca-bundle.crt' if ansible_facts.os_family == 'RedHat' else '/usr/local/share/ca-certificates/OS-TLS-ROOT.crt' }}"
81+
vault_docker_image: "{{ overcloud_vault_docker_image }}"
82+
vault_docker_tag: "{{ overcloud_vault_docker_tag }}"
83+
vault_tls_cert: "{% if kolla_internal_fqdn != kolla_internal_vip_address %}{{ kolla_internal_fqdn }}{% else %}overcloud{% endif %}.crt"
84+
vault_tls_key: "{% if kolla_internal_fqdn != kolla_internal_vip_address %}{{ kolla_internal_fqdn }}{% else %}overcloud{% endif %}.key"
85+
copy_self_signed_ca: true
86+
vault_api_addr: https://{{ internal_net_name | net_ip }}:8200
87+
vault_write_keys_file: true
88+
vault_write_keys_file_path: "{{ kayobe_env_config_path }}/vault/overcloud-vault-keys.json"
89+
when: stackhpc_ca_secret_store == "vault"
90+
91+
- name: Apply OpenBao role
92+
ansible.builtin.import_role:
93+
name: stackhpc.hashicorp.openbao
94+
vars:
95+
openbao_bind_addr: "{{ secret_store_bind_address }}"
96+
openbao_registry_url: "{{ overcloud_openbao_registry_url }}"
97+
openbao_registry_username: "{{ overcloud_openbao_registry_username }}"
98+
openbao_registry_password: "{{ overcloud_openbao_registry_password }}"
99+
openbao_config_dir: /opt/kayobe/openbao
100+
openbao_cluster_name: overcloud
101+
openbao_ca_cert: "{{ '/etc/pki/tls/certs/ca-bundle.crt' if ansible_facts.os_family == 'RedHat' else '/usr/local/share/ca-certificates/OS-TLS-ROOT.crt' }}"
102+
openbao_docker_image: "{{ overcloud_openbao_docker_image }}"
103+
openbao_docker_tag: "{{ overcloud_openbao_docker_tag }}"
104+
openbao_tls_cert: "{% if kolla_internal_fqdn != kolla_internal_vip_address %}{{ kolla_internal_fqdn }}{% else %}overcloud{% endif %}.crt"
105+
openbao_tls_key: "{% if kolla_internal_fqdn != kolla_internal_vip_address %}{{ kolla_internal_fqdn }}{% else %}overcloud{% endif %}.key"
106+
openbao_tls_ca: "OS-TLS-INT.crt"
107+
copy_self_signed_ca: true
108+
openbao_api_addr: https://{{ internal_net_name | net_ip }}:8200
109+
openbao_write_keys_file: true
110+
openbao_write_keys_file_path: "{{ kayobe_env_config_path }}/openbao/overcloud-openbao-keys.json"
111+
when: stackhpc_ca_secret_store == "openbao"
112+
113+
- name: Include secret store keys
114+
ansible.builtin.include_vars:
115+
file: "{{ kayobe_env_config_path }}/{{ stackhpc_ca_secret_store }}/overcloud-{{ stackhpc_ca_secret_store }}-keys.json"
116+
name: secret_store_keys
117+
118+
- name: Unseal first secret store instance
119+
ansible.builtin.import_role:
120+
name: stackhpc.hashicorp.vault_unseal
121+
vars:
122+
vault_api_addr: https://{{ internal_net_name | net_ip }}:8200
123+
vault_unseal_token: "{{ secret_store_keys.root_token }}"
124+
vault_unseal_ca_cert: "{{ '/etc/pki/tls/certs/ca-bundle.crt' if ansible_facts.os_family == 'RedHat' else '/usr/local/share/ca-certificates/OS-TLS-ROOT.crt' }}"
125+
vault_unseal_keys: "{{ secret_store_keys.keys_base64 }}"
126+
environment:
127+
https_proxy: ""
128+
run_once: true
129+
130+
# As the first instance is now unsealed the other instances will now need some
131+
# time to connect before we can proceed.
132+
- name: Wait for OpenBao Raft peers to connect
133+
ansible.builtin.wait_for:
134+
timeout: 30
135+
delegate_to: localhost
136+
137+
# Raft peers take few seconds before they report an unsealed state therefore
138+
# we must wait.
139+
- name: Unseal all secret store instances
140+
ansible.builtin.import_role:
141+
name: stackhpc.hashicorp.vault_unseal
142+
vars:
143+
vault_api_addr: https://{{ internal_net_name | net_ip }}:8200
144+
vault_unseal_token: "{{ secret_store_keys.root_token }}"
145+
vault_unseal_ca_cert: "{{ '/etc/pki/tls/certs/ca-bundle.crt' if ansible_facts.os_family == 'RedHat' else '/usr/local/share/ca-certificates/OS-TLS-ROOT.crt' }}"
146+
vault_unseal_keys: "{{ secret_store_keys.keys_base64 }}"
147+
vault_unseal_timeout: 10
148+
environment:
149+
https_proxy: ""
150+
151+
- name: Configure PKI
152+
any_errors_fatal: true
153+
gather_facts: true
154+
hosts: controllers[0]
155+
tasks:
156+
- name: Apply pki role
157+
ansible.builtin.import_role:
158+
name: stackhpc.hashicorp.vault_pki
159+
vars:
160+
vault_token: "{{ secret_store_keys.root_token }}"
161+
vault_api_addr: https://{{ internal_net_name | net_ip }}:8200
162+
vault_ca_cert: "{{ '/etc/pki/tls/certs/ca-bundle.crt' if ansible_facts.os_family == 'RedHat' else '/usr/local/share/ca-certificates/OS-TLS-ROOT.crt' }}"
163+
vault_pki_root_create: false
164+
vault_pki_intermediate_import: true
165+
vault_pki_intermediate_ca_name: OS-TLS-INT
166+
vault_pki_intermediate_ca_bundle: "{{ lookup('file', kayobe_env_config_path + '/' + stackhpc_ca_secret_store + '/OS-TLS-INT.pem') }}"
167+
vault_pki_intermediate_ca_cert: "{{ lookup('file', kayobe_env_config_path + '/' + stackhpc_ca_secret_store + '/OS-TLS-INT.crt') }}"
168+
vault_pki_intermediate_roles: "{{ overcloud_vault_pki_roles if stackhpc_ca_secret_store == 'vault' else overcloud_openbao_pki_roles }}"
169+
vault_pki_write_certificate_files: true
170+
vault_pki_certificates_directory: "{{ kayobe_env_config_path }}/{{ stackhpc_ca_secret_store }}"
171+
environment:
172+
https_proxy: ""
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
---
2+
- name: Deploy CA secret store on the seed
3+
any_errors_fatal: true
4+
gather_facts: true
5+
hosts: seed
6+
vars:
7+
secret_store_bind_interface: lo
8+
secret_store_bind_address: "{{ ansible_facts[secret_store_bind_interface].ipv4.address }}"
9+
secret_store_api_address: "http://{{ secret_store_bind_address }}:8200"
10+
tasks:
11+
- name: Set a fact about the virtualenv on the remote system
12+
ansible.builtin.set_fact:
13+
virtualenv: "{{ ansible_python_interpreter | dirname | dirname }}"
14+
when:
15+
- ansible_python_interpreter is defined
16+
- not ansible_python_interpreter.startswith('/bin/')
17+
- not ansible_python_interpreter.startswith('/usr/bin/')
18+
19+
- name: Ensure Python PyYAML and hvac modules are installed
20+
ansible.builtin.pip:
21+
name:
22+
- PyYAML
23+
- hvac
24+
state: latest
25+
extra_args: "{% if pip_upper_constraints_file %}-c {{ pip_upper_constraints_file }}{% endif %}"
26+
virtualenv: "{{ virtualenv is defined | ternary(virtualenv, omit) }}"
27+
become: "{{ virtualenv is not defined }}"
28+
29+
- name: Ensure secret store directory exists in Kayobe configuration
30+
ansible.builtin.file:
31+
path: "{{ kayobe_env_config_path }}/{{ stackhpc_ca_secret_store }}/"
32+
state: directory
33+
delegate_to: localhost
34+
run_once: true
35+
36+
- name: Apply vault role
37+
ansible.builtin.import_role:
38+
name: stackhpc.hashicorp.vault
39+
vars:
40+
hashicorp_registry_url: "{{ seed_hashicorp_registry_url }}"
41+
hashicorp_registry_username: "{{ seed_hashicorp_registry_username }}"
42+
hashicorp_registry_password: "{{ seed_hashicorp_registry_password }}"
43+
consul_docker_image: "{{ seed_consul_docker_image }}"
44+
consul_docker_tag: "{{ seed_consul_docker_tag }}"
45+
consul_bind_interface: "{{ secret_store_bind_interface }}"
46+
vault_bind_address: "{{ secret_store_bind_address }}"
47+
vault_api_addr: "{{ secret_store_api_address }}"
48+
vault_config_dir: /opt/kayobe/vault
49+
vault_cluster_name: seed
50+
vault_docker_image: "{{ seed_vault_docker_image }}"
51+
vault_docker_tag: "{{ seed_vault_docker_tag }}"
52+
vault_write_keys_file: true
53+
vault_write_keys_file_path: "{{ kayobe_env_config_path }}/vault/seed-vault-keys.json"
54+
when: stackhpc_ca_secret_store == "vault"
55+
56+
- name: Apply OpenBao role
57+
ansible.builtin.import_role:
58+
name: stackhpc.hashicorp.openbao
59+
vars:
60+
openbao_bind_addr: "{{ secret_store_bind_address }}"
61+
openbao_api_addr: "{{ secret_store_api_address }}"
62+
openbao_registry_url: "{{ seed_openbao_registry_url }}"
63+
openbao_registry_username: "{{ seed_openbao_registry_username }}"
64+
openbao_registry_password: "{{ seed_openbao_registry_password }}"
65+
openbao_config_dir: /opt/kayobe/openbao
66+
openbao_cluster_name: seed
67+
openbao_docker_image: "{{ seed_openbao_docker_image }}"
68+
openbao_docker_tag: "{{ seed_openbao_docker_tag }}"
69+
openbao_write_keys_file: true
70+
openbao_write_keys_file_path: "{{ kayobe_env_config_path }}/openbao/seed-openbao-keys.json"
71+
when: stackhpc_ca_secret_store == "openbao"
72+
73+
- name: Include {{ stackhpc_ca_secret_store }} keys
74+
ansible.builtin.include_vars:
75+
file: "{{ kayobe_env_config_path }}/{{ stackhpc_ca_secret_store }}/seed-{{ stackhpc_ca_secret_store }}-keys.json"
76+
name: secret_store_keys
77+
78+
- name: Unseal {{ stackhpc_ca_secret_store }}
79+
ansible.builtin.import_role:
80+
name: stackhpc.hashicorp.vault_unseal
81+
vars:
82+
vault_api_addr: "{{ secret_store_api_address }}"
83+
vault_unseal_keys: "{{ secret_store_keys.keys_base64 }}"
84+
85+
- name: Apply PKI role
86+
ansible.builtin.import_role:
87+
name: stackhpc.hashicorp.vault_pki
88+
vars:
89+
vault_api_addr: "{{ secret_store_api_address }}"
90+
vault_token: "{{ secret_store_keys.root_token }}"
91+
vault_pki_root_ca_name: OS-TLS-ROOT
92+
vault_pki_write_root_ca_to_file: true
93+
vault_pki_intermediate_ca_name: OS-TLS-INT
94+
vault_pki_intermediate_export: true
95+
vault_pki_intermediate_roles: "{{ seed_vault_pki_roles if stackhpc_ca_secret_store == 'vault' else seed_openbao_pki_roles }}"
96+
vault_pki_certificates_directory: "{{ kayobe_env_config_path }}/{{ stackhpc_ca_secret_store }}"
97+
vault_pki_generate_certificates: true
98+
vault_pki_write_certificates: true
99+
vault_pki_certificate_subject: "{{ seed_vault_pki_certificate_subject if stackhpc_ca_secret_store == 'vault' else seed_openbao_pki_certificate_subject }}"
100+
vault_pki_write_certificate_files: true
101+
vault_pki_write_pem_bundle: false
102+
vault_pki_write_int_ca_to_file: true

0 commit comments

Comments
 (0)