Querying PuppetDB with vRealize Orchestrator and vRealize Automation

TL;DR: if you're just interested in how to configure orchestrator to allow puppetDB querying,follow the link.

PuppetDB is an extension to Puppet allowing you to aggregate data from Puppet nodes such as custom facts, catalogs and resources. While PuppetDB is installed by default in Puppet Enterprise, it is not included by default in Puppet Open Source. Installing and configuring PuppetDB - either on your puppet master or as a standalone server is as simple as following https://docs.puppet.com/puppetdb/4.3/installfrompackages.html.

PuppetDB and vRealize Automation

Now that we have PuppetDB, what can we use it for related to vRealize automation? Some examples are:

Performing day two operations using information about the guest operating system:

Instead of having to run commands through ssh or powershell to retrieve this information, you can now query the PuppetDB for this information. Not only is this faster, it's also more reliable and doesn't depend on the guest being up and running. An example of this would be setting the backup schedule based on the node's environment, the application owner or the region the VM is deployed in.

Querying information of other nodes for the purpose of deployment.

Let's say you're scaling out an application and need to perform post-provisioning tasks. Instead of storing the task-specific information in vRealize Orchestrator configuration elements or vRealize automation custom properties, you can now query Puppet directly for the required information.

Best of all

You get to use a proper, clean API that returns standardized JSON instead of having to mess about with shell scripts that may or may not return correctly formatted information.

Some interesting examples of information that can be used to improve your workflows:

  • The name of your nics in the guest operating system: vRealize automation only shows you the nic index, not the nic name. Since new versions of most Linux operating systems use bios device names for their nics, this has caused issues for all of us when workflows depend on static naming such as eth0, eth1, etc.
  • Mountpoints of filesystems and their actual sizes. Instead of having to grep your /etc/mtab for the purpose of day 2 operations involving the filesystem, you can now do a simple query on the guest's filesystem and parse that information.
  • Whether or not a specific package or piece of software is installed, and if so - what version.
  • Relationships between nodes: You can now see which node depends on other nodes, allowing you to improve dependency handling between multimachine nodes.
  • In addition, you can create custom facts - either static or dynamic - to include in PuppetDB.

Configuring vRealize Orchestrator

So how do we set all of this up? First, we have to start with signing a custom certificate for vRealize Orchestrator. As PuppetDB performs client-based certificate authentication, we need to provide vRealize Orchestrator with a certificate.

Start off with generating a custom certificate on the puppetmaster. This assumes that your Puppetmaster is a CA. If not, you'll have to find out how your certificates are generated and trusted):

Run the following on your puppetmaster (replacing your.vro.fqdn with your actual vro machine's fqdn. If you have a cluster of vRO machines each machine needs to have their own individual certificate generated:

puppet cert generate your.vro.fqdn

This generates the following files:

  • /etc/puppetlabs/puppet/ssl/certs/your.vro.fqdn.pem
  • /etc/puppetlabs/puppet/ssl/private_keys/your.vro.fqdn.pem

Next, we'll need to generate a certificate file containing the private key and the full chain to import into vRO. This is important, as the vRO certificate store is very picky about the format of the file:

run the following command on your puppetmaster you signed the certificate on:

cd /etc/puppetlabs/puppet/ssl  
cat private_keys/your.vro.fqdn.pem certs/your.vro.fqdn.pem certs/ca.pem > /tmp/vro-cert.pem  

Your certificate chain should now be located in /tmp/vro-cert.pem.

Next, open orchestrator and perform the following:

  • Run the Library\Configuration\Keystores\Add key workflow.
  • Select the keystore you want to add the key to (i created a separate keystore through the Library\Configuration\Keystores\Create a keystore workflow, though this is entirely optional.)
  • enter a key alias. This is entirely freeform, but i recommend providing a sensible alias.
  • Paste the entire contents of the /tmp/vro-cert.pem file in the PEM encoded key field. Ensure that you have no whitespace in your head or tail.
  • Leave the key password field blank, as we don't have a password set.

Afterwards, you can go to the inventory, and the vRO configuration\Keystores should show your certificate with a padlock icon, indicating this certificate has a private key stored.

Next, we'll run the HTTP-REST\Configuration\Add a REST Host workflow. Enter the usual properties such as the name, URL, and certificate acceptance properties. Set the authentication in 2a to NONE, as we will not be performing credential-based authentication.

Then, in the 4a SSL page, set "Verify whether the target hostname matches the names stored inside the server's X509 certificates to yes. As puppet self-signs its certificates this should always match. Next, Select your certificate in the PrivateKey entry:

When you run the workflow, you should now have a REST host added to your inventory. Note that if the certificate authentication fails, for whatever reason vRO will still add the rest host, but prepend its name with [Invalid]. This is most likely due to the connection succeeding, but vRA never receiving valid HTTPS data. This is what cost me some time to figure out why it wasn't actually working.

Next, you can run your REST queries as normal in your workflow. Some samples are located in the "HTTP-REST Samples" Folder for inspiration. As an example, this query returns the uptime fact for a specific node. You can obviously turn this into any query you need, and you'll probably want to make the query URL dynamic:

And the result is as follows:

[{
"certname":"media.int.vxsan.com",
"name":"uptime",
"value":"35 days",
"environment":"production"
}]

And that's all there is to querying your puppetDB dynamically from vRealize Orchestrator, and obviously if you have any other product that performs mutual certificate authentication you can use the same method.

Happy puppeting!