diff --git a/doc/source/configuration/index.rst b/doc/source/configuration/index.rst index 136cf13a1..576dfe63d 100644 --- a/doc/source/configuration/index.rst +++ b/doc/source/configuration/index.rst @@ -13,6 +13,7 @@ the various features provided. lvm cephadm monitoring + openbao vault wazuh walled-garden diff --git a/doc/source/configuration/openbao.rst b/doc/source/configuration/openbao.rst new file mode 100644 index 000000000..87d1c1435 --- /dev/null +++ b/doc/source/configuration/openbao.rst @@ -0,0 +1,441 @@ +.. _openbao: + +======================== +OpenBao for internal PKI +======================== + +This document describes how to deploy OpenBao for +internal PKI purposes using the +`StackHPC Hashicorp collection `_ + +OpenBao may be used as a Certificate Authority to generate certificates for: + +* OpenStack internal API +* OpenStack backend APIs +* RabbitMQ + +TLS support is described in the :kolla-ansible-doc:`Kolla Ansible documentation +` and the :kayobe-doc:`Kayobe documentation +`. + +OpenBao may also be used as the secret store for Barbican. + +Background +========== + +Our OpenStack environment employs two separate OpenBao instances. +These instances manage the Public Key Infrastructure (PKI) by handling the +creation and issuance of certificates. + +- The first OpenBao instance is located on the seed host. + It handles infrastructure-level certificates, generating the root + Certificate Authority (CA) and intermediate CA for the second OpenBao. + The ``openbao-deploy-seed.yml`` playbook sets up this instance. + +- The second OpenBao instance is within the OpenStack + overcloud, located on the controller nodes. This instance uses the + intermediate CA from the seed OpenBao to issue application-specific + certificates. The ``vault-openbao-overcloud.yml`` playbook is used + for its setup. It ensures that all controller nodes trust the + intermediate CA from the root OpenBao. + +The dual OpenBao setup enhances security by protecting the root CA's key. The more +exposed overcloud OpenBao only possesses the intermediate key, ensuring that +the root key remains secure even if the overcloud OpenBao instance is compromised. + +Prerequisites +============= + +Before beginning the deployment of OpenBao for openstack internal TLS and backend TLS you should ensure that you have the following. + + * Seed Node or a host to run the vault container on + * Overcloud controller hosts to install second vault on + * Ansible Galaxy dependencies installed: ``kayobe control host bootstrap`` + * Python dependencies installed: ``pip install -r kayobe-config/requirements.txt`` + +By default OpenBao image is not synced from Docker Hub to the local +Pulp. To sync this image, set ``stackhpc_sync_openbao_images`` to ``true``. +The OpenBao deployment configuration will be automatically updated to pull images +from Pulp. + +Deployment +========== + +Setup OpenBao on the seed node +------------------------------ + +1. Run openbao-deploy-seed.yml custom playbook + + .. code-block:: + + kayobe playbook run $KAYOBE_CONFIG_PATH/ansible/openbao-deploy-seed.yml + +2. Encrypt generated certs/keys with ansible-vault (use proper location of vault password file) + + .. code-block:: + + ansible-vault encrypt --vault-password-file ~/vault.pass $KAYOBE_CONFIG_PATH/openbao/OS-TLS-INT.pem + ansible-vault encrypt --vault-password-file ~/vault.pass $KAYOBE_CONFIG_PATH/openbao/seed-openbao-keys.json + ansible-vault encrypt --vault-password-file ~/vault.pass $KAYOBE_CONFIG_PATH/openbao/overcloud.key + + Or if environments are being used + + .. code-block:: + + ansible-vault encrypt --vault-password-file ~/vault.pass $KAYOBE_CONFIG_PATH/environments/$KAYOBE_ENVIRONMENT/openbao/OS-TLS-INT.pem + ansible-vault encrypt --vault-password-file ~/vault.pass $KAYOBE_CONFIG_PATH/environments/$KAYOBE_ENVIRONMENT/openbao/seed-openbao-keys.json + ansible-vault encrypt --vault-password-file ~/vault.pass $KAYOBE_CONFIG_PATH/environments/$KAYOBE_ENVIRONMENT/openbao/overcloud.key + +Setup OpenBao HA on the overcloud hosts +--------------------------------------- + +1. Run openbao-deploy-overcloud.yml custom playbook + + .. code-block:: + + kayobe playbook run $KAYOBE_CONFIG_PATH/ansible/openbao-deploy-overcloud.yml + +2. Encrypt overcloud openbao keys (use proper location of vault password file) + + .. code-block:: + + ansible-vault encrypt --vault-password-file ~/vault.pass $KAYOBE_CONFIG_PATH/openbao/overcloud-openbao-keys.json + + Or if environments are being used + + .. code-block:: + + ansible-vault encrypt --vault-password-file ~/vault.pass $KAYOBE_CONFIG_PATH/environments/$KAYOBE_ENVIRONMENT/openbao/overcloud-openbao-keys.json + +Rotating OpenBao certificate on the overcloud hosts +--------------------------------------------------- + +The certificate for the overcloud OpenBao has an expiry time of one year. While +the cloud won't break if this expires, it will need rotating before new +certificates can be generated for internal PKI. If a OpenBao becomes sealed, it +cannot be unsealed with an expired certificate. + +1. Delete the old certificate: + + .. code-block:: + + rm $KAYOBE_CONFIG_PATH/openbao/overcloud.crt + + Or if environments are being used + + .. code-block:: + + rm $KAYOBE_CONFIG_PATH/environments/$KAYOBE_ENVIRONMENT/openbao/overcloud.crt + +2. Generate a new certificate (and key): + + .. code-block:: + + kayobe playbook run $KAYOBE_CONFIG_PATH/ansible/openbao-deploy-seed.yml + +3. Encrypt generated key with ansible-vault (use proper location of vault password file) + + .. code-block:: + + ansible-vault encrypt --vault-password-file ~/vault.pass $KAYOBE_CONFIG_PATH/openbao/overcloud.key + + Or if environments are being used + + .. code-block:: + + ansible-vault encrypt --vault-password-file ~/vault.pass $KAYOBE_CONFIG_PATH/environments/$KAYOBE_ENVIRONMENT/openbao/overcloud.key + +4. Copy the new certificate to the overcloud hosts. Note, if the old + certificate has expired this will fail on the unseal step. + + .. code-block:: + + kayobe playbook run $KAYOBE_CONFIG_PATH/ansible/openbao-deploy-overcloud.yml + +5. Restart the containers to use the new certificate: + + .. code-block:: + + kayobe overcloud host command run --command "docker restart openbao" -l controllers + +6. If sealed, unseal OpenBao: + + .. code-block:: + + kayobe playbook run $KAYOBE_CONFIG_PATH/ansible/openbao-unseal-overcloud.yml + +Certificates generation +======================= + +.. note:: + + Generating certificates will fail if the OpenBao on the overcloud is sealed. This will happen whenever the openbao containers are restarted. To unseal the + overcloud OpenBao, run: + + .. code-block:: + + kayobe playbook run $KAYOBE_CONFIG_PATH/ansible/openbao-unseal-overcloud.yml + +Create the external TLS certificates (testing only) +--------------------------------------------------- + +This method should only be used for testing. For external TLS on production systems, +See `Installing External TLS Certificates `__. + +Typically external API TLS certificates should be generated by a organisation's trusted internal or third-party CA. +For test and development purposes it is possible to use OpenBao as a CA for the external API. + +1. Run the playbook + + .. code-block:: + + kayobe playbook run $KAYOBE_CONFIG_PATH/ansible/openbao-generate-test-external-tls.yml + +2. Use ansible-vault to encrypt the PEM bundle in $KAYOBE_CONFIG_PATH/kolla/certificates/haproxy.pem. Commit the PEM bundle to the kayobe configuration. + + .. code-block:: + + ansible-vault encrypt --vault-password-file ~/vault.pass $KAYOBE_CONFIG_PATH/kolla/certificates/haproxy.pem + + Or if environments are being used + + .. code-block:: + + ansible-vault encrypt --vault-password-file ~/vault.pass $KAYOBE_CONFIG_PATH/environments/$KAYOBE_ENVIRONMENT/kolla/certificates/haproxy.pem + +Create the internal TLS certificates +------------------------------------ + +1. Run the playbook + + .. code-block:: + + kayobe playbook run $KAYOBE_CONFIG_PATH/ansible/openbao-generate-internal-tls.yml + +2. Use ansible-vault to encrypt the PEM bundle in $KAYOBE_CONFIG_PATH/kolla/certificates/haproxy-internal.pem. Commit the PEM bundle and root CA to the kayobe configuration. + + .. code-block:: + + ansible-vault encrypt --vault-password-file ~/vault.pass $KAYOBE_CONFIG_PATH/kolla/certificates/haproxy-internal.pem + + Or if environments are being used + + .. code-block:: + + ansible-vault encrypt --vault-password-file ~/vault.pass $KAYOBE_CONFIG_PATH/environments/$KAYOBE_ENVIRONMENT/kolla/certificates/haproxy-internal.pem + +Create the backend TLS and RabbitMQ TLS certificates +---------------------------------------------------- + +1. Run the playbook + + .. code-block:: + + kayobe playbook run $KAYOBE_CONFIG_PATH/ansible/openbao-generate-backend-tls.yml + +2. Use ansible-vault to encrypt the keys in $KAYOBE_CONFIG_PATH/kolla/certificates/-key.pem. Commit the certificates and keys to the kayobe configuration. + + .. code-block:: + + ansible-vault encrypt --vault-password-file ~/vault.pass $KAYOBE_CONFIG_PATH/kolla/certificates/-key.pem + + Or if environments are being used + + .. code-block:: + + ansible-vault encrypt --vault-password-file ~/vault.pass $KAYOBE_CONFIG_PATH/environments/$KAYOBE_ENVIRONMENT/kolla/certificates/-key.pem + +.. _openbao-haproxy: + +HAProxy integration +=================== + +It is possible to expose the overcloud OpenBao service via the Kolla Ansible HAProxy load balancer. +This provides a single highly available API endpoint, as well as monitoring of the OpenBao backends when combined with Prometheus. +HAProxy integration is no longer required for generating OpenStack control plane certificates, making it possible to deploy OpenBao and generate certificates before any containers have been deployed by Kolla Ansible. + +1. Create the HAProxy config to reverse proxy the OpenBao HA container + + Set the openbao_front to the external VIP address or internal VIP address depending on the installation. Set the openbao_back to the IPs of the control nodes. + + Set the following in etc/kayobe/kolla/config/haproxy/services.d/openbao.cfg or if environments are being used etc/kayobe/environments/$KAYOBE_ENVIRONMENT/kolla/config/haproxy/services.d/openbao.cfg + + .. code-block:: + + # Delete "verify none" if not using self-signed/unknown issuer + {% raw %} + frontend openbao_front + mode tcp + option tcplog + bind {{ kolla_internal_vip_address }}:8200 + default_backend openbao_back + + backend openbao_back + mode tcp + option httpchk GET /v1/sys/health + # https://openbao.org/api-docs/system/health/ + # 200: initialized, unsealed, and active + # 429: standby + http-check expect rstatus (200|429) + + {% for host in groups['control'] %} + {% set host_name = hostvars[host].ansible_facts.hostname %} + {% set host_ip = 'api' | kolla_address(host) %} + server {{ host_name }} {{ host_ip }}:8200 check check-ssl verify none inter 2000 rise 2 fall 5 + {% endfor %} + {% endraw %} + +2. If HAProxy has not yet been deployed, continue to :ref:`certificates deployment `. + If HAProxy has been deployed, it may be redeployed with the new OpenBao service configuration: + + .. code-block:: + + kayobe overcloud service deploy -kt haproxy + +.. _openbao-certificates: + +Certificates deployment +======================= + +.. warning:: + + The switch from HTTP to HTTPS during the deployment of internal/backend TLS certificates can temporarily disrupt service availability and necessitates a restart of all services. During this transition, endpoints may become unreachable following the HAProxy restart, persisting until the endpoint catalogue and client have been reconfigured to use HTTPS. + +Enable the required TLS variables in kayobe and kolla +----------------------------------------------------- + +1. If using OpenBao as a CA for the external API, set the following in kayobe-config/etc/kayobe/kolla.yml or if environments are being used etc/kayobe/environments/$KAYOBE_ENVIRONMENT/kolla.yml + + .. code-block:: + + # Whether TLS is enabled for the external API endpoints. Default is 'no'. + kolla_enable_tls_external: yes + kolla_public_openrc_cacert: "{{ '/etc/pki/tls/certs/ca-bundle.crt' if os_distribution in ['centos', 'rocky'] else '/etc/ssl/certs/ca-certificates.crt' }}" + + See :ref:`tempest-cacert` for information on adding CA certificates to the trust store when running Tempest. + +2. Set the following in kayobe-config/etc/kayobe/kolla.yml or if environments are being used etc/kayobe/environments/$KAYOBE_ENVIRONMENT/kolla.yml + + .. code-block:: + + # Whether TLS is enabled for the internal API endpoints. Default is 'no'. + kolla_enable_tls_internal: yes + kolla_admin_openrc_cacert: "{{ '/etc/pki/tls/certs/ca-bundle.crt' if os_distribution in ['centos', 'rocky'] else '/etc/ssl/certs/ca-certificates.crt' }}" + + See :ref:`os-capacity` for information on adding CA certificates to the trust store when deploying the OpenStack Capacity exporter. + +3. Set the following in etc/kayobe/kolla/globals.yml or if environments are being used etc/kayobe/environments/$KAYOBE_ENVIRONMENT/kolla/globals.yml + + .. code-block:: + + # Internal TLS configuration + # Copy the self-signed CA into the kolla containers + kolla_copy_ca_into_containers: "yes" + # Use the following trust store within the container + openstack_cacert: "{{ '/etc/pki/tls/certs/ca-bundle.crt' if os_distribution == 'rocky' else '/etc/ssl/certs/ca-certificates.crt' }}" + + # Backend TLS config + # Enable backend TLS + kolla_enable_tls_backend: "yes" + + # If using RabbitMQ TLS: + rabbitmq_enable_tls: "yes" + +4. Deploy OpenStack + + .. warning:: + + It is important that you are only using admin endpoints for keystone. If + any admin endpoints exist for other services, they must be deleted e.g. + + .. code-block:: + + openstack endpoint list --interface admin -f value | \ + awk '!/keystone/ {print $1}' | xargs openstack endpoint delete + + .. code-block:: + + kayobe overcloud service deploy + + If VM provisioning fails with an error with this format: + + .. code-block:: + + Unable to establish connection to http://:9696/v2.0/ports/some-sort-of-uuid: Connection aborted + + Restart the nova-compute container on all hypervisors: + + .. code-block:: + + kayobe overcloud host command run --command "systemctl restart kolla-nova_compute-container.service" --become --show-output -l compute + +Barbican integration +==================== + +Barbican integration depends on :ref:`HAProxy integration `. + +Enable Barbican in kayobe +------------------------- + +1. Set the following in kayobe-config/etc/kayobe/kolla.yml or if environments are being used etc/kayobe/environments/$KAYOBE_ENVIRONMENT/kolla.yml + + .. code-block:: + + kolla_enable_barbican: yes + +Generate secrets_barbican_approle_secret_id +------------------------------------------- + +1. Run ``uuidgen`` to generate secret id +2. Insert into secrets.yml or if environments are being used etc/kayobe/environments/$KAYOBE_ENVIRONMENT/secrets.yml + + .. code-block:: + + secrets_barbican_approle_secret_id: "YOUR-SECRET-GOES-HERE" + +Create required configuration in OpenBao +---------------------------------------- + +1. Run openbao-deploy-barbican.yml custom playbook + + .. code-block:: + + kayobe playbook run $KAYOBE_CONFIG_PATH/ansible/openbao-deploy-barbican.yml + +Add secrets_barbican_approle_id to secrets +------------------------------------------ + +1. Note the role id from playbook output and insert into secrets.yml or if environments are being used etc/kayobe/environments/$KAYOBE_ENVIRONMENT/secrets.yml + + .. code-block:: + + secrets_barbican_approle_role_id: "YOUR-APPROLE-ID-GOES-HERE" + +Configure Barbican +------------------ + +1. Put required configuration in kayobe-config/etc/kayobe/kolla/config/barbican.conf or if environments are being used etc/kayobe/environments/$KAYOBE_ENVIRONMENT/kolla/config/barbican.conf + + .. code-block:: + + [secretstore] + namespace=barbican.secretstore.plugin + enable_multiple_secret_stores=false + enabled_secretstore_plugins=vault_plugin + + [vault_plugin] + vault_url = https://{{ kolla_internal_fqdn }}:8200 + use_ssl = True + {% raw %} + ssl_ca_crt_file = {{ openstack_cacert }} + {% endraw %} + approle_role_id = {{ secrets_barbican_approle_role_id }} + approle_secret_id = {{ secrets_barbican_approle_secret_id }} + kv_mountpoint = barbican + +Deploy Barbican +--------------- + + .. code-block:: + + kayobe overcloud service deploy -kt barbican diff --git a/doc/source/configuration/vault.rst b/doc/source/configuration/vault.rst index 239ed64c6..126f5adc8 100644 --- a/doc/source/configuration/vault.rst +++ b/doc/source/configuration/vault.rst @@ -4,6 +4,13 @@ Hashicorp Vault for internal PKI ================================ +.. warning:: + + Deployment of Hashicorp Vault is deprecated and will be removed in a future release. + New deployments should use OpenBao and existing deployments will be migrated once an + method for migration is available. + See :ref:`here ` for more information. + This document describes how to deploy Hashicorp Vault for internal PKI purposes using the `StackHPC Hashicorp collection `_ diff --git a/etc/kayobe/ansible/openbao-deploy-barbican.yml b/etc/kayobe/ansible/openbao-deploy-barbican.yml new file mode 100644 index 000000000..50d55aa22 --- /dev/null +++ b/etc/kayobe/ansible/openbao-deploy-barbican.yml @@ -0,0 +1,107 @@ +--- +- name: Configure AppRole + any_errors_fatal: true + gather_facts: true + hosts: controllers[0] + vars: + openbao_api_addr: https://{{ internal_net_name | net_ip }}:8200 + 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' }}" + 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 OpenBao keys + ansible.builtin.include_vars: + file: "{{ kayobe_env_config_path }}/openbao/overcloud-openbao-keys.json" + name: openbao_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: "{{ openbao_api_addr }}" + ca_cert: "{{ openbao_ca_cert }}" + token: "{{ openbao_keys.root_token }}" + method_type: approle + state: enabled + + - name: Enable barbican kv store + hashivault_secret_engine: # noqa: fqcn + url: "{{ openbao_api_addr }}" + ca_cert: "{{ openbao_ca_cert }}" + token: "{{ openbao_keys.root_token }}" + name: barbican + backend: kv + description: Barbican kv store + + - name: Ensure barbican policy is defined + hashivault_policy: # noqa: fqcn + url: "{{ openbao_api_addr }}" + ca_cert: "{{ openbao_ca_cert }}" + token: "{{ openbao_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: "{{ openbao_api_addr }}" + ca_cert: "{{ openbao_ca_cert }}" + token: "{{ openbao_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: "{{ openbao_api_addr }}" + ca_cert: "{{ openbao_ca_cert }}" + token: "{{ openbao_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: "{{ openbao_api_addr }}" + ca_cert: "{{ openbao_ca_cert }}" + token: "{{ openbao_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: "{{ openbao_api_addr }}" + ca_cert: "{{ openbao_ca_cert }}" + token: "{{ openbao_keys.root_token }}" + secret: "{{ secrets_barbican_approle_secret_id }}" + name: barbican + when: barbican_approle_secret_get.status == "absent" diff --git a/etc/kayobe/ansible/openbao-deploy-overcloud.yml b/etc/kayobe/ansible/openbao-deploy-overcloud.yml new file mode 100644 index 000000000..811e9b1f0 --- /dev/null +++ b/etc/kayobe/ansible/openbao-deploy-overcloud.yml @@ -0,0 +1,116 @@ +--- +# 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 }}/openbao/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 OpenBao on the overcloud + any_errors_fatal: true + gather_facts: true + hosts: controllers + vars: + openbao_bind_address: "{{ internal_net_name | net_ip }}" + 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/openbao exists + ansible.builtin.file: + path: /opt/kayobe/openbao + state: directory + + - name: Template out TLS key and cert + ansible.builtin.copy: + # Within the OpenBao container these uids & gids map to the vault user + src: "{{ kayobe_env_config_path }}/openbao/{{ item }}" + dest: /opt/kayobe/openbao/{{ 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" + become: true + + - name: Apply OpenBao role + ansible.builtin.import_role: + name: stackhpc.hashicorp.openbao + vars: + 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" + 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" + + - name: Include OpenBao keys + ansible.builtin.include_vars: + file: "{{ kayobe_env_config_path }}/openbao/overcloud-openbao-keys.json" + name: openbao_keys + + - name: Unseal OpenBao + ansible.builtin.import_role: + name: stackhpc.hashicorp.vault_unseal + vars: + vault_api_addr: https://{{ internal_net_name | net_ip }}:8200 + vault_unseal_token: "{{ openbao_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: "{{ openbao_keys.keys_base64 }}" + environment: + https_proxy: "" + +- name: Configure PKI + any_errors_fatal: true + gather_facts: true + hosts: controllers[0] + tasks: + - name: Apply OpenBao pki role + ansible.builtin.import_role: + name: stackhpc.hashicorp.vault_pki + vars: + vault_token: "{{ openbao_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 + '/openbao/OS-TLS-INT.pem') }}" + vault_pki_intermediate_ca_cert: "{{ lookup('file', kayobe_env_config_path + '/openbao/OS-TLS-INT.crt') }}" + vault_pki_intermediate_roles: "{{ overcloud_openbao_pki_roles }}" + vault_pki_write_certificate_files: true + vault_pki_certificates_directory: "{{ kayobe_env_config_path }}/openbao" + environment: + https_proxy: "" diff --git a/etc/kayobe/ansible/openbao-deploy-seed.yml b/etc/kayobe/ansible/openbao-deploy-seed.yml new file mode 100644 index 000000000..2f276cbf6 --- /dev/null +++ b/etc/kayobe/ansible/openbao-deploy-seed.yml @@ -0,0 +1,78 @@ +--- +- name: Deploy OpenBao on the seed + any_errors_fatal: true + gather_facts: true + hosts: seed + vars: + openbao_bind_address: "{{ ansible_facts['lo'].ipv4.address }}" + openbao_api_addr: "http://{{ openbao_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 OpenBao directory exists in Kayobe configuration + ansible.builtin.file: + path: "{{ kayobe_env_config_path }}/openbao/" + state: directory + delegate_to: localhost + run_once: true + + - name: Apply OpenBao role + ansible.builtin.import_role: + name: stackhpc.hashicorp.openbao + vars: + 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" + + - name: Include Vault keys + ansible.builtin.include_vars: + file: "{{ kayobe_env_config_path }}/openbao/seed-openbao-keys.json" + name: openbao_keys + + - name: Unseal OpenBao + ansible.builtin.import_role: + name: stackhpc.hashicorp.vault_unseal + vars: + vault_api_addr: "{{ openbao_api_addr }}" + vault_unseal_keys: "{{ openbao_keys.keys_base64 }}" + + - name: Apply PKI role + ansible.builtin.import_role: + name: stackhpc.hashicorp.vault_pki + vars: + vault_api_addr: "{{ openbao_api_addr }}" + vault_token: "{{ openbao_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_openbao_pki_roles }}" + vault_pki_certificates_directory: "{{ kayobe_env_config_path }}/openbao" + vault_pki_generate_certificates: true + vault_pki_write_certificates: true + vault_pki_certificate_subject: "{{ 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 diff --git a/etc/kayobe/ansible/openbao-generate-backend-tls.yml b/etc/kayobe/ansible/openbao-generate-backend-tls.yml new file mode 100644 index 000000000..f43513ff1 --- /dev/null +++ b/etc/kayobe/ansible/openbao-generate-backend-tls.yml @@ -0,0 +1,83 @@ +--- +# Required for uri module to work with self-signed certificates and for systems to trust +# the self-signed CA +- name: Install CA + hosts: controllers:network + tasks: + - name: Copy the intermediate CA + ansible.builtin.copy: + src: "{{ kayobe_env_config_path }}/openbao/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: Generate backend API certificates + hosts: controllers:network + vars: + openbao_api_addr: https://{{ internal_net_name | net_ip(groups['controllers'][0]) }}:8200 + openbao_intermediate_ca_name: OS-TLS-INT + 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: Include OpenBao keys + ansible.builtin.include_vars: + file: "{{ kayobe_env_config_path }}/openbao/overcloud-openbao-keys.json" + name: openbao_keys + + - name: Issue a certificate for backend TLS + hashivault_pki_cert_issue: # noqa: fqcn + url: "{{ openbao_api_addr }}" + 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' }}" + token: "{{ openbao_keys.root_token }}" + mount_point: "{{ openbao_intermediate_ca_name }}" + role: "{{ overcloud_openbao_pki_backend_tls_role_name }}" + common_name: "" + extra_params: + ip_sans: "{{ internal_net_name | net_ip }}" + register: backend_cert + environment: + https_proxy: "" + + - name: Ensure certificates directory exists + ansible.builtin.file: + path: "{{ kayobe_env_config_path }}/kolla/certificates" + state: directory + delegate_to: localhost + + - name: Copy backend cert + no_log: true + ansible.builtin.copy: + dest: "{{ kayobe_env_config_path }}/kolla/certificates/{{ inventory_hostname }}-cert.pem" + content: | + {{ backend_cert.data.certificate }} + {{ backend_cert.data.issuing_ca }} + mode: "0600" + delegate_to: localhost + + - name: Copy backend key + no_log: true + ansible.builtin.copy: + dest: "{{ kayobe_env_config_path }}/kolla/certificates/{{ inventory_hostname }}-key.pem" + content: | + {{ backend_cert.data.private_key }} + mode: "0600" + delegate_to: localhost diff --git a/etc/kayobe/ansible/openbao-generate-internal-tls.yml b/etc/kayobe/ansible/openbao-generate-internal-tls.yml new file mode 100644 index 000000000..2cc9e841a --- /dev/null +++ b/etc/kayobe/ansible/openbao-generate-internal-tls.yml @@ -0,0 +1,56 @@ +--- +- name: Generate internal API certificate + hosts: controllers + run_once: true + vars: + openbao_api_addr: https://{{ internal_net_name | net_ip }}:8200 + openbao_intermediate_ca_name: OS-TLS-INT + tasks: + - name: Include OpenBao keys + ansible.builtin.include_vars: + file: "{{ kayobe_env_config_path }}/openbao/overcloud-openbao-keys.json" + name: openbao_keys + + - name: Issue a certificate for internal TLS + hashivault_pki_cert_issue: # noqa: fqcn + url: "{{ openbao_api_addr }}" + 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' }}" + token: "{{ openbao_keys.root_token }}" + mount_point: "{{ openbao_intermediate_ca_name }}" + role: "{{ overcloud_openbao_pki_internal_tls_role_name }}" + common_name: "{% if kolla_internal_fqdn != kolla_internal_vip_address %}{{ kolla_internal_fqdn }}{% endif %}" + extra_params: + ip_sans: "{{ kolla_internal_vip_address }}" + register: internal_cert + environment: + https_proxy: "" + + - name: Ensure certificates directory exists + ansible.builtin.file: + path: "{{ kayobe_env_config_path }}/kolla/certificates" + state: directory + delegate_to: localhost + + - name: Ensure CA certificates directory exists + ansible.builtin.file: + path: "{{ kayobe_env_config_path }}/kolla/certificates/ca" + state: directory + delegate_to: localhost + + - name: Copy internal API PEM bundle + no_log: true + ansible.builtin.copy: + dest: "{{ kayobe_env_config_path }}/kolla/certificates/haproxy-internal.pem" + content: | + {{ internal_cert.data.certificate }} + {{ internal_cert.data.issuing_ca }} + {{ internal_cert.data.private_key }} + mode: "0600" + delegate_to: localhost + + - name: Copy root CA + ansible.builtin.copy: + src: "{{ kayobe_env_config_path }}/openbao/OS-TLS-ROOT.pem" + dest: "{{ kayobe_env_config_path }}/kolla/certificates/ca/openbao.crt" + mode: "0600" + delegate_to: localhost diff --git a/etc/kayobe/ansible/openbao-generate-test-external-tls.yml b/etc/kayobe/ansible/openbao-generate-test-external-tls.yml new file mode 100644 index 000000000..e7150fed1 --- /dev/null +++ b/etc/kayobe/ansible/openbao-generate-test-external-tls.yml @@ -0,0 +1,57 @@ +--- +- name: Generate external API certificate (for testing only) + hosts: controllers + run_once: true + vars: + openbao_api_addr: https://{{ internal_net_name | net_ip }}:8200 + # NOTE: Using the same CA as internal TLS. + openbao_intermediate_ca_name: OS-TLS-INT + tasks: + - name: Include OpenBao keys + ansible.builtin.include_vars: + file: "{{ kayobe_env_config_path }}/openbao/overcloud-openbao-keys.json" + name: openbao_keys + + - name: Issue a certificate for external TLS + hashivault_pki_cert_issue: # noqa: fqcn + url: "{{ openbao_api_addr }}" + 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' }}" + token: "{{ openbao_keys.root_token }}" + mount_point: "{{ openbao_intermediate_ca_name }}" + role: "{{ overcloud_openbao_pki_external_tls_role_name }}" + common_name: "{% if kolla_external_fqdn != kolla_external_vip_address %}{{ kolla_external_fqdn }}{% endif %}" + extra_params: + ip_sans: "{{ kolla_external_vip_address }}" + register: external_cert + environment: + https_proxy: "" + + - name: Ensure certificates directory exists + ansible.builtin.file: + path: "{{ kayobe_env_config_path }}/kolla/certificates" + state: directory + delegate_to: localhost + + - name: Ensure CA certificates directory exists + ansible.builtin.file: + path: "{{ kayobe_env_config_path }}/kolla/certificates/ca" + state: directory + delegate_to: localhost + + - name: Copy external API PEM bundle + no_log: true + ansible.builtin.copy: + dest: "{{ kayobe_env_config_path }}/kolla/certificates/haproxy.pem" + content: | + {{ external_cert.data.certificate }} + {{ external_cert.data.issuing_ca }} + {{ external_cert.data.private_key }} + mode: "0600" + delegate_to: localhost + + - name: Copy root CA + ansible.builtin.copy: + src: "{{ kayobe_env_config_path }}/openbao/OS-TLS-ROOT.pem" + dest: "{{ kayobe_env_config_path }}/kolla/certificates/ca/openbao.crt" + mode: "0600" + delegate_to: localhost diff --git a/etc/kayobe/ansible/openbao-unseal-overcloud.yml b/etc/kayobe/ansible/openbao-unseal-overcloud.yml new file mode 100644 index 000000000..0a631c598 --- /dev/null +++ b/etc/kayobe/ansible/openbao-unseal-overcloud.yml @@ -0,0 +1,37 @@ +--- +- name: Unseal OpenBao on the overcloud + any_errors_fatal: true + gather_facts: true + hosts: controllers + 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: Include OpenBao keys + ansible.builtin.include_vars: + file: "{{ kayobe_env_config_path }}/openbao/overcloud-openbao-keys.json" + name: openbao_keys + + - name: Apply OpenBao unseal role + ansible.builtin.import_role: + name: stackhpc.hashicorp.vault_unseal + vars: + vault_api_addr: https://{{ internal_net_name | net_ip }}:8200 + vault_unseal_token: "{{ openbao_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: "{{ openbao_keys.keys_base64 }}" + environment: + https_proxy: "" diff --git a/etc/kayobe/ansible/openbao-unseal-seed.yml b/etc/kayobe/ansible/openbao-unseal-seed.yml new file mode 100644 index 000000000..82f9b8fa7 --- /dev/null +++ b/etc/kayobe/ansible/openbao-unseal-seed.yml @@ -0,0 +1,34 @@ +--- +- name: Unseal OpenBao on the seed + any_errors_fatal: true + gather_facts: true + hosts: seed + vars: + vault_api_addr: http://127.0.0.1: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 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: Include OpenBao keys + ansible.builtin.include_vars: + file: "{{ kayobe_env_config_path }}/openbao/seed-openbao-keys.json" + name: openbao_keys + + - name: Apply OpenBao unseal role + ansible.builtin.import_role: + name: stackhpc.hashicorp.vault_unseal + vars: + vault_unseal_keys: "{{ openbao_keys.keys_base64 }}" diff --git a/etc/kayobe/ansible/requirements.yml b/etc/kayobe/ansible/requirements.yml index b70528d60..a81decfc1 100644 --- a/etc/kayobe/ansible/requirements.yml +++ b/etc/kayobe/ansible/requirements.yml @@ -9,7 +9,7 @@ collections: - name: stackhpc.pulp version: 0.5.5 - name: stackhpc.hashicorp - version: 2.5.1 + version: 2.6.1 - name: stackhpc.kayobe_workflows version: 1.1.0 roles: diff --git a/etc/kayobe/ansible/vault-deploy-barbican.yml b/etc/kayobe/ansible/vault-deploy-barbican.yml index 0270dc8d0..54f17bb35 100644 --- a/etc/kayobe/ansible/vault-deploy-barbican.yml +++ b/etc/kayobe/ansible/vault-deploy-barbican.yml @@ -30,7 +30,7 @@ https_proxy: "" block: - name: Enable AppRole auth module - hashivault_auth_method: + hashivault_auth_method: # noqa: fqcn url: "{{ vault_api_addr }}" ca_cert: "{{ vault_ca_cert }}" token: "{{ vault_keys.root_token }}" @@ -38,7 +38,7 @@ state: enabled - name: Enable barbican kv store - hashivault_secret_engine: + hashivault_secret_engine: # noqa: fqcn url: "{{ vault_api_addr }}" ca_cert: "{{ vault_ca_cert }}" token: "{{ vault_keys.root_token }}" @@ -47,7 +47,7 @@ description: Barbican kv store - name: Ensure barbican policy is defined - hashivault_policy: + hashivault_policy: # noqa: fqcn url: "{{ vault_api_addr }}" ca_cert: "{{ vault_ca_cert }}" token: "{{ vault_keys.root_token }}" @@ -59,7 +59,7 @@ } - name: Ensure barbican AppRole is defined - hashivault_approle_role: + hashivault_approle_role: # noqa: fqcn url: "{{ vault_api_addr }}" ca_cert: "{{ vault_ca_cert }}" token: "{{ vault_keys.root_token }}" @@ -70,7 +70,7 @@ name: barbican - name: Get barbican Approle ID - hashivault_approle_role_id: + hashivault_approle_role_id: # noqa: fqcn url: "{{ vault_api_addr }}" ca_cert: "{{ vault_ca_cert }}" token: "{{ vault_keys.root_token }}" @@ -89,7 +89,7 @@ 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: + hashivault_approle_role_secret_get: # noqa: fqcn url: "{{ vault_api_addr }}" ca_cert: "{{ vault_ca_cert }}" token: "{{ vault_keys.root_token }}" @@ -98,7 +98,7 @@ register: barbican_approle_secret_get - name: Ensure barbican AppRole Secret ID is defined - hashivault_approle_role_secret: + hashivault_approle_role_secret: # noqa: fqcn url: "{{ vault_api_addr }}" ca_cert: "{{ vault_ca_cert }}" token: "{{ vault_keys.root_token }}" diff --git a/etc/kayobe/ansible/vault-generate-backend-tls.yml b/etc/kayobe/ansible/vault-generate-backend-tls.yml index 71f243c85..32e502fbe 100644 --- a/etc/kayobe/ansible/vault-generate-backend-tls.yml +++ b/etc/kayobe/ansible/vault-generate-backend-tls.yml @@ -43,7 +43,7 @@ name: vault_keys - name: Issue a certificate for backend TLS - hashivault_pki_cert_issue: + hashivault_pki_cert_issue: # noqa: fqcn url: "{{ vault_api_addr }}" 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' }}" token: "{{ vault_keys.root_token }}" diff --git a/etc/kayobe/ansible/vault-generate-internal-tls.yml b/etc/kayobe/ansible/vault-generate-internal-tls.yml index d5d4e6068..a585d1bc9 100644 --- a/etc/kayobe/ansible/vault-generate-internal-tls.yml +++ b/etc/kayobe/ansible/vault-generate-internal-tls.yml @@ -12,7 +12,7 @@ name: vault_keys - name: Issue a certificate for internal TLS - hashivault_pki_cert_issue: + hashivault_pki_cert_issue: # noqa: fqcn url: "{{ vault_api_addr }}" 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' }}" token: "{{ vault_keys.root_token }}" diff --git a/etc/kayobe/ansible/vault-generate-test-external-tls.yml b/etc/kayobe/ansible/vault-generate-test-external-tls.yml index 37841ad0d..de02ddb03 100644 --- a/etc/kayobe/ansible/vault-generate-test-external-tls.yml +++ b/etc/kayobe/ansible/vault-generate-test-external-tls.yml @@ -13,7 +13,7 @@ name: vault_keys - name: Issue a certificate for external TLS - hashivault_pki_cert_issue: + hashivault_pki_cert_issue: # noqa: fqcn url: "{{ vault_api_addr }}" 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' }}" token: "{{ vault_keys.root_token }}" diff --git a/etc/kayobe/inventory/group_vars/all/openbao.yml b/etc/kayobe/inventory/group_vars/all/openbao.yml new file mode 100644 index 000000000..3e084a936 --- /dev/null +++ b/etc/kayobe/inventory/group_vars/all/openbao.yml @@ -0,0 +1,79 @@ +############################################################################### +# Openbao deployment configuration. + +# Registry information for seed. +seed_openbao_registry_url: "{{ stackhpc_docker_registry if stackhpc_sync_openbao_images | bool else '' }}" +seed_openbao_registry_username: "{{ stackhpc_docker_registry_username if stackhpc_sync_openbao_images | bool else '' }}" +seed_openbao_registry_password: "{{ stackhpc_docker_registry_password if stackhpc_sync_openbao_images | bool else '' }}" + +# Seed OpenBao container image. +seed_openbao_docker_image: "{{ stackhpc_docker_registry ~ '/' if stackhpc_sync_openbao_images | bool else '' }}openbao/openbao" + +# Seed OpenBao container image tag. +seed_openbao_docker_tag: "2.2.1" + +# Seed OpenBao PKI Role name +seed_openbao_pki_role_name: "ServerCert" + +# Seed OpenBao PKI Roles definition +seed_openbao_pki_roles: + - name: "{{ seed_openbao_pki_role_name }}" + config: + max_ttl: 8760h + ttl: 8760h + allow_any_name: true + allow_ip_sans: true + require_cn: false + server_flag: true + key_type: rsa + key_bits: 4096 + country: ["UK"] + locality: ["Bristol"] + organization: ["StackHPC"] + ou: ["OpenStack"] + +# Registry information for overcloud. +overcloud_openbao_registry_url: "{{ stackhpc_docker_registry if stackhpc_sync_openbao_images | bool else '' }}" +overcloud_openbao_registry_username: "{{ stackhpc_docker_registry_username if stackhpc_sync_openbao_images | bool else '' }}" +overcloud_openbao_registry_password: "{{ stackhpc_docker_registry_password if stackhpc_sync_openbao_images | bool else '' }}" + +# Overcloud OpenBao container image. +overcloud_openbao_docker_image: "{{ stackhpc_docker_registry ~ '/' if stackhpc_sync_openbao_images | bool else '' }}openbao/openbao" + +# Overcloud OpenBao container image tag. +overcloud_openbao_docker_tag: "2.2.1" + +# Overcloud OpenBao PKI Default Role name +overcloud_openbao_pki_default_role_name: "ServerCert" + +# Overcloud OpenBao PKI Internal TLS Role name +overcloud_openbao_pki_internal_tls_role_name: "{{ overcloud_openbao_pki_default_role_name }}" + +# Overcloud OpenBao PKI Backend TLS Role name +overcloud_openbao_pki_backend_tls_role_name: "{{ overcloud_openbao_pki_default_role_name }}" + +# Overcloud OpenBao PKI External TLS Role name (for testing only) +overcloud_openbao_pki_external_tls_role_name: "{{ overcloud_openbao_pki_default_role_name }}" + +# Overcloud OpenBao PKI Roles definition +overcloud_openbao_pki_roles: + - name: "{{ overcloud_openbao_pki_default_role_name }}" + config: + max_ttl: 8760h + ttl: 8760h + allow_any_name: true + allow_ip_sans: true + require_cn: false + server_flag: true + key_type: rsa + key_bits: 4096 + country: ["UK"] + locality: ["Bristol"] + organization: ["StackHPC"] + ou: ["OpenStack"] + +seed_openbao_pki_certificate_subject: + - common_name: "{% if kolla_internal_fqdn != kolla_internal_vip_address %}{{ kolla_internal_fqdn }}{% else %}overcloud{% endif %}" + role: "{{ seed_openbao_pki_role_name }}" + extra_params: + ip_sans: "{% for host in groups['controllers'] %}{{ internal_net_name | net_ip(host) }}{% if not loop.last %},{% endif %}{% endfor %},{{ kolla_internal_vip_address }}" diff --git a/etc/kayobe/openbao.yml b/etc/kayobe/openbao.yml new file mode 100644 index 000000000..0a545eced --- /dev/null +++ b/etc/kayobe/openbao.yml @@ -0,0 +1,47 @@ +--- +############################################################################### +# OpenBao deployment configuration. + +# Registry information for seed. +# seed_openbao_registry_url: +# seed_openbao_registry_username: +# seed_openbao_registry_password: + +# Seed OpenBao container image. +# seed_openbao_docker_image: + +# Seed OpenBao container image tag. +seed_openbao_docker_tag: 2.2.1 + +# Seed OpenBao PKI Role name +# seed_openbao_pki_role_name: + +# Seed OpenBao PKI Roles definition +# seed_openbao_pki_roles: [] + +# Registry information for overcloud. +# overcloud_openbao_registry_url: +# overcloud_openbao_registry_username: +# overcloud_openbao_registry_password: + +# Overcloud OpenBao container image. +# overcloud_openbao_docker_image: + +# Overcloud OpenBao container image tag. +overcloud_openbao_docker_tag: 2.2.1 + +# Overcloud OpenBao PKI Default Role name +# overcloud_openbao_pki_default_role_name: + +# Overcloud OpenBao PKI Internal TLS Role name +# overcloud_openbao_pki_internal_tls_role_name: + +# Overcloud OpenBao PKI Backend TLS Role name +# overcloud_openbao_pki_backend_tls_role_name: + +# Overcloud OpenBao PKI Roles definition +# overcloud_openbao_pki_roles: [] + +############################################################################### +# Dummy variable to allow Ansible to accept this file. +workaround_ansible_issue_8743: yes diff --git a/etc/kayobe/pulp.yml b/etc/kayobe/pulp.yml index 5b4cd77a3..4a858b948 100644 --- a/etc/kayobe/pulp.yml +++ b/etc/kayobe/pulp.yml @@ -716,6 +716,18 @@ stackhpc_pulp_distribution_container_hashicorp: state: present required: "{{ stackhpc_sync_hashicorp_images | bool }}" +stackhpc_sync_openbao_images: false + +# List of OpenBao container image repositories. +stackhpc_pulp_repository_container_repos_openbao: + - name: "openbao/openbao" + url: "https://registry-1.docker.io" + policy: on_demand + proxy_url: "{{ pulp_proxy_url }}" + state: present + include_tags: "{{ overcloud_vault_docker_tag }}" + required: "{{ stackhpc_sync_openbao_images | bool }}" + # List of extra container image repositories. stackhpc_pulp_repository_container_repos_extra: [] @@ -727,6 +739,7 @@ stackhpc_pulp_repository_container_repos: >- {{ (stackhpc_pulp_repository_container_repos_kolla + stackhpc_pulp_repository_container_repos_ceph + stackhpc_pulp_repository_container_repos_hashicorp + + stackhpc_pulp_repository_container_repos_openbao + stackhpc_pulp_repository_container_repos_extra) | selectattr('required') }} # List of container image distributions. @@ -734,4 +747,5 @@ stackhpc_pulp_distribution_container: >- {{ (stackhpc_pulp_distribution_container_kolla + stackhpc_pulp_distribution_container_ceph + stackhpc_pulp_distribution_container_hashicorp + + stackhpc_pulp_distribution_container_openbao + stackhpc_pulp_distribution_container_extra) | selectattr('required') }} diff --git a/releasenotes/notes/add-openbao-for-tls-698ae3834ed5c67f.yaml b/releasenotes/notes/add-openbao-for-tls-698ae3834ed5c67f.yaml new file mode 100644 index 000000000..c6c760b40 --- /dev/null +++ b/releasenotes/notes/add-openbao-for-tls-698ae3834ed5c67f.yaml @@ -0,0 +1,12 @@ +--- +features: + - | + Add support for deploying ``OpenBao`` across the ``seed`` and ``overcloud`` hosts + for the purpose of internal and backend TLS generation. +deprecations: + - | + Hashicorp Vault for TLS generation is deprecated in favour of OpenBao. + The ``openbao`` role is now used to deploy OpenBao on the seed and overcloud hosts. + New deployments should use OpenBao for TLS generation. + Existing deployments using Hashicorp Vault for TLS generation should be migrated + to OpenBao once migration steps are available.