Skip to main content
Gå til innhold

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> ...]
info

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.