Usage from puppet
Creating a token for a puppet node
Once you know the certificate name of a puppet node you can generate a
vault token for it. To do so, get hold of the generate_puppet_token.py
script, e.g. by checking out the puppet
repo, logging in to vault, and run:
$ python generate_puppet_token.py --role <role> <node> <policy> [<policy> ...]
To override the Vault URL export the VAULT_ADDR environment variable
where <node>
is the certname of the puppet node and <policy>
is
one or more policies that this node should have and <role>
is the
name of a role that has access to create tokens with the specified
policies.
The puppet node will fetch this token using its puppet certificate as authentication and the mechanism used ensures that it can only be fetched once. This means that if a node is decommissioned and a new node is created with the same name, this can not receive the previous nodes token.
NOTE: In order to use vault from puppet this way, the node needs to access the following endpoints:
- vault.sikt.no at port 8200 (for fetching secrets)
- puppetvault.uninett.no at port 443 (for fetching initial token)
Ensure that ACLs include the puppet node in question. Most of Sikts server networks should have this access already.
If you do not know the role and policy to use and they should be the same as a node which already has a valid token, you can ask vault about that token:
curl -sSLf -H "X-Vault-Token: $(sudo cat /root/.vault-token)" https://vault.sikt.no:8200/v1/auth/token/lookup-self | json_pp
Look for policies
and role
.
Pushing a Vault secret as a file
The pmodule_vault::secret_simple_file
defined resource type can be used to extract data from Vault as a file.
The following example will look up the field_in_secret
field in the secret/vault/path
path in Vault and store it in /etc/secret
:
::pmodule_vault::secret_simple_file { '/etc/secret':
vault_key => 'secret/vault/path',
vault_field => 'field_in_secret',
owner => 'root',
group => 'root',
mode => '0600',
}
Pushing templated files with secrets in them
The pmodule_vault
module contains a define called pmodule_vault::secret_file
to create files on a node with secrets from vault inserted in them. Example usage:
pmodule_vault::secret_file{'/etc/myfile':
ensure => present,
content => template('pmodule_something/myfile.erb'),
mode => '0600',
owner => 'root',
group => 'root',
secrets => {
'secret_name' => "secret/vault/path",
},
}
In the template you use <%= scope.function_vault(["secret_name", "key"]) %>
to indicate which secret to use. The first argument is a "nice name" for the secret (the key in the secrets
hash passed to pmodule_vault::secret_file) and the second argument is the key of the key-value pair inside that vault path that you want to insert there. So if you wrote the secrets like this:
vault kv put secret/vault/path username=foo password=bar
And your template looks like this:
USERNAME=<%= scope.function_vault(["secret_name", "username"]) %>
PASSWORD=<%= scope.function_vault(["secret_name", "password"]) %>
the resulting file would look like this:
USERNAME=foo
PASSWORD=bar
Installing a certificate
To install a certificate from vault, include something like this in your puppet manifest:
pmodule_vault::cert{'mysite.uninett.no':
vault_key => "secret/mysite/certs/mysite.uninett.no",
}
This creates /etc/ssl/private/mysite.uninett.no.pem
and /etc/ssl/private/mysite.uninett.no_key.pem
with sensible permissions. The file paths and permissions can be overridden using the $cert_filename
, key_filename
, cert_mode
and key_mode
parameters. Use the helper (/usr/local/uninett-ca/bin/helper.py) on crt.uninett.no with the --store-vault
parameter to upload the certificate and private key to vault.
Troubleshooting
If on running puppet you get an error something like this:
Notice: /Stage[main]/Pmodule_vault::Secret_setup/Exec[vault_get_token]/returns: requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: https://vault.sikt.no:8200/v1/cubbyhole/puppet_token
Error: '/usr/local/bin/vault_get_token.py --vault-url https://vault.sikt.no:8200/v1/ --ssl-path /etc/puppetlabs/puppet/ssl' returned 1 instead of one of [0]
Error: /Stage[main]/Pmodule_vault::Secret_setup/Exec[vault_get_token]/returns: change from notrun to 0 failed: '/usr/local/bin/vault_get_token.py --vault-url https://vault.sikt.no:8200/v1/ --ssl-path /etc/puppetlabs/puppet/ssl' returned 1 instead of one of [0]
Notice: /Stage[main]/Pmodule_vault::Secret_setup/Exec[vault_renew_token]: Dependency Exec[vault_get_token] has failures: true
Warning: /Stage[main]/Pmodule_vault::Secret_setup/Exec[vault_renew_token]: Skipping because of failed dependencies
.. just generate a new token with generate_puppet_token.py
.
If this does not help, try removing /root/.vault-token
and run puppet again.
If you are unsure about which role and policy to use, you can go to a machine with the same setup and a valid token, and run
sudo curl -H "X-Vault-Token: $(sudo cat /root/.vault-token)" \
https://vault.sikt.no:8200/v1/auth/token/lookup-self
The result is json which includes data.policies
and data.role
.