Skip to content

Puppet external node

Matt Pascoe edited this page May 30, 2023 · 1 revision

Here is a quick note about how I use ONA to be an external node classifier for Puppet.

First off, I utilize hiera to act as the classifier. If you are not already using Hiera then you should be! It has many more benefits than simply talking to ONA.

For my Puppet environments, I like to classify all my hosts using a role. A role is a single name that defines what this specific server is for. This conforms to the Puppet Roles and Profiles method. I suggest you go familiarize with Hiera and Roles/Profiles if you are not already. Here we go with my example setup.

Site.pp Setup

manifests/site.pp is typically the first entry point into Puppet. In this case, it is where the default node is defined for all Puppet managed servers.

# Set default exec path for all
Exec { path => '/usr/bin:/usr/sbin:/bin:/usr/local/bin:/usr/local/sbin:/opt/local/bin:/opt/ccm/bin'}

node default {
  # Example FQDN breakdown
  # KEY: role##.deployenv.toplevel_domain
  # Example FQDN:    ona01.dev01.example.com

  # role:            ona  (the 01 instance of N+1)
  # deployenv:       dev01
  # toplevel_domain: example.com

  # Split the current FQDN into an array
  $fqdnsplit = split($::trusted['certname'], '[.]')

  # Define toplevel domain, this would be the last two sections of FQDN
  $toplevel_domain = "${fqdnsplit[-2]}.${fqdnsplit[-1]}"

  # Lookup role in hiera, this should come from ONA
  # Roles can not contain -, only _, This is a puppet class name limitation.
  $role = lookup('role', undef, undef, 'common')

  # Pull deployenv from FQDN, you might choose to have this as another ONA custom attribute if desired.
  $deployenv = $fqdnsplit[1]

  #debug output
  #notify{"--- ROLE: $role DEPLOYENV: $deployenv TLD: $toplevel_domain": }

  include "role::${role}"
}

I wont go over each line in site.pp, they are mostly described or self explanatory here anyway. Just note the lookup('role') portion that sets the $role variable. This is the magic of Hiera.

Hiera.yaml config

So now that we are doing a hiera lookup function, we will need to have a hiera.yaml file configured. Here is an example:

---
version: 5

defaults:  # Used for any hierarchy level that omits these keys.
  datadir: data         # This path is relative to hiera.yaml's directory.
  data_hash: yaml_data  # Use the built-in YAML backend.

hierarchy:
  # Hiera_http info https://github.com/crayfishx/hiera-http
  # Install lookup_http gem per install instructions on project
  # Install module via Puppetfile as usual
  - name: "HTTP to ONA"
    lookup_key: hiera_http
    uri: "https://ona.example.com/dcm.php?module=host_display&format=json&host=%{trusted.certname}"
    options:
      dig_key: custom_attributes.__KEY__
      output: json
      use_ssl: true
      ssl_verify: false
      ignore_404: true
      confine_to_keys:
        - "role"
  - name: "Environment yaml files"
    lookup_key: eyaml_lookup_key
    options:
      pkcs7_private_key: /opt/puppetlabs/puppet/eyaml/private_key.pkcs7.pem
      pkcs7_public_key:  /opt/puppetlabs/puppet/eyaml/public_key.pkcs7.pem
    paths:
      - "nodes/%{trusted.certname}.yaml"
      - "deployenvs/%{deployenv}.yaml"
      - "roles/%{role}.yaml"
      - "common.yaml"

Again, I'm not going to go through each line. This simply reaches out to the ONA dcm.php endpoint and invokes the host_display module to get json output. You must first install the hiera-http module.

In ONA you must define a new custom attribute type called role within the Admin section of the ONA GUI. It should have the following field validation rule: /^[a-z0-9]+(?:_[a-z0-9]+)*$/. This is what mine looks like.

image

Once you have that custom attribute type defined, you will need to assign the role to your specific host. The expectation is that this role name will match a defined role that is configured in your puppet manifest using the Roles and Profiles methodology.

If you do not assign a custom attribute role in ONA then the lookup function will default to a role called common. If you do have a role in ONA but have not defined it in the puppet manifest, then you will get an error in your puppet run.