diff --git a/roles/vault_unseal/defaults/main.yml b/roles/vault_unseal/defaults/main.yml new file mode 100644 index 0000000..8e3f47f --- /dev/null +++ b/roles/vault_unseal/defaults/main.yml @@ -0,0 +1,75 @@ +--- + +vault_unseal_version: 0.7.2 +vault_unseal_bin_url: https://github.com/lrstanley/vault-unseal/releases/download/v{{ vault_unseal_version }}/vault-unseal_linux_amd64 +vault_unseal_bin_sha256: f6e2ee07a4e10e73b9518a6d45e22ff68797c8a78dbedc7df5789dc279b60284 +vault_unseal_root_dir: /opt/vault_unseal +vault_unseal_user: vault-unseal + +vault_unseal_base_conf: + # named environment that vault-unseal is running in, gets passed in when sending + # email alerts. + environment: dev + + # delay between seal-checks of each vault node. + check_interval: 15s + + # maximum delay between checks of each vault node. when an error occurs, we will + # add a backoff delay, up to this maximum. + max_check_interval: 30m + + # list of vault nodes to check, must include http/https, and a port (unless 80/443). + vault_nodes: [] + + # unseal tokens necessary to unseal any of the given vaults in the above node + # list. + # + # WARNING: do not put enough tokens in this list that can be used to unseal a + # vault instance. I.e. if vault requires 3 of 5 tokens, DO NOT PUT 3 TOKENS HERE. + # the goal is to put less than the required amount, but have more instances of + # vault-unseal setup with the other missing tokens from the list. this ensures + # that if the server was compromised, they don't have all of the needed tokens. + # + # i.e. 1 instance of vault-unseal on each of the three nodes, each with two + # tokens. given A, B, and C tokens required, each instance should have the + # following tokens: + # * 1: AB + # * 2: BC + # * 3: AC + unseal_tokens: [] + + # skip tls checks for the given vault instance. useful if your instance doesn't + # have a certificate which has all of the server hostnames on it. + tls_skip_verify: false + + # email notifications. setting this to false will disable all notifications. + email: + enabled: false + hostname: 127.0.0.1 + port: 25 + # username: your-username + # password: your-password + # address to send from. + from_addr: vault-unseal-{{ ansible_hostname }}@{{ ansible_domain }} + # addresses to send to. the first will be the TO, the second and on will be CC'd + # onto the message. + send_addrs: + - "{{ system_admin_email }}" + # Skip TLS certificate validation. + # tls_skip_verify: false + # Require TLS for SMTP connections. + # The default is opportunistic. + # mandatory_tls: false + + # notifications in vault-unseal queue up to prevent email spam (e.g. 20 alerts + # in one email). this is the max allotted time an event can be queued before + # the queue is sent as a notification. + notify_max_elapsed: 10m + + # queue delay is the amount of time vault-unseal waits after the last received + # notification, before it sends all of them in bulk. + notify_queue_delay: 60s + +vault_unseal_extra_conf: {} +vault_unseal_host_conf: {} +vault_unseal_conf: "{{ vault_unseal_base_conf | combine(vault_unseal_extra_conf, recursive=True) | combine(vault_unseal_host_conf, recursive=True) }}" diff --git a/roles/vault_unseal/handlers/main.yml b/roles/vault_unseal/handlers/main.yml new file mode 100644 index 0000000..3596a2a --- /dev/null +++ b/roles/vault_unseal/handlers/main.yml @@ -0,0 +1,4 @@ +--- + +- name: restart vault-unseal + service: name=vault-unseal state={{ vault_unseal_enabled | ternary('restarted', 'stopped') }} diff --git a/roles/vault_unseal/tasks/conf.yml b/roles/vault_unseal/tasks/conf.yml new file mode 100644 index 0000000..cd434d5 --- /dev/null +++ b/roles/vault_unseal/tasks/conf.yml @@ -0,0 +1,6 @@ +--- + +- name: Deploy vault-unseal configuration + template: src=vault-unseal.yaml.j2 dest=/etc/vault-unseal.yaml owner=root group={{ vault_unseal_user }} mode=440 + notify: restart vault-unseal + tags: vault diff --git a/roles/vault_unseal/tasks/facts.yml b/roles/vault_unseal/tasks/facts.yml new file mode 100644 index 0000000..5f5eb3a --- /dev/null +++ b/roles/vault_unseal/tasks/facts.yml @@ -0,0 +1,38 @@ +--- + +- set_fact: + vault_unseal_install_mode: 'none' + tags: vault + +- name: Detect if vault_unseal is installed + stat: path=/usr/local/bin/vault_unseal + register: vault_unseal_bin + tags: vault + +- when: not vault_unseal_bin.stat.exists + set_fact: vault_unseal_install_mode='install' + tags: vault + +- when: vault_unseal_bin.stat.exists + block: + - name: Detect installed version + shell: | + /usr/local/bin/vault_unseal -v | perl -pe 's/vault-unseal version: (\d+(\.\d+)*).*/$1/' + changed_when: False + register: vault_unseal_current_version + - set_fact: + vault_current_version: "{{ vault_unseal_current_version.stdout }}" + tags: vault + +- when: vault_unseal_bin.stat.exists and vault_unseal_current_version != vault_unseal_version + set_fact: vault_unseal_install_mode='upgrade' + tags: vault + +- debug: msg={{ vault_unseal_conf }} + tags: vault + +- debug: msg={{ vault_unseal_conf.vault_nodes }} + tags: vault + +- set_fact: vault_unseal_enabled={{ (vault_unseal_conf.vault_nodes | length > 0 and vault_unseal_conf.unseal_tokens | length > 0) | ternary(true, false) }} + tags: vault diff --git a/roles/vault_unseal/tasks/install.yml b/roles/vault_unseal/tasks/install.yml new file mode 100644 index 0000000..f3f0a8d --- /dev/null +++ b/roles/vault_unseal/tasks/install.yml @@ -0,0 +1,17 @@ +--- + +- name: Download vault-unseal + get_url: + url: "{{ vault_unseal_bin_url }}" + dest: /usr/local/bin/vault-unseal + checksum: sha256:{{ vault_unseal_bin_sha256 }} + owner: root + group: root + mode: 755 + when: vault_unseal_install_mode != 'none' + tags: vault + +- name: Deploy systemd unit + template: src=vault-unseal.service.j2 dest=/etc/systemd/system/vault-unseal.service + notify: restart vault-unseal + tags: vault diff --git a/roles/vault_unseal/tasks/main.yml b/roles/vault_unseal/tasks/main.yml new file mode 100644 index 0000000..9e4ef27 --- /dev/null +++ b/roles/vault_unseal/tasks/main.yml @@ -0,0 +1,16 @@ +--- + +- include_tasks: user.yml + tags: always + +- include_tasks: facts.yml + tags: always + +- include_tasks: install.yml + tags: always + +- include_tasks: conf.yml + tags: always + +- include_tasks: service.yml + tags: always diff --git a/roles/vault_unseal/tasks/service.yml b/roles/vault_unseal/tasks/service.yml new file mode 100644 index 0000000..04015d3 --- /dev/null +++ b/roles/vault_unseal/tasks/service.yml @@ -0,0 +1,5 @@ +--- + +- name: Handle vault-unseal service + service: name=vault-unseal state={{ vault_unseal_enabled | ternary('started', 'stopped') }} enabled={{ vault_unseal_enabled }} + tags: vault diff --git a/roles/vault_unseal/tasks/user.yml b/roles/vault_unseal/tasks/user.yml new file mode 100644 index 0000000..243b4c4 --- /dev/null +++ b/roles/vault_unseal/tasks/user.yml @@ -0,0 +1,9 @@ +--- + +- name: Create vault-unseal user + user: + name: "{{ vault_unseal_user }}" + home: "{{ vault_unseal_root_dir }}" + system: true + shell: /sbin/nologin + tags: vault diff --git a/roles/vault_unseal/templates/vault-unseal.service.j2 b/roles/vault_unseal/templates/vault-unseal.service.j2 new file mode 100644 index 0000000..64a8996 --- /dev/null +++ b/roles/vault_unseal/templates/vault-unseal.service.j2 @@ -0,0 +1,24 @@ +[Unit] +Description=Vault unsealing utility +Documentation=https://github.com/lrstanley/vault-unseal +Wants=network-online.target +After=network-online.target + +[Service] +User=vault-unseal +Group=vault-unseal +ExecStart=/usr/local/bin/vault-unseal --config /etc/vault-unseal.yaml +Restart=always +RestartSec=10 +StartLimitInterval=0 +TimeoutStopSec=10s +KillMode=mixed +KillSignal=SIGQUIT + +PrivateDevices=true +ProtectHome=true +ProtectSystem=full +PrivateTmp=true + +[Install] +WantedBy=multi-user.target diff --git a/roles/vault_unseal/templates/vault-unseal.yaml.j2 b/roles/vault_unseal/templates/vault-unseal.yaml.j2 new file mode 100644 index 0000000..f759d26 --- /dev/null +++ b/roles/vault_unseal/templates/vault-unseal.yaml.j2 @@ -0,0 +1 @@ +{{ vault_unseal_conf | to_nice_yaml }}