Skip to content

Encrypting Hiera Data

It is possible to store sensitive data in Hiera using hiera-eyaml. Encrypted values live in your Hiera data alongside plain values, and OpenVox decrypts them at lookup time.

You can enable EYAML on a single layer of the hierarchy by giving that layer an eyaml_lookup_key and the paths to your key pair:

---
version: 5
hierarchy:
  - name: "Secret data"
    lookup_key: eyaml_lookup_key
    paths:
      - "secrets/nodes/%{facts.fqdn}.eyaml"
      - "common.eyaml"
    options:
      pkcs7_private_key: /etc/puppetlabs/puppet/eyaml/private_key.pkcs7.pem
      pkcs7_public_key:  /etc/puppetlabs/puppet/eyaml/public_key.pkcs7.pem

In this example, the Secret data layer is encrypted using the key specified by pkcs7_public_key.

Note

This example uses PKCS7 keys (the default). hiera-eyaml supports other encryption methods through pluggable backends — one alternative is hiera-eyaml-gpg.

Alternatively, you can enable EYAML across all layers of the hierarchy by putting the settings in the defaults key:

---
version: 5

defaults:
  lookup_key: eyaml_lookup_key
  options:
    pkcs7_private_key: /etc/puppetlabs/puppet/eyaml/private_key.pkcs7.pem
    pkcs7_public_key:  /etc/puppetlabs/puppet/eyaml/public_key.pkcs7.pem

hierarchy:
  - name: "Common"
    path: "common.yaml"

Enabling EYAML

Both OpenVox and voxbox include the hiera-eyaml gem, so the eyaml command is available at /opt/puppetlabs/puppet/bin/eyaml.

Try it yourself: generate keys

Generate a key pair and install it where the OpenVox server can read it:

$ mkdir keys
$ /opt/puppetlabs/puppet/bin/eyaml createkeys

$ sudo mkdir -m 0500 -p /etc/puppetlabs/puppet/eyaml
$ sudo cp keys/*.pem /etc/puppetlabs/puppet/eyaml/

In a real deployment you would manage the keys with OpenVox itself. A profile class to create them might look like this:

class profile::server::eyaml (
  String $eyaml_dir    = '/etc/puppetlabs/puppet/eyaml',
  String $private_key  = "${eyaml_dir}/private_key.pkcs7.pem",
  String $public_key   = "${eyaml_dir}/public_key.pkcs7.pem",
  String $puppet_user  = 'puppet',
  String $puppet_group = 'puppet',
) {
  file { $eyaml_dir:
    ensure => directory,
    owner  => $puppet_user,
    group  => $puppet_group,
    mode   => '0500',
  }
  -> exec { 'createkeys':
    command => [
      '/opt/puppetlabs/puppet/bin/eyaml',
      'createkeys',
      "--pkcs7-private-key=${private_key}",
      "--pkcs7-public-key=${public_key}",
    ].join(' '),
    cwd     => $eyaml_dir,
    creates => $private_key,
  }
  ~> exec { "/bin/chown ${puppet_user}:${puppet_group} ${private_key} ${public_key}":
    refreshonly => true,
  }
}

Try it yourself: configure the hierarchy

With the keys in place, add the following to your control repo's hiera.yaml:

defaults:
  lookup_key: eyaml_lookup_key
  options:
    pkcs7_private_key: /etc/puppetlabs/puppet/eyaml/private_key.pkcs7.pem
    pkcs7_public_key: /etc/puppetlabs/puppet/eyaml/public_key.pkcs7.pem

Try it yourself: encrypt and look up a value

Encrypt a test value and add the output to data/common.yaml in your control repo:

$ /opt/puppetlabs/puppet/bin/eyaml encrypt \
  -o block -l testkey -s testvalue

Commit the change and deploy with r10k deploy environment -v. Then verify the value decrypts correctly by running this as root:

# puppet lookup testkey