haase.dev/ blog

Puppet: Hiera Lookup with Trusted Facts

April 5, 2021

I'm playing around with a new Puppet setup based on the new version 7.5 and with the goal to keep complexity to a minimum.

While trying to configure my hiera hierarchy, I stumbled upon the issue that my lookups failed.

The configured hierarchy looks as follows:

paths:
  - 'nodes/%{trusted.certname}.yaml'
  - 'role/%{trusted.extensions.pp_role}.yaml'
  - 'zones/%{trusted.extensions.pp_zone}.yaml'
  - 'common.yaml'

When I first started with Puppet, I used custom facts on the node itself to determine its role and zone, which could potentially be tampered. With trusted facts this is no longer possible, as these facts are embedded into the node's certificate.

If you are not sure whether the facts are correctly embedded in your certificate, you can use puppet ssl show to display them.

So let's check if the hiera lookup works as expected: puppet lookup role --explain

Environment Data Provider (hiera configuration version 5)
Using configuration "/etc/puppetlabs/code/environments/production/hiera.yaml"
  Hierarchy entry "Environment data"
    Merge strategy hash
      Path "/etc/puppetlabs/code/environments/production/data/nodes/cfg01.gernox.de.yaml"
        Original path: "nodes/%{trusted.certname}.yaml"
        No such key: "lookup_options"
      Path "/etc/puppetlabs/code/environments/production/data/role/.yaml"
        Original path: "role/%{trusted.extensions.pp_role}.yaml"
        Path not found
      Path "/etc/puppetlabs/code/environments/production/data/zones/.yaml"
        Original path: "zones/%{trusted.extensions.pp_zone}.yaml"
        Path not found
      Path "/etc/puppetlabs/code/environments/production/data/common.yaml"
        Original path: "common.yaml"
        No such key: "lookup_options"

Looking at the role and zone paths, it is clear that the interpolation didn't work as expected...

Printing out the whole trusted variable, you can see that the value for the extensions key is in fact empty.

{
  "authenticated"=>"local",
  "certname"=>"cfg01.gernox.de",
  "extensions"=>{ },
  "hostname"=>"cfg01",
  "domain"=>"gernox.de",
  "external"=>{ }
}

Nevertheless, when doing a regular Puppet agent run, it works. So keep that in mind while debugging.