• Blog
  • Podcasts
  • Bio
  • About

Utah Tech Podcast

Bringing the Utah tech community together.

Welcome to the Blog @ utahtechpodcast.com!!!

October 10, 2017 By Brett Benassi Leave a Comment

Thanks for coming to pay a visit. Hopefully the content here will help you in some way.

Hashicorp Vault & Salt Setup.

October 10, 2017 By Brett Benassi Leave a Comment

This article is going to do a walkthrough of how to use Salt to configure Hashicorp Vault. It is going to also use Consul as a backend in this example.

This article assumes that you are familiar with the following:

  • Salt
  • Vault
  • Consul

We are going to do the following things here:

  1. Setup Vault (“not in a dev capacity”)
  2. Setup Consul systemd unit
  3. Setup Vault systemd unit
  4. Setup basic Vault policies
  5. Setup Salt to talk to Vault

Assumptions I am going to use in this example:

  • CentOS Linux release 7.4
  • Vault Version: 0.8.3
  • Consul Version: 0.9.3

 

Lets get started…

So first I will create a path for the files: In my case it is:

Shell
1
/srv/salt/release-mgmt/states/services/

 

In there, I create: consul-appĀ and vault-app folders.

Shell
1
/srv/salt/release-mgmt/states/services/consul-app

Shell
1
/srv/salt/release-mgmt/states/services/vault-app

 

Vault Setup:

From there I setup an init.sls file with the following contents:

init.sls
Python
1
2
include:
  - services.vault-app.install

 

This is going to just be the starting place for the state file. I will be creating a install.sls file to perform the install.

Shell
1
/srv/salt/release-mgmt/states/services/vault-app/install.sls

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
{% import 'services/vault-app/vault-params.jinja' as params %}
 
vault:
  file.managed:
    - source: https://releases.hashicorp.com/vault/{{ salt['pillar.get']('vault_version') }}/vault_{{ salt['pillar.get']('vault_version') }}_linux_amd64.zip
    - name: /tmp/vault_{{ salt['pillar.get']('vault_version') }}_linux_amd64.zip
    - source_hash: https://releases.hashicorp.com/vault/{{ salt['pillar.get']('vault_version') }}/vault_{{ salt['pillar.get']('vault_version') }}_SHA256SUMS
    - template: jinja
 
  archive.extracted:
    - name: /usr/bin
    - source: /tmp/vault_{{ salt['pillar.get']('vault_version') }}_linux_amd64.zip
    - user: {{ params.vault_user }}
    - group: {{ params.vault_group }}
    - enforce_toplevel: False
 
  group.present:
    - name: {{ params.vault_group }}
    - addusers:
      - {{ params.vault_user }}
    - require:
      - user: {{ params.vault_user }}
 
  user.present:
    - name: {{ params.vault_user }}
    - shell: /bin/bash
 
 
set_user_mlock:
  cmd.run:
    - name: '{{ params.vault_user_setcap }} && touch {{ params.vault_config_base_path }}/mlock.ran'
    - unless: test -f  {{ params.vault_config_base_path }}/mlock.ran
 
/etc/sysconfig/vault:
  file.directory:
    - user: {{ params.vault_user }}
    - group: {{ params.vault_group }}
    - dir_mode: 755
    - file_mode: 644
    - recurse:
      - user
      - group
      - mode    
 
vault_configs:
  file.managed:
    - name: {{ params.vault_config_dest }}
    - source: {{ params.vault_config_source }}
    - group: {{ params.vault_user }}
    - user: {{ params.vault_group }}
    - require:
      - file: {{ params.vault_config_base_path }}
 
vault_systemd_unit:
  file.managed:
    - name: {{ params.vault_service_file_dest }}
    - source: {{ params.vault_service_file_source }}
    - template: jinja
  module.run:
    - name: service.systemctl_reload
    - onchanges:
      - file: vault_systemd_unit
 
vault_running:
  service.running:
    - name: vault
    - watch:
      - module: vault_systemd_unit
    - require:
      - cmd: set_user_mlock

We will need some vault policies, I have defined a generic on here as:

Shell
1
/srv/salt/release-mgmt/states/services/vault-app/vault_policies_install.sls

YAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{% import 'services/vault-app/vault-params.jinja' as params %}
{% for policy_name, policy_file in salt['pillar.get']('vault_policies').items() %}
 
vault_policies:
  file.managed:
    - name: {{ params.vault_policies_dest }}/{{ policy_file }}
    - source: {{ params.vault_policies_source }}/{{ policy_file }}
    - group: {{ params.vault_user }}
    - user: {{ params.vault_group }}
    - template: jinja
    - context:
        policy_file: {{ policy_file }}
 
  cmd.run:
    - name: vault policy-write {{ policy_name }} {{ params.vault_policies_dest }}/{{ policy_file }}
    - env:
        VAULT_ADDR: 'http://127.0.0.1:8200'
 
 
{% endfor %}

We will need the params file for all of the parameters that have been set:

Shell
1
/srv/salt/release-mgmt/states/services/vault-app/vault-params.jinja

YAML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{# vault parmas #}
{% set vault_user = 'vault' %}
{% set vault_group = 'vault' %}
{% set files_root_path = 'salt://services/vault-app/files' %}
{% set vault_config_base_path = '/etc/sysconfig/vault' %}
{% set vault_config_source = files_root_path + '/' + 'vault.hcl' %}
{% set vault_config_dest = vault_config_base_path + '/' + 'vault.hcl' %}
{% set vault_service_file_dest = '/etc/systemd/system/vault.service' %}
{% set vault_service_file_source = files_root_path + '/' + 'vault.service'%}
{% set vault_user_setcap = 'sudo setcap cap_ipc_lock=+ep $(readlink -f $(which vault))'%}
 
 
 
{# vault policy params #}
{% set vault_policies_dest = vault_config_base_path %}
{% set vault_policies_source = files_root_path %}

And at last the pillar data…

Install this in your pillar for the env you are going to run it against(in my case “dev”).

YAML
1
2
3
vault_version: 0.8.3
vault_policies:
Ā  dev-policy: dev-policy.hcl

Now the last piece is all the files we are going to manage:

I create a directory called:

Shell
1
/srv/salt/release-mgmt/states/services/vault-app/files/

In the files directory I create the following files:

Shell
1
/srv/salt/release-mgmt/states/services/vault-app/files/dev-policy.hcl

Shell
1
/srv/salt/release-mgmt/states/services/vault-app/files/vault.hcl

Shell
1
/srv/salt/release-mgmt/states/services/vault-app/files/vault.service

 

And the contents for each will be:

Shell
1
/srv/salt/release-mgmt/states/services/vault-app/files/dev-policy.hcl

Python
1
2
3
4
5
6
7
path "secret/*" {
capabilities = ["read", "list"]
}
 
path "auth/*" {
capabilities = ["read", "list","sudo","create","update","delete"]
}

Shell
1
/srv/salt/release-mgmt/states/services/vault-app/files/vault.hcl

Python
1
2
3
4
5
6
7
8
9
storage "consul" {
address = "127.0.0.1:8500"
path = "vault"
}
 
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = 1
}

Shell
1
/srv/salt/release-mgmt/states/services/vault-app/files/vault.service

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{% import 'services/vault-app/vault-params.jinja' as params %}
[Unit]
Description=vault server
Requires=network-online.target
After=network-online.target
 
[Service]
User=vault
EnvironmentFile=-{{ params.vault_config_base_path }}
Environment=GOMAXPROCS=2
Restart=on-failure
ExecStart=/usr/bin/vault server -config={{ params.vault_config_dest }}
ExecReload=/bin/kill -HUP $MAINPID
KillSignal=SIGINT
 
[Install]
WantedBy=multi-user.target

 

Consul Setup:

This is a basic consul setup to be able to use Consul as the Vault backend.

Shell
1
/srv/salt/release-mgmt/states/services/consul-app/consul-params.jinja

Python
1
2
3
4
5
6
7
{# consul parmas #}
{% set consul_user = 'consul' %}
{% set consul_group = 'consul' %}
{% set files_root_path = 'salt://services/consul-app/files' %}
{% set consul_config_base_path = '/usr/local/consul' %}
{% set consul_service_file_dest = '/etc/systemd/system/consul.service' %}
{% set consul_service_file_source = files_root_path + '/' + 'consul.service'%}

Shell
1
/srv/salt/release-mgmt/states/services/consul-app/install.sls

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
{% import 'services/consul-app/consul-params.jinja' as params %}
 
consul:
  file.managed:
    - source: https://releases.hashicorp.com/consul/{{ salt['pillar.get']('consul_version') }}/consul_{{ salt['pillar.get']('consul_version') }}_linux_amd64.zip
    - name: /tmp/consul_{{ salt['pillar.get']('consul_version') }}_linux_amd64.zip
    - source_hash: https://releases.hashicorp.com/consul/{{ salt['pillar.get']('consul_version') }}/consul_{{ salt['pillar.get']('consul_version') }}_SHA256SUMS
 
 
  archive.extracted:
    - name: /usr/bin
    - source: /tmp/consul_{{ salt['pillar.get']('consul_version') }}_linux_amd64.zip
    - user: {{ params.consul_user }}
    - group: {{ params.consul_group }}
    - enforce_toplevel: False
 
  group.present:
    - name: {{ params.consul_group }}
    - addusers:
      - {{ params.consul_user }}
    - require:
      - user: {{ params.consul_user }}
 
  user.present:
    - name: {{ params.consul_user }}
    - shell: /bin/bash
 
consul_systemd_unit:
  file.managed:
    - name: {{ params.consul_service_file_dest }}
    - source: {{ params.consul_service_file_source }}
    - template: jinja
  module.run:
    - name: service.systemctl_reload
    - onchanges:
      - file: consul_systemd_unit
 
consul_running:
  service.running:
    - name: consul
    - watch:
      - module: consul_systemd_unit

Shell
1
/srv/salt/release-mgmt/states/services/consul-app/files/consul.service

Python
1
2
3
4
[Unit]
Description=consul agent
Requires=network-online.target
After=network-online.target

Python
1
2
3
4
5
6
7
8
9
10
11
[Service]
User=consul
EnvironmentFile=-/etc/sysconfig/consul
Environment=GOMAXPROCS=2
Restart=on-failure
ExecStart=/usr/bin/consul agent -server -bootstrap-expect 1 -data-dir /usr/local/consul -bind 127.0.0.1
ExecReload=/bin/kill -HUP $MAINPID
KillSignal=SIGINT
 
[Install]
WantedBy=multi-user.target

With this setup you should have a very basic Vault setup. Beyond this you will need to add some k/v pairs and test out the commands from your salt-master.

An example is:

Shell
1
salt '<target>' vault.read_secret "secret/somesecret"

And dont forget to wire up the salt master for Vault:

https://docs.saltstack.com/en/latest/ref/modules/all/salt.modules.vault.html

Hopefully I have not missed anything, if I did please leave a comment and I will update the post.

 

Next up will be InfuxDB, Grafana, and Telegraf…

 

Recent Posts

  • Welcome to the Blog @ utahtechpodcast.com!!! October 10, 2017
  • Hashicorp Vault & Salt Setup. October 10, 2017

© 2018 utahtechpodcast.com | Send Feedback | Terms