From f47f085693595ad23b53fc26e45e3c568a1fa63d Mon Sep 17 00:00:00 2001 From: vincent Date: Sun, 29 Oct 2023 15:39:20 +0100 Subject: [PATCH] manage init and unseal --- defaults/main.yml | 24 +++++++++++++-- tasks/init.yml | 68 +++++++++++++++++++++++++++++++++++++++++ tasks/main.yml | 11 ++++++- tasks/unseal.yml | 42 +++++++++++++++++++++++++ templates/config.hcl.j2 | 9 ++++-- 5 files changed, 149 insertions(+), 5 deletions(-) create mode 100644 tasks/init.yml create mode 100644 tasks/unseal.yml diff --git a/defaults/main.yml b/defaults/main.yml index 3ca1cb3..6eed5d8 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,8 +1,28 @@ --- vault_listener_address: 0.0.0.0 +vault_port: 8200 +vault_protocol: "http" +vault_api_addr: "{{ vault_protocol }}://{{ ansible_default_ipv4.address }}:{{ vault_port }}" +vault_tls_disable: true + +vault_raft_group_name: "vault_raft_servers" +vault_raft_cluster_members: | + [ + {% for server in groups[vault_raft_group_name] %} + { + "peer": "{{ server }}", + "api_addr": "{{ hostvars[server]['vault_api_addr'] | + default(vault_protocol + '://' + hostvars[server]['ansible_' + hostvars[server]['ansible_default_ipv4']['interface']]['ipv4']['address'] + ':' + (vault_port|string)) }}" + }, + {% endfor %} + ] # vault backup variable vault_snapshot: false vault_backup_location: /tmp vault_cron_hour: 1 -vault_roleID: '' -vault_secretID: '' +vault_roleid: '' +vault_secretid: '' + + +vault_unseal_keys_dir_output: "~/vaultUnseal" +vault_unseal_token: "" diff --git a/tasks/init.yml b/tasks/init.yml new file mode 100644 index 0000000..3db57f1 --- /dev/null +++ b/tasks/init.yml @@ -0,0 +1,68 @@ +--- +- name: Vault API reachable? + ansible.builtin.uri: + url: "{{ vault_api_addr }}/v1/sys/health" + method: GET +# 200 if initialized, unsealed, and active +# 429 if unsealed and standby +# 472 if data recovery mode replication secondary and active +# 473 if performance standby +# 501 if not initialized +# 503 if sealed +# See: https://www.vaultproject.io/api/system/health.html + status_code: 200, 429, 472, 473, 501, 503 + body_format: json + register: check_result + retries: 6 + until: check_result is succeeded + delay: 10 + changed_when: false + +- name: Debug + ansible.builtin.debug: + var: check_result.status +- name: Create unseal directories + ansible.builtin.file: + path: "{{ vault_unseal_keys_dir_output }}" + state: directory + delegate_to: localhost + become: false + run_once: true + when: check_result.status == 501 + +- name: Initialise Vault operator + ansible.builtin.shell: vault operator init -key-shares=1 -key-threshold=1 -format json + environment: + VAULT_ADDR: "http://127.0.0.1:8200" + register: vault_init_results + run_once: true + when: check_result.status == 501 + +- name: Parse output of vault init + ansible.builtin.set_fact: + vault_init_parsed: "{{ vault_init_results.stdout | from_json }}" + delegate_to: localhost + run_once: true + when: check_result.status == 501 + +- name: Write unseal keys to files + ansible.builtin.copy: + dest: "{{ vault_unseal_keys_dir_output }}/unseal_key_{{ item.0 }}" + content: "{{ item.1 }}" + force: true + with_indexed_items: "{{ vault_init_parsed.unseal_keys_hex }}" + delegate_to: localhost + run_once: true + register: sealkey_set + become: false + when: check_result.status == 501 + +- name: Write root token to file + ansible.builtin.copy: + content: "{{ vault_init_parsed.root_token }}" + dest: "{{ vault_unseal_keys_dir_output }}/rootkey" + force: true + delegate_to: localhost + run_once: true + become: false + when: check_result.status == 501 diff --git a/tasks/main.yml b/tasks/main.yml index 94d6d2c..137c055 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -42,7 +42,6 @@ mode: "0755" - name: Apply config template - notify: restart vault block: - name: Server template ansible.builtin.template: @@ -51,6 +50,12 @@ owner: vault group: vault mode: "0400" + register: vault_config_change + - name: Restart service if change + ansible.builtin.service: + name: '{{ vault_os_service }}' + state: restarted + when: vault_config_change.changed == true - name: Ensure service is started ansible.builtin.systemd: @@ -74,3 +79,7 @@ job: "/opt/vault/vault-backup.sh {{ vault_backup_location }} {{vault_roleID}} {{vault_secretID}}" hour: "{{vault_cron_hour}}" when: vault_snapshot +- name: Import Init + ansible.builtin.import_tasks: init.yml +- name: Import UnSeal + ansible.builtin.import_tasks: unseal.yml diff --git a/tasks/unseal.yml b/tasks/unseal.yml new file mode 100644 index 0000000..f415df3 --- /dev/null +++ b/tasks/unseal.yml @@ -0,0 +1,42 @@ +--- +- name: Vault API reachable? + ansible.builtin.uri: + url: "{{ vault_api_addr }}/v1/sys/health" + method: GET + # 200 if initialized, unsealed, and active + # 429 if unsealed and standby + # 472 if data recovery mode replication secondary and active + # 473 if performance standby + # 501 if not initialized + # 503 if sealed + # See: https://www.vaultproject.io/api/system/health.html + status_code: 200, 429, 472, 473, 501, 503 + body_format: json + register: check_result1 + retries: 6 + until: check_result1 is succeeded + delay: 10 + changed_when: false + +- name: Debug + ansible.builtin.debug: + var: check_result1.status +- name: Reading unseal key contents + ansible.builtin.command: cat {{ item }} + register: unseal_keys + with_fileglob: "{{ vault_unseal_keys_dir_output }}/unseal*" + delegate_to: localhost + when: check_result1.status == 503 +- name: Set_fact if unseal files + ansible.builtin.set_fact: + vault_unseal_token: "{{ item.stdout }}" + with_items: "{{ unseal_keys.results }}" + when: check_result1.status == 503 and unseal_keys.results is defined + +- name: Unseal vault with unseal keys + ansible.builtin.shell: | + vault operator unseal {{ item }} + environment: + VAULT_ADDR: "http://127.0.0.1:8200" + with_items: "{{vault_unseal_token}}" + when: check_result1.status == 503 diff --git a/templates/config.hcl.j2 b/templates/config.hcl.j2 index 4a18105..57cdce7 100644 --- a/templates/config.hcl.j2 +++ b/templates/config.hcl.j2 @@ -2,14 +2,19 @@ storage "raft" { path = "/opt/vault/raft/" node_id = "{{ inventory_hostname }}" +{% for raft_peer in vault_raft_cluster_members | rejectattr('peer', 'equalto', inventory_hostname) %} + retry_join { + leader_api_addr = "{{ raft_peer.api_addr }}" +} +{% endfor %} } listener "tcp" { - address = "{{ vault_listener_address}}:8200" + address = "{{ vault_listener_address}}:{{vault_port}}" cluster_address = "{{ vault_listener_address}}:8201" tls_disable = 1 } -api_addr = "http://{{ vault_listener_address}}:8200" +api_addr = "http://{{ vault_listener_address}}:{{vault_port}}" cluster_addr = "http://{{ ansible_default_ipv4.address }}:8201" ui= true disable_mlock = true