diff --git a/vault/config.sls b/vault/config.sls new file mode 100644 index 0000000..b93b78a --- /dev/null +++ b/vault/config.sls @@ -0,0 +1,16 @@ +{%- from slspath + '/map.jinja' import vault with context -%} + +vault-config: + file.managed: + - name: /etc/vault.d/config.hcl + - source: salt://vault/files/config.hcl + - template: jinja + - user: {{ vault.user }} + - group: {{ vault.group }} + - mode: 0640 + - require: + - user: vault-user + {%- if vault.service %} + - watch_in: + - service: vault + {%- endif %} diff --git a/vault/defaults.yaml b/vault/defaults.yaml index 96f5d82..6c2eb34 100644 --- a/vault/defaults.yaml +++ b/vault/defaults.yaml @@ -1,51 +1,23 @@ vault: version: 0.10.1 - listen_protocol: tcp - listen_port: 8200 - listen_address: 0.0.0.0 - tls_disable: 0 - tls_cert_file: {} - tls_key_file: {} - default_lease_ttl: 24h - max_lease_ttl: 24h - self_signed_cert: - enabled: false - backend: {} - dev_mode: true - secure_download: true - service: - type: systemd - user: root - group: root - hashicorp_gpg_key: | - -----BEGIN PGP PUBLIC KEY BLOCK----- - Version: GnuPG v1 + download_host: releases.hashicorp.com - mQENBFMORM0BCADBRyKO1MhCirazOSVwcfTr1xUxjPvfxD3hjUwHtjsOy/bT6p9f - W2mRPfwnq2JB5As+paL3UGDsSRDnK9KAxQb0NNF4+eVhr/EJ18s3wwXXDMjpIifq - fIm2WyH3G+aRLTLPIpscUNKDyxFOUbsmgXAmJ46Re1fn8uKxKRHbfa39aeuEYWFA - 3drdL1WoUngvED7f+RnKBK2G6ZEpO+LDovQk19xGjiMTtPJrjMjZJ3QXqPvx5wca - KSZLr4lMTuoTI/ZXyZy5bD4tShiZz6KcyX27cD70q2iRcEZ0poLKHyEIDAi3TM5k - SwbbWBFd5RNPOR0qzrb/0p9ksKK48IIfH2FvABEBAAG0K0hhc2hpQ29ycCBTZWN1 - cml0eSA8c2VjdXJpdHlAaGFzaGljb3JwLmNvbT6JATgEEwECACIFAlMORM0CGwMG - CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEFGFLYc0j/xMyWIIAIPhcVqiQ59n - Jc07gjUX0SWBJAxEG1lKxfzS4Xp+57h2xxTpdotGQ1fZwsihaIqow337YHQI3q0i - SqV534Ms+j/tU7X8sq11xFJIeEVG8PASRCwmryUwghFKPlHETQ8jJ+Y8+1asRydi - psP3B/5Mjhqv/uOK+Vy3zAyIpyDOMtIpOVfjSpCplVRdtSTFWBu9Em7j5I2HMn1w - sJZnJgXKpybpibGiiTtmnFLOwibmprSu04rsnP4ncdC2XRD4wIjoyA+4PKgX3sCO - klEzKryWYBmLkJOMDdo52LttP3279s7XrkLEE7ia0fXa2c12EQ0f0DQ1tGUvyVEW - WmJVccm5bq25AQ0EUw5EzQEIANaPUY04/g7AmYkOMjaCZ6iTp9hB5Rsj/4ee/ln9 - wArzRO9+3eejLWh53FoN1rO+su7tiXJA5YAzVy6tuolrqjM8DBztPxdLBbEi4V+j - 2tK0dATdBQBHEh3OJApO2UBtcjaZBT31zrG9K55D+CrcgIVEHAKY8Cb4kLBkb5wM - skn+DrASKU0BNIV1qRsxfiUdQHZfSqtp004nrql1lbFMLFEuiY8FZrkkQ9qduixo - mTT6f34/oiY+Jam3zCK7RDN/OjuWheIPGj/Qbx9JuNiwgX6yRj7OE1tjUx6d8g9y - 0H1fmLJbb3WZZbuuGFnK6qrE3bGeY8+AWaJAZ37wpWh1p0cAEQEAAYkBHwQYAQIA - CQUCUw5EzQIbDAAKCRBRhS2HNI/8TJntCAClU7TOO/X053eKF1jqNW4A1qpxctVc - z8eTcY8Om5O4f6a/rfxfNFKn9Qyja/OG1xWNobETy7MiMXYjaa8uUx5iFy6kMVaP - 0BXJ59NLZjMARGw6lVTYDTIvzqqqwLxgliSDfSnqUhubGwvykANPO+93BBx89MRG - unNoYGXtPlhNFrAsB1VR8+EyKLv2HQtGCPSFBhrjuzH3gxGibNDDdFQLxxuJWepJ - EK1UbTS4ms0NgZ2Uknqn1WRU1Ki7rE4sTy68iZtWpKQXZEJa0IGnuI2sSINGcXCJ - oEIgXTMyCILo34Fa/C6VCm2WBgz9zZO8/rHIiQm1J5zqz0DrDwKBUM9C - =LYpS - -----END PGP PUBLIC KEY BLOCK----- - hashicorp_key_id: 51852D87348FFC4C + service: false + + user: vault + group: vault + + config: + data_dir: /var/lib/vault + listen_protocol: tcp + listen_port: 8200 + listen_address: 0.0.0.0 + tls_disable: 0 + tls_cert_file: '' + tls_key_file: '' + default_lease_ttl: 24h + max_lease_ttl: 24h + self_signed_cert: + enabled: false + backend: {} + dev_mode: false diff --git a/vault/files/config.hcl b/vault/files/config.hcl new file mode 100644 index 0000000..94c0058 --- /dev/null +++ b/vault/files/config.hcl @@ -0,0 +1,37 @@ +{%- from "vault/map.jinja" import vault with context -%} + +listener "{{ vault.config.listen_protocol }}" { + address = "{{ vault.config.listen_address }}:{{ vault.config.listen_port }}" + tls_disable = {{ vault.config.tls_disable }} +{%- if vault.config.self_signed_cert.enabled %} + tls_cert_file = "/etc/vault/{{ vault.config.self_signed_cert.hostname }}.pem" + tls_key_file = "/etc/vault/{{ vault.config.self_signed_cert.hostname }}-nopass.key" +{% else -%} +{%- if vault.tls_cert_file %} + tls_cert_file = "{{ vault.config.tls_cert_file }}" +{% endif -%} +{%- if vault.tls_key_file %} + tls_key_file = "{{ vault.config.tls_key_file }}" +{% endif -%} +{% endif %} +} + +{%- if vault.config.backend and vault.config.backend.type == "s3" %} +backend "s3" { + bucket = "{{ vault.config.backend.bucket }}" +} +{% endif -%} + +{%- if vault.config.storage and vault.config.storage.type == "consul" %} +storage "consul" { + address = "{{ vault.config.storage.address }}" + path = "{{ vault.config.storage.path }}" +} +{%- else %} +storage "file" { + path = "{{ vault.config.data_dir }}" +} +{% endif -%} + +default_lease_ttl="{{ vault.config.default_lease_ttl }}" +max_lease_ttl="{{ vault.config.max_lease_ttl }}" diff --git a/vault/files/config.hcl.jinja b/vault/files/config.hcl.jinja deleted file mode 100644 index ff30c85..0000000 --- a/vault/files/config.hcl.jinja +++ /dev/null @@ -1,31 +0,0 @@ -{%- from "vault/map.jinja" import vault with context -%} -{%- if vault.backend and vault.backend.type == "s3" %} -backend "s3" { - bucket = "{{ vault.backend.bucket }}" -} -{% endif -%} -{%- if vault.storage and vault.storage.type == "consul" %} -storage "consul" { - address = "{{ vault.storage.address }}" - path = "{{ vault.storage.path }}" -} -{% endif -%} - -listener "{{ vault.listen_protocol }}" { - address = "{{ vault.listen_address }}:{{ vault.listen_port }}" - tls_disable = {{ vault.tls_disable }} -{% if vault.self_signed_cert.enabled %} - tls_cert_file = "/etc/vault/{{ vault.self_signed_cert.hostname }}.pem" - tls_key_file = "/etc/vault/{{ vault.self_signed_cert.hostname }}-nopass.key" -{% else %} -{%- if vault.tls_cert_file %} - tls_cert_file = "{{ vault.tls_cert_file }}" -{% endif -%} -{%- if vault.tls_key_file %} - tls_key_file = "{{ vault.tls_key_file }}" -{% endif -%} -{% endif %} -} - -default_lease_ttl="{{ vault.default_lease_ttl }}" -max_lease_ttl="{{ vault.max_lease_ttl }}" diff --git a/vault/files/vault_systemd.service.jinja b/vault/files/vault.service similarity index 100% rename from vault/files/vault_systemd.service.jinja rename to vault/files/vault.service diff --git a/vault/files/vault.sysvinit b/vault/files/vault.sysvinit new file mode 100644 index 0000000..f2ae5f4 --- /dev/null +++ b/vault/files/vault.sysvinit @@ -0,0 +1,196 @@ +#!/bin/bash +# +# vault Manage the vault agent +# +# chkconfig: 2345 95 95 +# description: Vault is a tool for service discovery and configuration +# processname: vault +# config: /etc/vault.conf +# pidfile: /var/run/vault.pid + +### BEGIN INIT INFO +# Provides: vault +# Required-Start: $local_fs $network +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Manage the vault agent +# Description: Vault is a tool for service discovery and configuration +### END INIT INFO + +# source function library +. /etc/rc.d/init.d/functions + +prog="vault" +exec="/usr/local/bin/$prog" +pidfile="/var/run/$prog.pid" +lockfile="/var/lock/subsys/$prog" +logfile="/var/log/$prog" +confdir="/etc/vault.d" + +# pull in sysconfig settings +[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog + +user=${VAULT_USER:-vault} +group=${VAULT_GROUP:-vault} + +export GOMAXPROCS=${GOMAXPROCS:-2} + +start() { + [ -x $exec ] || exit 5 + + [ -d $confdir ] || exit 6 + + umask 077 + + touch $logfile $pidfile + chown "$user:$group" $logfile $pidfile + + echo -n $"Starting $prog: " + + ## holy shell shenanigans, batman! + ## daemon can't be backgrounded. we need the pid of the spawned process, + ## which is actually done via runuser thanks to --user. + ## you can't do "cmd &; action" but you can do "{cmd &}; action". + ## vault 0.2.1 added -pid-file; although the following creates $pidfile + ## owned by vault:vault, using -pid-file results in a permission error. + daemon \ + --pidfile=$pidfile \ + --user="$user" \ + " { $exec agent -config=$confdir/config.hcl &>> $logfile & } ; echo \$! >| $pidfile " + + RETVAL=$? + echo + + [ $RETVAL -eq 0 ] && touch $lockfile + + echo -n $"Waiting for Vault ready: " + + ## wait up to 60s for the rpc port to become listened-upon + ## vault 0.2.1 got much slower to start! + count=0 + ready=0 + pid=$( cat ${pidfile} ) + while checkpid ${pid} && [ $count -lt 60 ] && [ $ready -ne 1 ]; do + count=$(( count + 1 )) + + if netstat -lptn | egrep -q ":8400.*LISTEN +${pid}/" ; then + ready=1 + else + sleep 1 + fi + done + + if [ $ready -eq 1 ]; then + RETVAL=0 + success + else + RETVAL=1 + failure + fi + + echo + return $RETVAL +} + +stop() { + echo -n $"Shutting down $prog: " + + ## graceful shutdown with leave + $exec leave &> /dev/null + RETVAL=$? + + ## wait up to 10s for the daemon to exit + if [ $RETVAL -eq 0 ]; then + count=0 + stopped=0 + pid=$( cat ${pidfile} ) + while [ $count -lt 10 ] && [ $stopped -ne 1 ]; do + count=$(( count + 1 )) + + if ! checkpid ${pid} ; then + stopped=1 + else + sleep 1 + fi + done + + if [ $stopped -ne 1 ]; then + RETVAL=125 + fi + fi + + if [ $RETVAL -eq 0 ]; then + success + rm -f $lockfile $pidfile + else + failure + fi + + echo + return $RETVAL +} + +restart() { + stop + start +} + +reload() { + echo -n $"Reloading $prog: " + killproc -p $pidfile $exec -HUP + echo +} + +force_reload() { + restart +} + +rh_status() { + status -p "$pidfile" -l $prog $exec + + RETVAL=$? + + [ $RETVAL -eq 0 ] && $exec members + + return $RETVAL +} + +rh_status_q() { + rh_status >/dev/null 2>&1 +} + +case "$1" in + start) + rh_status_q && exit 0 + $1 + ;; + stop) + rh_status_q || exit 0 + $1 + ;; + restart) + $1 + ;; + reload) + rh_status_q || exit 7 + $1 + ;; + force-reload) + force_reload + ;; + status) + rh_status + ;; + condrestart|try-restart) + rh_status_q || exit 0 + restart + ;; + *) + echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}" + exit 2 +esac + +exit $? diff --git a/vault/files/vault_upstart.conf.jinja b/vault/files/vault.upstart similarity index 100% rename from vault/files/vault_upstart.conf.jinja rename to vault/files/vault.upstart diff --git a/vault/init.sls b/vault/init.sls index 968622c..e703be3 100644 --- a/vault/init.sls +++ b/vault/init.sls @@ -1,78 +1,6 @@ -{% from "vault/map.jinja" import vault with context %} -# using archive.extracted causes: 'Comment: Failed to cache https://releases.hashicorp.com/vault/0.7.0/vault_0.7.0_linux_amd64.zip: [Errno 1] _ssl.c:493: error:1409442E:SSL routines:SSL3_READ_BYTES:tlsv1 alert protocol version' -vault packages: - pkg.installed: - - names: - - unzip - - curl - {% if vault.secure_download %} - {% if grains['os'] == 'CentOS' or grains['os'] == 'Amazon' %} - - gnupg2 - - perl-Digest-SHA - {% elif grains['os'] == 'Ubuntu' %} - - gnupg - - libdigest-sha-perl - {% endif %} - {% endif %} +{%- from slspath + "/map.jinja" import vault with context -%} -download vault: - cmd.run: - - name: curl --silent -L https://releases.hashicorp.com/vault/{{ vault.version }}/vault_{{ vault.version }}_linux_amd64.zip -o /tmp/vault_{{ vault.version }}_linux_amd64.zip - - creates: /tmp/vault_{{ vault.version }}_linux_amd64.zip - -{% if vault.secure_download %} -download shasums: - cmd.run: - - name: curl --silent -L https://releases.hashicorp.com/vault/{{ vault.version }}/vault_{{ vault.version }}_SHA256SUMS -o /tmp/vault_{{ vault.version }}_SHA256SUMS - - creates: /tmp/vault_{{ vault.version }}_SHA256SUMS - -download shasums sig: - cmd.run: - - name: curl --silent -L https://releases.hashicorp.com/vault/{{ vault.version }}/vault_{{ vault.version }}_SHA256SUMS.sig -o /tmp/vault_{{ vault.version }}_SHA256SUMS.sig - - creates: /tmp/vault_{{ vault.version }}_SHA256SUMS.sig - -/tmp/hashicorp.asc: - file.managed: - - source: salt://vault/files/hashicorp.asc.jinja - - template: jinja - -import key: - cmd.run: - - name: gpg --import /tmp/hashicorp.asc - - unless: gpg --list-keys {{ vault.hashicorp_key_id }} - - requires: - - file: /tmp/hashicorp.asc - - cmd: vault packages - -verify shasums sig: - cmd.run: - - name: gpg --verify /tmp/vault_{{ vault.version }}_SHA256SUMS.sig /tmp/vault_{{ vault.version }}_SHA256SUMS - - require: - - cmd: download shasums - - cmd: import key - -verify vault: - cmd.run: - - name: "shasum -a 256 -c vault_{{ vault.version }}_SHA256SUMS 2>&1 | grep -q \"vault_{{ vault.version }}_linux_amd64.zip: OK\"" - - cwd: /tmp - - require: - - cmd: download vault - - cmd: verify shasums sig -{% endif %} - -install vault: - cmd.run: - - name: unzip /tmp/vault_{{ vault.version }}_linux_amd64.zip -d /usr/local/bin && chmod 0755 /usr/local/bin/vault && chown root:root /usr/local/bin/vault - - require: - - cmd: download vault - - pkg: unzip - {% if vault.secure_download %} - - cmd: verify vault - {% endif %} - - creates: /usr/local/bin/vault - -vault set cap mlock: - cmd.run: - - name: "setcap cap_ipc_lock=+ep /usr/local/bin/vault" - - onchanges: - - cmd: install vault +include: + - {{ slspath }}.install + - {{ slspath }}.config + - {{ slspath }}.service diff --git a/vault/install.sls b/vault/install.sls new file mode 100644 index 0000000..e654a74 --- /dev/null +++ b/vault/install.sls @@ -0,0 +1,84 @@ +{%- from slspath + '/map.jinja' import vault with context -%} + +vault-dep-unzp: + pkg.installed: + - name: unzip + +vault-bin-dir: + file.directory: + - name: /usr/local/bin + - makedirs: True + +# Create vault user +vault-group: + group.present: + - name: {{ vault.group }} + +vault-user: + user.present: + - name: {{ vault.user }} + - groups: + - {{ vault.group }} + - home: {{ salt['user.info'](vault.user)['home']|default(vault.config.data_dir) }} + - createhome: False + - system: True + - require: + - group: vault-group + +# Create directories +vault-config-dir: + file.directory: + - name: /etc/vault.d + - user: {{ vault.user }} + - group: {{ vault.group }} + - mode: 0750 + +vault-data-dir: + file.directory: + - name: {{ vault.config.data_dir }} + - makedirs: True + - user: {{ vault.user }} + - group: {{ vault.group }} + - mode: 0750 + +# Install agent +vault-download: + file.managed: + - name: /tmp/vault_{{ vault.version }}_linux_{{ vault.arch }}.zip + - source: https://{{ vault.download_host }}/vault/{{ vault.version }}/vault_{{ vault.version }}_linux_{{ vault.arch }}.zip + - source_hash: https://releases.hashicorp.com/vault/{{ vault.version }}/vault_{{ vault.version }}_SHA256SUMS + - unless: test -f /usr/local/bin/vault-{{ vault.version }} + +vault-extract: + cmd.wait: + - name: unzip /tmp/vault_{{ vault.version }}_linux_{{ vault.arch }}.zip -d /tmp + - watch: + - file: vault-download + +vault-install: + file.rename: + - name: /usr/local/bin/vault-{{ vault.version }} + - source: /tmp/vault + - require: + - file: /usr/local/bin + - watch: + - cmd: vault-extract + +vault-clean: + file.absent: + - name: /tmp/vault_{{ vault.version }}_linux_{{ vault.arch }}.zip + - watch: + - file: vault-install + +vault-link: + file.symlink: + - target: vault-{{ vault.version }} + - name: /usr/local/bin/vault + - watch: + - file: vault-install + +vault-set-cap-mlock: + cmd.run: + - name: "setcap cap_ipc_lock=+ep /usr/local/bin/vault-{{ vault.version }}" + - onchanges: + - file: vault-install diff --git a/vault/map.jinja b/vault/map.jinja index 3c3da4f..66a103c 100644 --- a/vault/map.jinja +++ b/vault/map.jinja @@ -1,2 +1,19 @@ -{% import_yaml "vault/defaults.yaml" as defaults %} -{% set vault = salt['pillar.get']('vault', default=defaults['vault'], merge=True) %} +{% import_yaml slspath+"/defaults.yaml" as defaults %} + +{% set vault = salt['pillar.get']('vault', default=defaults.vault, merge=True) %} + +{## Add any overrides based on CPU architecture. ##} +{% set vault = salt['grains.filter_by']({ + 'armv6l': { + "arch": 'arm' + }, + 'armv7l': { + "arch": 'arm' + }, + 'x86_64': { + "arch": 'amd64' + } + } + ,grain="cpuarch" + ,merge=vault) +%} diff --git a/vault/server.sls b/vault/server.sls deleted file mode 100644 index 02fdd5f..0000000 --- a/vault/server.sls +++ /dev/null @@ -1,68 +0,0 @@ -{% from "vault/map.jinja" import vault with context %} -{%- if vault.self_signed_cert.enabled %} -/usr/local/bin/self-cert-gen.sh: - file.managed: - - source: salt://vault/files/cert-gen.sh.jinja - - template: jinja - - user: root - - group: root - - mode: 644 - -generate self signed SSL certs: - cmd.run: - - name: bash /usr/local/bin/cert-gen.sh {{ vault.self_signed_cert.hostname }} {{ vault.self_signed_cert.password }} - - cwd: /etc/vault - - require: - - file: /usr/local/bin/self-cert-gen.sh -{% endif -%} - -/etc/vault.d: - file.directory: - - user: root - - group: root - - mode: 755 - -/etc/vault.d/config.hcl: - file.managed: - - source: salt://vault/files/config.hcl.jinja - - template: jinja - - user: root - - group: root - - mode: 644 - - require: - - file: /etc/vault.d - -{%- if vault.service.type == 'systemd' %} -/etc/systemd/system/vault.service: - file.managed: - - source: salt://vault/files/vault_systemd.service.jinja - - template: jinja - - user: root - - group: root - - mode: 644 - - require_in: - - service: vault - -{% elif vault.service.type == 'upstart' %} -/etc/init/vault.conf: - file.managed: - - source: salt://vault/files/vault_upstart.conf.jinja - - template: jinja - - user: root - - group: root - - require_in: - - service: vault -{% endif -%} - -vault: - service.running: - - enable: True - - require: - {%- if vault.self_signed_cert.enabled %} - - cmd: generate self signed SSL certs - {% endif %} - - file: /etc/vault.d/config.hcl - - cmd: install vault - - onchanges: - - cmd: install vault - - file: /etc/vault.d/config.hcl diff --git a/vault/service.sls b/vault/service.sls new file mode 100644 index 0000000..b8e1568 --- /dev/null +++ b/vault/service.sls @@ -0,0 +1,66 @@ +{%- from slspath + '/map.jinja' import vault with context -%} + +{%- if vault.self_signed_cert.enabled %} +self-cert-gen-script: + file.managed: + - name: /usr/local/bin/self-cert-gen.sh + - source: salt://vault/files/cert-gen.sh.jinja + - template: jinja + - user: root + - group: root + - mode: 644 + +generate-self-signed-SSL-certs: + cmd.run: + - name: bash /usr/local/bin/cert-gen.sh {{ vault.self_signed_cert.hostname }} {{ vault.self_signed_cert.password }} + - cwd: /etc/vault + - require: + - file: self-cert-gen-script +{% endif -%} + +vault-init-env: + file.managed: + {%- if grains['os_family'] == 'Debian' %} + - name: /etc/default/vault + {%- else %} + - name: /etc/sysconfig/vault + - makedirs: True + {%- endif %} + - user: root + - group: root + - mode: 0644 + - contents: + - VAULT_USER={{ vault.user }} + - VAULT_GROUP={{ vault.group }} + +vault-init-file: + file.managed: + {%- if salt['test.provider']('service') == 'systemd' %} + - source: salt://{{ slspath }}/files/vault.service + - name: /etc/systemd/system/vault.service + - template: jinja + - context: + user: {{ vault.user }} + group: {{ vault.group }} + - mode: 0644 + {%- elif salt['test.provider']('service') == 'upstart' %} + - source: salt://{{ slspath }}/files/vault.upstart + - name: /etc/init/vault.conf + - mode: 0644 + {%- else %} + - source: salt://{{ slspath }}/files/vault.sysvinit + - name: /etc/init.d/vault + - mode: 0755 + {%- endif %} + +{%- if vault.service %} + +vault-service: + service.running: + - name: vault + - enable: True + - watch: + - file: vault-init-env + - file: vault-init-file + +{%- endif %}