One of the downsides with having a clustered HashiCorp Vault, like I set up last year, is that each host has to be unsealed individually. Doing this from the command line requires specifying the URL of each host to the vault command, sending each of the 3 keys needed to unseal the vault then moving on to the next one. I made an Ansible playbook to do it with an API call, targeting the hosts from the inventory and reading the keys once as variables to unlock all of the hosts.

The playbook itself is actually really, really simple (so much so, I don’t think it needs any explanation!):

- name: Unseal the vault on all nodes in HA cluster
  hosts: hashicorp_vault_servers
  vars_prompt:
    # Assumes 3 keys needed to unseal - this might not be the case...
    - name: unseal_key_1
      prompt: Enter unseal key 1
      private: true
    - name: unseal_key_2
      prompt: Enter unseal key 2
      private: true
    - name: unseal_key_3
      prompt: Enter unseal key 3
      private: true
  tasks:
    - name: Enter unseal keys
      delegate_to: localhost
      ansible.builtin.uri:
        body:
          key: "{{ item }}"
        body_format: json
        force: true
        method: PUT
        url: "https://{{ ansible_facts.fqdn }}:8200/v1/sys/unseal"
      loop:
       - '{{ unseal_key_1 }}'
       - '{{ unseal_key_2 }}'
       - '{{ unseal_key_3 }}'
      loop_control:
        extended: true
        label: "key {{ ansible_loop.index }}/{{ ansible_loop.length }}"

Only unlocking a subset of hosts, e.g. if one gets rebooted, can be done by passing -l to ansible-playbook to limit the hosts being targetted.

Simple, convenient and so far reliable. I like this playbook and am mildly proud of it!