Puppet setup

Integrations

Puppet and Vault (hiera_vault)

Idea here is to use cert auth which will be used by puppetserver for authentication.There are two options to set certs on vault server,certs created by puppetserver and copied and certs used from puppet-agent.

Common puppetserver setup

Install required modules

puppet module install petems-hiera_vault --version 0.4.0
/opt/puppetlabs/puppet/bin/gem install vault

Here is the hiera config

root@milekitic1c:/etc/puppetlabs/code/environments/production# cat hiera.yaml
---
version: 5
defaults:
  # The default value for "datadir" is "data" under the same directory as the hiera.yaml
  # file (this file)
  # When specifying a datadir, make sure the directory exists.
  # See https://puppet.com/docs/puppet/latest/environments_about.html for further details on environments.
  # datadir: data
  # data_hash: yaml_data
hierarchy:
  - name: "Hiera-vault lookup"
    lookup_key: hiera_vault
    options:
      confine_to_keys:
        - '^vault_.*'
        - '^.*_password$'
        - '^password.*'
      ssl_verify: false
      address: https://milekitic1c.mylabserver.com:8200
      token: /etc/vault_token.txt
      default_field: value
      mounts:
        puppet:
          - '%{::trusted.certname}'
          - 'common'
  - name: "Per-node data (yaml version)"
    path: "nodes/%{::trusted.certname}.yaml"
  - name: "Other YAML hierarchy levels"
    paths:
      - "common.yaml"

Common Vault setup

Here is the config files for vault.

root@milekitic2c:~/vault# cat my_policy vault.hcl
path "kv/test" {
  capabilities = ["read"]
}

path "puppet/*" {
  capabilities = ["read", "list"]
}
listener "tcp" {
  address       = "0.0.0.0:8200"
  tls_cert_file = "/root/vault/vault_cert_file.pem"
  tls_key_file  = "/root/vault/vault_key_file.pem"
  tls_client_ca_file = "/root/vault/vault_client_ca_file.pem"
}
api_addr = "https://milekitic2c.mylabserver.com:8200"
cluster_addr = "https://milekitic2c.mylabserver.com:8201"


# storage in file
storage "file" {
  path = "/mnt/vault/data"
}

Option 1

Files vault_*.pem are generated and copied from puppetmaster server after executing puppetserver ca generate --certname VAULT.FQDN

Here is the output of above command:

root@milekitic1c:~# puppetserver ca generate --certname milekitic2c.mylabserver.com
Successfully saved private key for milekitic2c.mylabserver.com to /etc/puppetlabs/puppet/ssl/private_keys/milekitic2c.mylabserver.com.pem
Successfully saved public key for milekitic2c.mylabserver.com to /etc/puppetlabs/puppet/ssl/public_keys/milekitic2c.mylabserver.com.pem
Successfully submitted certificate request for milekitic2c.mylabserver.com
Error:
    Signed certificate milekitic2c.mylabserver.com could not be found on the CA
Successfully signed certificate request for milekitic2c.mylabserver.com
Successfully saved certificate for milekitic2c.mylabserver.com to /etc/puppetlabs/puppet/ssl/certs/milekitic2c.mylabserver.com.pem

Mapping of files

vault_cert_file.pem = /etc/puppetlabs/puppet/ssl/certs/milekitic2c.mylabserver.com.pem
vault_client_ca_file.pem = /etc/puppetlabs/puppet/ssl/certs/ca.pem # ca file from puppetserver
vault_key_file.pem = /etc/puppetlabs/puppet/ssl/public_keys/milekitic2c.mylabserver.com.pem
root@milekitic2c:~/vault# ls -l
total 20
-rw-r--r-- 1 root root  100 Mar 27 15:29 my_policy
-rw-r--r-- 1 root root  439 Mar 27 15:41 vault.hcl
-rw-r--r-- 1 root root 1984 Mar 27 15:18 vault_cert_file.pem
-rw-r--r-- 1 root root 3875 Mar 27 15:20 vault_client_ca_file.pem
-rw-r--r-- 1 root root 3243 Mar 27 15:19 vault_key_file.pem

Option 2

If vault server is managed by puppet vault.hcl can be configured as:

root@milekitic1c:~# cat vault.hcl
listener "tcp" {
  address       = "0.0.0.0:8200"
  tls_cert_file = "/etc/puppetlabs/puppet/ssl/certs/milekitic1c.mylabserver.com.pem"
  tls_key_file  = "/etc/puppetlabs/puppet/ssl/private_keys/milekitic1c.mylabserver.com.pem"
  tls_client_ca_file = "/etc/puppetlabs/puppet/ssl/certs/ca.pem"
}
api_addr = "https://milekitic1c.mylabserver.com:8200"
cluster_addr = "https://milekitic1c.mylabserver.com:8201"

# storage in memory
#storage "inmem" {}

# storage in file
storage "file" {
  path = "/mnt/vault/data"
}

Vault cert auth config

enable cert auth

vault auth enable cert

create test policy

vault policy write test /path/my-policy.hcl

content of /path/my-policy.hcl

path "puppet/*" {
  capabilities = ["read","list"]
}

create auth cert config

vault write auth/cert/certs/puppetserver \
display_name=puppet \
policies=test \
certificate=@/etc/puppetlabs/puppet/ssl/certs/ca.pem \
ttl=3600

enable secret engine and create some secret

vault secrets enable -path=puppet kv
vault kv put puppet/common/vault_notify value=test1234

Puppet fetching token during cert auth

Idea here it to use crontab on some interval and fetch token.Token will be saved in /etc/vault_token.txt which is used by hiera for vault lookup.

*/1 * * * * curl -s --request POST --cacert /etc/puppetlabs/puppet/ssl/certs/ca.pem --cert /etc/puppetlabs/puppet/ssl/certs/milekitic2c.mylabserver.com.pem  --key /etc/puppetlabs/puppet/ssl/private_keys/milekitic2c.mylabserver.com.pem  --data '{"name": "puppetserver"}' https://milekitic2c.mylabserver.com:8200/v1/auth/cert/login | jq -r '.auth.client_token' > /etc/vault_token.txt

References

https://forge.puppet.com/puppet/vault_lookup/readme https://petersouter.xyz/how-to-use-vault-with-hiera-5-for-secret-management-with-puppet/ https://github.com/petems/petems-hiera_vault https://github.com/crayfishx/hiera-eyaml-vault https://github.com/hashicorp/webinar-vault-hiera-puppet https://github.com/petems/petems-hiera_vault