diff --git a/playbooks/group_vars/all/hashistack_ca.yml b/playbooks/group_vars/all/hashistack_ca.yml index 33aa792..bc1e3d2 100644 --- a/playbooks/group_vars/all/hashistack_ca.yml +++ b/playbooks/group_vars/all/hashistack_ca.yml @@ -2,7 +2,7 @@ # defaults hashistack_ca_directory: "{{ hashistack_sub_configuration_directories['certificates'] }}" hashistack_ca_use_cryptography: false -hashistack_ca_action: "noop" +# hashistack_ca_action: "noop" hashistack_ca_domain: example.com hashistack_ca_directory_owner: "{{ lookup('env', 'USER') }}" @@ -79,37 +79,52 @@ hashistack_ca_leaf_renew_threshold: 30d ############################ hashistack_ca_consul_org_name: "{{ hashistack_ca_root_org_name }}" hashistack_ca_consul_common_name: "{{ inventory_hostname }}" -hashistack_ca_consul_csr_sans: - - "DNS:{{ inventory_hostname }}" - - "DNS:consul.service.consul" - - "DNS:localhost" - - "IP:{{ api_interface_address }}" - - "IP:127.0.0.1" - - "{{ 'DNS:server.' ~ consul_datacenter ~ '.' ~ consul_domain if consul_enable_server else omit }}" +hashistack_ca_consul_csr_sans: > + {{ + [ + "DNS:" + inventory_hostname, + "DNS:consul.service.consul", + "DNS:localhost", + "IP:" + api_interface_address, + "IP:127.0.0.1" + ] + + ([ "DNS:server." + consul_datacenter + "." + consul_domain ] if consul_enable_server else []) + }} ########################### # Nomad Leaf Certificates # ########################### hashistack_ca_nomad_org_name: "{{ hashistack_ca_root_org_name }}" hashistack_ca_nomad_common_name: "{{ inventory_hostname }}" -hashistack_ca_nomad_csr_sans: - - "DNS:{{ inventory_hostname }}" - - "DNS:localhost" - - "IP:{{ api_interface_address }}" - - "IP:127.0.0.1" - - "{{ 'DNS:server.' ~ nomad_region ~ '.nomad' if nomad_enable_server else omit }}" - - "{{ 'DNS:nomad.service.consul' if (nomad_enable_server and enable_consul) else omit }}" +hashistack_ca_nomad_csr_sans: > + {{ + [ + "DNS:" + inventory_hostname, + "DNS:localhost", + "IP:" + api_interface_address, + "IP:127.0.0.1" + ] + + ([ "DNS:server." + nomad_region + ".nomad" ] if nomad_enable_server else []) + + ([ "DNS:client." + nomad_region + ".nomad" ] if nomad_enable_client else []) + + ([ "DNS:nomad.service.consul" ] if (nomad_enable_server and enable_consul) else []) + }} ########################### # Vault Leaf Certificates # ########################### hashistack_ca_vault_org_name: "{{ hashistack_ca_root_org_name }}" hashistack_ca_vault_common_name: "{{ inventory_hostname }}" -hashistack_ca_vault_csr_sans: - - "DNS:{{ inventory_hostname }}" - - "{{ 'DNS:active.vault.service.consul' if enable_consul else omit }}" - - "{{ 'DNS:standby.vault.service.consul' if enable_consul else omit }}" - - "{{ 'DNS:vault.service.consul' if enable_consul else omit }}" - - "DNS:localhost" - - "IP:{{ api_interface_address }}" - - "IP:127.0.0.1" +hashistack_ca_vault_csr_sans: > + {{ + [ + "DNS:" + inventory_hostname, + "DNS:localhost", + "IP:" + api_interface_address, + "IP:127.0.0.1" + ] + + ([ + "DNS:active.vault.service.consul", + "DNS:standby.vault.service.consul", + "DNS:vault.service.consul" + ] if enable_consul else []) + }} diff --git a/roles/consul/tasks/configure.yml b/roles/consul/tasks/configure.yml index 6d5d535..7e31ab9 100644 --- a/roles/consul/tasks/configure.yml +++ b/roles/consul/tasks/configure.yml @@ -24,6 +24,31 @@ when: _consul_env_file.changed or _consul_config_file.changed +- name: "Consul | Gather initial checksums for certificate files" + ansible.builtin.stat: + path: "{{ item }}" + checksum_algorithm: sha1 + loop: "{{ consul_certificates_reload_watchlist }}" + when: consul_enable_tls + register: _consul_initial_cert_checksums + +- name: "Consul | Normalize initial checksums" + ansible.builtin.set_fact: + # This needs to be optimized, but I have spent so much time on it not + # working that I will keep it as is for now, and we'll see later. + _consul_initial_checksums_normalized: >- + {% filter trim %} + {% set checksums = [] %} + {% for item in _consul_initial_cert_checksums.results %} + {% set _ = checksums.append({ + 'item': item.item, + 'initial_checksum': (item.stat.checksum | default('absent')) + }) %} + {% endfor %} + {{ checksums }} + {% endfilter %} + when: consul_enable_tls + - name: "Consul | Copy extra configuration files" when: consul_extra_files block: @@ -72,3 +97,44 @@ loop_control: loop_var: dir_source_item when: _consul_dir_sources is defined + +- name: "Consul | Gather final checksums for certificate files" + ansible.builtin.stat: + path: "{{ item }}" + checksum_algorithm: sha1 + loop: "{{ consul_certificates_reload_watchlist }}" + when: consul_enable_tls + register: _consul_final_cert_checksums + +- name: "Consul | Normalize final checksums" + ansible.builtin.set_fact: + # This needs to be optimized, but I have spent so much time on it not + # working that I will keep it as is for now, and we'll see later. + _consul_final_checksums_normalized: >- + {% filter trim %} + {% set checksums = [] %} + {% for item in _consul_final_cert_checksums.results %} + {% set _ = checksums.append({ + 'item': item.item, + 'final_checksum': (item.stat.checksum | default('absent')) + }) %} + {% endfor %} + {{ checksums }} + {% endfilter %} + when: consul_enable_tls + +- name: "Consul | Merge initial and final checksum lists" + ansible.builtin.set_fact: + _consul_checksums_list: >- + {{ + _consul_initial_checksums_normalized | + community.general.lists_mergeby(_consul_final_checksums_normalized, 'item') + }} + when: consul_enable_tls + +- name: "Consul | Determine if certificates have changed or were newly added" + ansible.builtin.set_fact: + _consul_service_need_reload: true + when: + - consul_enable_tls + - _consul_checksums_list | json_query('[?initial_checksum!=final_checksum]') | list| length > 0 diff --git a/roles/consul/tasks/install.yml b/roles/consul/tasks/install.yml index 1d4bd18..1dbcd8e 100644 --- a/roles/consul/tasks/install.yml +++ b/roles/consul/tasks/install.yml @@ -136,6 +136,6 @@ - name: "Consul | Set reload-check & restart-check variable" ansible.builtin.set_fact: - _consul_service_need_reload: true + _consul_service_need_daemon_reload: true _consul_service_need_restart: true when: _consul_unit_file.changed # noqa: no-handler diff --git a/roles/consul/tasks/main.yml b/roles/consul/tasks/main.yml index 98654f2..ddc9138 100644 --- a/roles/consul/tasks/main.yml +++ b/roles/consul/tasks/main.yml @@ -2,6 +2,7 @@ # task/main file for consul - name: "Consul | Set reload-check & restart-check variable" ansible.builtin.set_fact: + _consul_service_need_daemon_reload: false _consul_service_need_reload: false _consul_service_need_restart: false @@ -37,11 +38,23 @@ - name: "Consul | Reload systemd daemon" ansible.builtin.systemd: daemon_reload: true - when: _consul_service_need_reload + when: _consul_service_need_daemon_reload - name: "Consul | Start service: {{ consul_service_name }}" ansible.builtin.service: name: "{{ consul_service_name }}" state: restarted throttle: 1 - when: _consul_service_need_restart + when: + - consul_start_service + - _consul_service_need_restart + +- name: "Consul | Reload service: {{ consul_service_name }}" + ansible.builtin.service: + name: "{{ consul_service_name }}" + state: reloaded + throttle: 1 + when: + - consul_start_service + - _consul_service_need_reload + - not _consul_service_need_restart diff --git a/roles/consul/vars/main.yml b/roles/consul/vars/main.yml index 38cd5b5..b95d841 100644 --- a/roles/consul/vars/main.yml +++ b/roles/consul/vars/main.yml @@ -21,6 +21,19 @@ consul_github_project: hashicorp/consul consul_github_url: https://github.com consul_repository_url: https://releases.hashicorp.com/consul +consul_certificates_reload_watchlist: | + {% filter trim %} + {% set watchlist = [] %} + {% for block, config in (consul_configuration.tls | default({})).items() %} + {% for key in ['ca_file', 'cert_file', 'key_file'] %} + {% if config.get(key) %} + {{ watchlist.append(config[key]) }} + {% endif %} + {% endfor %} + {% endfor %} + {{ watchlist | unique }} + {% endfilter %} + consul_configuration: domain: "{{ consul_domain }}" datacenter: "{{ consul_datacenter }}" diff --git a/roles/hashistack_ca/tasks/main.yml b/roles/hashistack_ca/tasks/main.yml index 00a8b62..1e0f793 100644 --- a/roles/hashistack_ca/tasks/main.yml +++ b/roles/hashistack_ca/tasks/main.yml @@ -45,3 +45,15 @@ when: - hashistack_ca_renew_leaf - "('consul_servers' in group_names) or ('consul_agents' in group_names)" + +- name: "Nomad leaf certificates | Import renew_nomad.yml" + ansible.builtin.include_tasks: renew/renew_nomad.yml + when: + - hashistack_ca_renew_leaf + - "('nomad_servers' in group_names) or ('nomad_clients' in group_names)" + +- name: "Vault leaf certificates | Import renew_vault.yml" + ansible.builtin.include_tasks: renew/renew_vault.yml + when: + - hashistack_ca_renew_leaf + - "'vault_servers' in group_names" diff --git a/roles/nomad/meta/main.yml b/roles/nomad/meta/main.yml index 032b19a..acd6408 100644 --- a/roles/nomad/meta/main.yml +++ b/roles/nomad/meta/main.yml @@ -2,7 +2,7 @@ # meta file for nomad galaxy_info: namespace: "ednz_cloud" - role_name: "hashicorp_nomad" + role_name: "nomad" author: "Bertrand Lanson" description: "Install and configure hashicorp nomad for debian-based distros." license: "license (BSD, MIT)" diff --git a/roles/nomad/tasks/configure.yml b/roles/nomad/tasks/configure.yml index 0af74b2..e817eaa 100644 --- a/roles/nomad/tasks/configure.yml +++ b/roles/nomad/tasks/configure.yml @@ -24,6 +24,31 @@ when: _nomad_env_file.changed or _nomad_config_file.changed +- name: "Nomad | Gather initial checksums for certificate files" + ansible.builtin.stat: + path: "{{ item }}" + checksum_algorithm: sha1 + loop: "{{ nomad_certificates_reload_watchlist }}" + when: nomad_enable_tls + register: _nomad_initial_cert_checksums + +- name: "Nomad | Normalize initial checksums" + ansible.builtin.set_fact: + # This needs to be optimized, but I have spent so much time on it not + # working that I will keep it as is for now, and we'll see later. + _nomad_initial_checksums_normalized: >- + {% filter trim %} + {% set checksums = [] %} + {% for item in _nomad_initial_cert_checksums.results %} + {% set _ = checksums.append({ + 'item': item.item, + 'initial_checksum': (item.stat.checksum | default('absent')) + }) %} + {% endfor %} + {{ checksums }} + {% endfilter %} + when: nomad_enable_tls + - name: "Nomad | Copy extra configuration files" when: nomad_extra_files block: @@ -72,3 +97,44 @@ loop_control: loop_var: dir_source_item when: _nomad_dir_sources is defined + +- name: "Nomad | Gather final checksums for certificate files" + ansible.builtin.stat: + path: "{{ item }}" + checksum_algorithm: sha1 + loop: "{{ nomad_certificates_reload_watchlist }}" + when: nomad_enable_tls + register: _nomad_final_cert_checksums + +- name: "Nomad | Normalize final checksums" + ansible.builtin.set_fact: + # This needs to be optimized, but I have spent so much time on it not + # working that I will keep it as is for now, and we'll see later. + _nomad_final_checksums_normalized: >- + {% filter trim %} + {% set checksums = [] %} + {% for item in _nomad_final_cert_checksums.results %} + {% set _ = checksums.append({ + 'item': item.item, + 'final_checksum': (item.stat.checksum | default('absent')) + }) %} + {% endfor %} + {{ checksums }} + {% endfilter %} + when: nomad_enable_tls + +- name: "Nomad | Merge initial and final checksum lists" + ansible.builtin.set_fact: + _nomad_checksums_list: >- + {{ + _nomad_initial_checksums_normalized | + community.general.lists_mergeby(_nomad_final_checksums_normalized, 'item') + }} + when: nomad_enable_tls + +- name: "Nomad | Determine if certificates have changed or were newly added" + ansible.builtin.set_fact: + _nomad_service_need_reload: true + when: + - nomad_enable_tls + - _nomad_checksums_list | json_query('[?initial_checksum!=final_checksum]') | list| length > 0 diff --git a/roles/nomad/tasks/install.yml b/roles/nomad/tasks/install.yml index 200bcb4..52791a5 100644 --- a/roles/nomad/tasks/install.yml +++ b/roles/nomad/tasks/install.yml @@ -136,6 +136,6 @@ - name: "Nomad | Set reload-check & restart-check variable" ansible.builtin.set_fact: - _nomad_service_need_reload: true + _nomad_service_need_daemon_reload: true _nomad_service_need_restart: true when: _nomad_unit_file.changed # noqa: no-handler diff --git a/roles/nomad/tasks/main.yml b/roles/nomad/tasks/main.yml index 959a953..7e07a82 100644 --- a/roles/nomad/tasks/main.yml +++ b/roles/nomad/tasks/main.yml @@ -2,6 +2,7 @@ # task/main file for nomad - name: "Nomad | Set reload-check & restart-check variable" ansible.builtin.set_fact: + _nomad_service_need_daemon_reload: false _nomad_service_need_reload: false _nomad_service_need_restart: false @@ -33,11 +34,23 @@ - name: "Nomad | Reload systemd daemon" ansible.builtin.systemd: daemon_reload: true - when: _nomad_service_need_reload + when: _nomad_service_need_daemon_reload - name: "Nomad | Start service: {{ nomad_service_name }}" ansible.builtin.service: name: "{{ nomad_service_name }}" state: restarted throttle: 1 - when: _nomad_service_need_restart + when: + - nomad_start_service + - _nomad_service_need_restart + +- name: "Nomad | Reload service: {{ nomad_service_name }}" + ansible.builtin.service: + name: "{{ nomad_service_name }}" + state: reloaded + throttle: 1 + when: + - nomad_start_service + - _nomad_service_need_reload + - not _nomad_service_need_restart diff --git a/roles/nomad/vars/main.yml b/roles/nomad/vars/main.yml index c21ccb5..0674409 100644 --- a/roles/nomad/vars/main.yml +++ b/roles/nomad/vars/main.yml @@ -15,6 +15,18 @@ nomad_github_project: hashicorp/nomad nomad_github_url: https://github.com nomad_repository_url: https://releases.hashicorp.com/nomad +nomad_certificates_reload_watchlist: | + {% filter trim %} + {% set watchlist = [] %} + {% set config = nomad_configuration.get('tls', {}) %} + {% for key in ['ca_file', 'cert_file', 'key_file'] %} + {% if config.get(key) %} + {{ watchlist.append(config[key]) }} + {% endif %} + {% endfor %} + {{ watchlist | unique }} + {% endfilter %} + nomad_configuration: datacenter: "{{ nomad_datacenter }}" region: "{{ nomad_region }}" diff --git a/roles/vault/meta/main.yml b/roles/vault/meta/main.yml index 482d014..a0e8bf4 100644 --- a/roles/vault/meta/main.yml +++ b/roles/vault/meta/main.yml @@ -2,7 +2,7 @@ # meta file for vault galaxy_info: namespace: "ednz_cloud" - role_name: "hashicorp_vault" + role_name: "vault" author: "Bertrand Lanson" description: "Install and configure hashicorp vault for debian-based distros." license: "license (BSD, MIT)" diff --git a/roles/vault/tasks/configure.yml b/roles/vault/tasks/configure.yml index a8fe340..a4f71e0 100644 --- a/roles/vault/tasks/configure.yml +++ b/roles/vault/tasks/configure.yml @@ -24,6 +24,31 @@ when: _vault_env_file.changed or _vault_config_file.changed +- name: "Vault | Gather initial checksums for certificate files" + ansible.builtin.stat: + path: "{{ item }}" + checksum_algorithm: sha1 + loop: "{{ vault_certificates_reload_watchlist }}" + when: vault_enable_tls + register: _vault_initial_cert_checksums + +- name: "Vault | Normalize initial checksums" + ansible.builtin.set_fact: + # This needs to be optimized, but I have spent so much time on it not + # working that I will keep it as is for now, and we'll see later. + _vault_initial_checksums_normalized: >- + {% filter trim %} + {% set checksums = [] %} + {% for item in _vault_initial_cert_checksums.results %} + {% set _ = checksums.append({ + 'item': item.item, + 'initial_checksum': (item.stat.checksum | default('absent')) + }) %} + {% endfor %} + {{ checksums }} + {% endfilter %} + when: vault_enable_tls + - name: "Vault | Copy extra configuration files" when: vault_extra_files block: @@ -72,3 +97,44 @@ loop_control: loop_var: dir_source_item when: _vault_dir_sources is defined + +- name: "Vault | Gather final checksums for certificate files" + ansible.builtin.stat: + path: "{{ item }}" + checksum_algorithm: sha1 + loop: "{{ vault_certificates_reload_watchlist }}" + when: vault_enable_tls + register: _vault_final_cert_checksums + +- name: "Vault | Normalize final checksums" + ansible.builtin.set_fact: + # This needs to be optimized, but I have spent so much time on it not + # working that I will keep it as is for now, and we'll see later. + _vault_final_checksums_normalized: >- + {% filter trim %} + {% set checksums = [] %} + {% for item in _vault_final_cert_checksums.results %} + {% set _ = checksums.append({ + 'item': item.item, + 'final_checksum': (item.stat.checksum | default('absent')) + }) %} + {% endfor %} + {{ checksums }} + {% endfilter %} + when: vault_enable_tls + +- name: "Vault | Merge initial and final checksum lists" + ansible.builtin.set_fact: + _vault_checksums_list: >- + {{ + _vault_initial_checksums_normalized | + community.general.lists_mergeby(_vault_final_checksums_normalized, 'item') + }} + when: vault_enable_tls + +- name: "Vault | Determine if certificates have changed or were newly added" + ansible.builtin.set_fact: + _vault_service_need_reload: true + when: + - vault_enable_tls + - _vault_checksums_list | json_query('[?initial_checksum!=final_checksum]') | list| length > 0 diff --git a/roles/vault/tasks/install.yml b/roles/vault/tasks/install.yml index 0e61b73..0fc88b5 100644 --- a/roles/vault/tasks/install.yml +++ b/roles/vault/tasks/install.yml @@ -137,7 +137,7 @@ - name: "Vault | Set reload-check & restart-check variable" ansible.builtin.set_fact: - _vault_service_need_reload: true + _vault_service_need_daemon_reload: true _vault_service_need_restart: true when: _vault_unit_file.changed # noqa: no-handler diff --git a/roles/vault/tasks/main.yml b/roles/vault/tasks/main.yml index 89aa5ba..aecbb10 100644 --- a/roles/vault/tasks/main.yml +++ b/roles/vault/tasks/main.yml @@ -2,6 +2,7 @@ # task/main file for vault - name: "Vault | Set reload-check & restart-check variable" ansible.builtin.set_fact: + _vault_service_need_daemon_reload: false _vault_service_need_reload: false _vault_service_need_restart: false @@ -33,13 +34,24 @@ - name: "Vault | Reload systemd daemon" ansible.builtin.systemd: daemon_reload: true - when: _vault_service_need_reload + when: _vault_service_need_daemon_reload - name: "Vault | Start service: {{ vault_service_name }}" ansible.builtin.include_tasks: rolling_restart.yml when: + - vault_start_service - _vault_service_need_restart - "hostvars[host_item].inventory_hostname == inventory_hostname" with_items: "{{ ansible_play_batch }}" loop_control: loop_var: host_item + +- name: "Vault | Reload service: {{ vault_service_name }}" + ansible.builtin.service: + name: "{{ vault_service_name }}" + state: reloaded + throttle: 1 + when: + - vault_start_service + - _vault_service_need_reload + - not _vault_service_need_restart diff --git a/roles/vault/vars/main.yml b/roles/vault/vars/main.yml index 4d990f5..be12d70 100644 --- a/roles/vault/vars/main.yml +++ b/roles/vault/vars/main.yml @@ -15,6 +15,22 @@ vault_github_project: hashicorp/vault vault_github_url: https://github.com vault_repository_url: https://releases.hashicorp.com/vault +vault_certificates_reload_watchlist: | + {% filter trim %} + {% set watchlist = [] %} + {% for listener in vault_configuration.listener %} + {% if listener.get('tcp') %} + {% for key in ['tls_key_file', 'tls_cert_file', 'tls_client_ca_file'] %} + {% if listener['tcp'].get(key) %} + {{ watchlist.append(listener['tcp'][key]) }} + {% endif %} + {% endfor %} + {% endif %} + {% endfor %} + {{ watchlist | unique }} + {% endfilter %} + + vault_configuration: cluster_name: "{{ vault_cluster_name }}" cluster_addr: "{{ 'https' if vault_enable_tls else 'http'}}://{{ vault_cluster_addr }}:8201"