Skip to content

Backport: Merge Openbao and Hashicorp Vault playbooks #1781

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: stackhpc/2024.1
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions etc/kayobe/ansible/secret-store-deploy-barbican.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
---
- name: Configure AppRole
any_errors_fatal: true
gather_facts: true
hosts: controllers[0]
vars:
secret_store_api_address: https://{{ internal_net_name | net_ip }}:8200
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' }}"
tasks:
- name: Assert that secrets_barbican_approle_secret_id is defined
ansible.builtin.assert:
that:
- secrets_barbican_approle_secret_id is defined
fail_msg: Please define secrets_barbican_approle_secret_id in your secrets.yml

- name: Include secret store keys
ansible.builtin.include_vars:
file: "{{ kayobe_env_config_path }}/{{ stackhpc_ca_secret_store }}/overcloud-{{ stackhpc_ca_secret_store }}-keys.json"
name: secret_store_keys

- name: Ensure hvac is installed
ansible.builtin.pip:
name: hvac
state: present
extra_args: "{% if pip_upper_constraints_file %}-c {{ pip_upper_constraints_file }}{% endif %}"
virtualenv: "{{ virtualenv_path }}/kayobe"

- name: Ensure AppRole is configured
environment:
https_proxy: ""
block:
- name: Enable AppRole auth module
hashivault_auth_method: # noqa: fqcn
url: "{{ secret_store_api_address }}"
ca_cert: "{{ secret_store_ca_cert }}"
token: "{{ secret_store_keys.root_token }}"
method_type: approle
state: enabled

- name: Enable barbican kv store
hashivault_secret_engine: # noqa: fqcn
url: "{{ secret_store_api_address }}"
ca_cert: "{{ secret_store_ca_cert }}"
token: "{{ secret_store_keys.root_token }}"
name: barbican
backend: kv
description: Barbican kv store

- name: Ensure barbican policy is defined
hashivault_policy: # noqa: fqcn
url: "{{ secret_store_api_address }}"
ca_cert: "{{ secret_store_ca_cert }}"
token: "{{ secret_store_keys.root_token }}"
name: barbican-policy
state: present
rules: |
path "barbican/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}

- name: Ensure barbican AppRole is defined
hashivault_approle_role: # noqa: fqcn
url: "{{ secret_store_api_address }}"
ca_cert: "{{ secret_store_ca_cert }}"
token: "{{ secret_store_keys.root_token }}"
bind_secret_id: true
secret_id_bound_cidrs: "{{ internal_net_name | net_cidr }}"
secret_id_ttl: 0
token_policies: barbican-policy
name: barbican

- name: Get barbican Approle ID
hashivault_approle_role_id: # noqa: fqcn
url: "{{ secret_store_api_address }}"
ca_cert: "{{ secret_store_ca_cert }}"
token: "{{ secret_store_keys.root_token }}"
name: barbican
register: barbican_role_id

- name: Print barbican Approle ID
ansible.builtin.debug:
msg: barbican role id is {{ barbican_role_id.id }}

- name: Write barbican Approle ID to file if requested
delegate_to: localhost
ansible.builtin.copy:
content: "{{ barbican_role_id.id }}"
dest: "{{ stackhpc_barbican_role_id_file_path | default('~/barbican-role-id') }}"
when: stackhpc_write_barbican_role_id_to_file | default(false) | bool

- name: Check if barbican Approle Secret ID is defined
hashivault_approle_role_secret_get: # noqa: fqcn
url: "{{ secret_store_api_address }}"
ca_cert: "{{ secret_store_ca_cert }}"
token: "{{ secret_store_keys.root_token }}"
secret: "{{ secrets_barbican_approle_secret_id }}"
name: barbican
register: barbican_approle_secret_get

- name: Ensure barbican AppRole Secret ID is defined
hashivault_approle_role_secret: # noqa: fqcn
url: "{{ secret_store_api_address }}"
ca_cert: "{{ secret_store_ca_cert }}"
token: "{{ secret_store_keys.root_token }}"
secret: "{{ secrets_barbican_approle_secret_id }}"
name: barbican
when: barbican_approle_secret_get.status == "absent"
172 changes: 172 additions & 0 deletions etc/kayobe/ansible/secret-store-deploy-overcloud.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
---
# Required for uri module to work with self-signed certificates and for systems to trust
# the self-signed CA
- name: Install CA on controllers
hosts: controllers
tasks:
- name: Copy the intermediate CA
ansible.builtin.copy:
src: "{{ kayobe_env_config_path }}/{{ stackhpc_ca_secret_store }}/OS-TLS-ROOT.pem"
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'
}}"
mode: "0644"
become: true

- name: Update system CA
become: true
ansible.builtin.command: "{{ 'update-ca-trust' if ansible_facts.os_family == 'RedHat' else 'update-ca-certificates' }}"

- name: Deploy Secret store on the overcloud
any_errors_fatal: true
gather_facts: true
hosts: controllers
vars:
secret_store_bind_interface: "{{ internal_net_name | net_interface }}"
secret_store_bind_address: "{{ internal_net_name | net_ip }}"
# This is the IP address of the first controller and therefore the leader within
# OpenBao. This could be replaced with the VIP address of the internal network if
# HAProxy has been configured to load balance the OpenBao API.
openbao_raft_leaders:
- "{{ internal_net_name | net_ip(inventory_hostname=groups['controllers'][0]) }}"
tasks:
- name: Set a fact about the virtualenv on the remote system
ansible.builtin.set_fact:
virtualenv: "{{ ansible_python_interpreter | dirname | dirname }}"
when:
- ansible_python_interpreter is defined
- not ansible_python_interpreter.startswith('/bin/')
- not ansible_python_interpreter.startswith('/usr/bin/')

- name: Ensure Python hvac module is installed
ansible.builtin.pip:
name: hvac
state: latest
extra_args: "{% if pip_upper_constraints_file %}-c {{ pip_upper_constraints_file }}{% endif %}"
virtualenv: "{{ virtualenv is defined | ternary(virtualenv, omit) }}"
become: "{{ virtualenv is not defined }}"

- name: Ensure /opt/kayobe/{{ stackhpc_ca_secret_store }} exists
ansible.builtin.file:
path: /opt/kayobe/{{ stackhpc_ca_secret_store }}
state: directory

- name: Template out TLS key and cert
ansible.builtin.copy:
# Within the OpenBao container these uids & gids map to the openbao user
src: "{{ kayobe_env_config_path }}/{{ stackhpc_ca_secret_store }}/{{ item }}"
dest: /opt/kayobe/{{ stackhpc_ca_secret_store }}/{{ item }}
owner: 100
group: 1000
mode: "0600"
loop:
- "{% if kolla_internal_fqdn != kolla_internal_vip_address %}{{ kolla_internal_fqdn }}{% else %}overcloud{% endif %}.crt"
- "{% if kolla_internal_fqdn != kolla_internal_vip_address %}{{ kolla_internal_fqdn }}{% else %}overcloud{% endif %}.key"
- "OS-TLS-INT.crt"
become: true

- name: Apply vault role
ansible.builtin.import_role:
name: stackhpc.hashicorp.vault
vars:
hashicorp_registry_url: "{{ overcloud_hashicorp_registry_url }}"
hashicorp_registry_username: "{{ overcloud_hashicorp_registry_username }}"
hashicorp_registry_password: "{{ overcloud_hashicorp_registry_password }}"
consul_docker_image: "{{ overcloud_consul_docker_image }}"
consul_docker_tag: "{{ overcloud_consul_docker_tag }}"
consul_bind_interface: "{{ secret_store_bind_interface }}"
vault_bind_address: "{{ secret_store_bind_address }}"
vault_config_dir: /opt/kayobe/vault
vault_cluster_name: overcloud
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' }}"
vault_docker_image: "{{ overcloud_vault_docker_image }}"
vault_docker_tag: "{{ overcloud_vault_docker_tag }}"
vault_tls_cert: "{% if kolla_internal_fqdn != kolla_internal_vip_address %}{{ kolla_internal_fqdn }}{% else %}overcloud{% endif %}.crt"
vault_tls_key: "{% if kolla_internal_fqdn != kolla_internal_vip_address %}{{ kolla_internal_fqdn }}{% else %}overcloud{% endif %}.key"
copy_self_signed_ca: true
vault_api_addr: https://{{ internal_net_name | net_ip }}:8200
vault_write_keys_file: true
vault_write_keys_file_path: "{{ kayobe_env_config_path }}/vault/overcloud-vault-keys.json"
when: stackhpc_ca_secret_store == "vault"

- name: Apply OpenBao role
ansible.builtin.import_role:
name: stackhpc.hashicorp.openbao
vars:
openbao_bind_addr: "{{ secret_store_bind_address }}"
openbao_registry_url: "{{ overcloud_openbao_registry_url }}"
openbao_registry_username: "{{ overcloud_openbao_registry_username }}"
openbao_registry_password: "{{ overcloud_openbao_registry_password }}"
openbao_config_dir: /opt/kayobe/openbao
openbao_cluster_name: overcloud
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' }}"
openbao_docker_image: "{{ overcloud_openbao_docker_image }}"
openbao_docker_tag: "{{ overcloud_openbao_docker_tag }}"
openbao_tls_cert: "{% if kolla_internal_fqdn != kolla_internal_vip_address %}{{ kolla_internal_fqdn }}{% else %}overcloud{% endif %}.crt"
openbao_tls_key: "{% if kolla_internal_fqdn != kolla_internal_vip_address %}{{ kolla_internal_fqdn }}{% else %}overcloud{% endif %}.key"
openbao_tls_ca: "OS-TLS-INT.crt"
copy_self_signed_ca: true
openbao_api_addr: https://{{ internal_net_name | net_ip }}:8200
openbao_write_keys_file: true
openbao_write_keys_file_path: "{{ kayobe_env_config_path }}/openbao/overcloud-openbao-keys.json"
when: stackhpc_ca_secret_store == "openbao"

- name: Include secret store keys
ansible.builtin.include_vars:
file: "{{ kayobe_env_config_path }}/{{ stackhpc_ca_secret_store }}/overcloud-{{ stackhpc_ca_secret_store }}-keys.json"
name: secret_store_keys

- name: Unseal first secret store instance
ansible.builtin.import_role:
name: stackhpc.hashicorp.vault_unseal
vars:
vault_api_addr: https://{{ internal_net_name | net_ip }}:8200
vault_unseal_token: "{{ secret_store_keys.root_token }}"
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' }}"
vault_unseal_keys: "{{ secret_store_keys.keys_base64 }}"
environment:
https_proxy: ""
run_once: true

# As the first instance is now unsealed the other instances will now need some
# time to connect before we can proceed.
- name: Wait for OpenBao Raft peers to connect
ansible.builtin.wait_for:
timeout: 30
delegate_to: localhost

# Raft peers take few seconds before they report an unsealed state therefore
# we must wait.
- name: Unseal all secret store instances
ansible.builtin.import_role:
name: stackhpc.hashicorp.vault_unseal
vars:
vault_api_addr: https://{{ internal_net_name | net_ip }}:8200
vault_unseal_token: "{{ secret_store_keys.root_token }}"
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' }}"
vault_unseal_keys: "{{ secret_store_keys.keys_base64 }}"
vault_unseal_timeout: 10
environment:
https_proxy: ""

- name: Configure PKI
any_errors_fatal: true
gather_facts: true
hosts: controllers[0]
tasks:
- name: Apply pki role
ansible.builtin.import_role:
name: stackhpc.hashicorp.vault_pki
vars:
vault_token: "{{ secret_store_keys.root_token }}"
vault_api_addr: https://{{ internal_net_name | net_ip }}:8200
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' }}"
vault_pki_root_create: false
vault_pki_intermediate_import: true
vault_pki_intermediate_ca_name: OS-TLS-INT
vault_pki_intermediate_ca_bundle: "{{ lookup('file', kayobe_env_config_path + '/' + stackhpc_ca_secret_store + '/OS-TLS-INT.pem') }}"
vault_pki_intermediate_ca_cert: "{{ lookup('file', kayobe_env_config_path + '/' + stackhpc_ca_secret_store + '/OS-TLS-INT.crt') }}"
vault_pki_intermediate_roles: "{{ overcloud_vault_pki_roles if stackhpc_ca_secret_store == 'vault' else overcloud_openbao_pki_roles }}"
vault_pki_write_certificate_files: true
vault_pki_certificates_directory: "{{ kayobe_env_config_path }}/{{ stackhpc_ca_secret_store }}"
environment:
https_proxy: ""
102 changes: 102 additions & 0 deletions etc/kayobe/ansible/secret-store-deploy-seed.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
---
- name: Deploy CA secret store on the seed
any_errors_fatal: true
gather_facts: true
hosts: seed
vars:
secret_store_bind_interface: lo
secret_store_bind_address: "{{ ansible_facts[secret_store_bind_interface].ipv4.address }}"
secret_store_api_address: "http://{{ secret_store_bind_address }}:8200"
tasks:
- name: Set a fact about the virtualenv on the remote system
ansible.builtin.set_fact:
virtualenv: "{{ ansible_python_interpreter | dirname | dirname }}"
when:
- ansible_python_interpreter is defined
- not ansible_python_interpreter.startswith('/bin/')
- not ansible_python_interpreter.startswith('/usr/bin/')

- name: Ensure Python PyYAML and hvac modules are installed
ansible.builtin.pip:
name:
- PyYAML
- hvac
state: latest
extra_args: "{% if pip_upper_constraints_file %}-c {{ pip_upper_constraints_file }}{% endif %}"
virtualenv: "{{ virtualenv is defined | ternary(virtualenv, omit) }}"
become: "{{ virtualenv is not defined }}"

- name: Ensure secret store directory exists in Kayobe configuration
ansible.builtin.file:
path: "{{ kayobe_env_config_path }}/{{ stackhpc_ca_secret_store }}/"
state: directory
delegate_to: localhost
run_once: true

- name: Apply vault role
ansible.builtin.import_role:
name: stackhpc.hashicorp.vault
vars:
hashicorp_registry_url: "{{ seed_hashicorp_registry_url }}"
hashicorp_registry_username: "{{ seed_hashicorp_registry_username }}"
hashicorp_registry_password: "{{ seed_hashicorp_registry_password }}"
consul_docker_image: "{{ seed_consul_docker_image }}"
consul_docker_tag: "{{ seed_consul_docker_tag }}"
consul_bind_interface: "{{ secret_store_bind_interface }}"
vault_bind_address: "{{ secret_store_bind_address }}"
vault_api_addr: "{{ secret_store_api_address }}"
vault_config_dir: /opt/kayobe/vault
vault_cluster_name: seed
vault_docker_image: "{{ seed_vault_docker_image }}"
vault_docker_tag: "{{ seed_vault_docker_tag }}"
vault_write_keys_file: true
vault_write_keys_file_path: "{{ kayobe_env_config_path }}/vault/seed-vault-keys.json"
when: stackhpc_ca_secret_store == "vault"

- name: Apply OpenBao role
ansible.builtin.import_role:
name: stackhpc.hashicorp.openbao
vars:
openbao_bind_addr: "{{ secret_store_bind_address }}"
openbao_api_addr: "{{ secret_store_api_address }}"
openbao_registry_url: "{{ seed_openbao_registry_url }}"
openbao_registry_username: "{{ seed_openbao_registry_username }}"
openbao_registry_password: "{{ seed_openbao_registry_password }}"
openbao_config_dir: /opt/kayobe/openbao
openbao_cluster_name: seed
openbao_docker_image: "{{ seed_openbao_docker_image }}"
openbao_docker_tag: "{{ seed_openbao_docker_tag }}"
openbao_write_keys_file: true
openbao_write_keys_file_path: "{{ kayobe_env_config_path }}/openbao/seed-openbao-keys.json"
when: stackhpc_ca_secret_store == "openbao"

- name: Include {{ stackhpc_ca_secret_store }} keys
ansible.builtin.include_vars:
file: "{{ kayobe_env_config_path }}/{{ stackhpc_ca_secret_store }}/seed-{{ stackhpc_ca_secret_store }}-keys.json"
name: secret_store_keys

- name: Unseal {{ stackhpc_ca_secret_store }}
ansible.builtin.import_role:
name: stackhpc.hashicorp.vault_unseal
vars:
vault_api_addr: "{{ secret_store_api_address }}"
vault_unseal_keys: "{{ secret_store_keys.keys_base64 }}"

- name: Apply PKI role
ansible.builtin.import_role:
name: stackhpc.hashicorp.vault_pki
vars:
vault_api_addr: "{{ secret_store_api_address }}"
vault_token: "{{ secret_store_keys.root_token }}"
vault_pki_root_ca_name: OS-TLS-ROOT
vault_pki_write_root_ca_to_file: true
vault_pki_intermediate_ca_name: OS-TLS-INT
vault_pki_intermediate_export: true
vault_pki_intermediate_roles: "{{ seed_vault_pki_roles if stackhpc_ca_secret_store == 'vault' else seed_openbao_pki_roles }}"
vault_pki_certificates_directory: "{{ kayobe_env_config_path }}/{{ stackhpc_ca_secret_store }}"
vault_pki_generate_certificates: true
vault_pki_write_certificates: true
vault_pki_certificate_subject: "{{ seed_vault_pki_certificate_subject if stackhpc_ca_secret_store == 'vault' else seed_openbao_pki_certificate_subject }}"
vault_pki_write_certificate_files: true
vault_pki_write_pem_bundle: false
vault_pki_write_int_ca_to_file: true
Loading
Loading