A Puppet server provides several features above and beyond what’s possible in a puppet apply environment. Let’s review each of these server-based features.
When using a Puppet server you gain several data sources not available to you with puppet apply.
When a node connects to the server it transmits a list of facts about the node. Unfortunately, there is no way to validate that these facts are correct. If you have conditions in your code based on node information that provide access to security-related data, the data could be accessed by a compromised node that forged its facts.
There is a new hash available named $trusted[]. It contains facts that have been validated by the server, and can be trusted to be correct.
$trusted['authenticated']The possible values are:
remotelocalpuppet apply is being used and validation is unavailablefalse$trusted['certname']$certname in the Puppet configuration if local.$trusted['hostname'] and $trusted['domain']hostname will contain the part before the first period of the certificate name, and domain will contain the remainder. This is useful when you’re using FQDN certnames, and confusing in other situations.$trusted['extensions']You can significantly improve security by altering the Hiera hierarchy to use the trusted[] facts provided by the server instead of the facts[] supplied by the client:
:hierarchy:-"nodes/%{trusted.certname}"-"os/%{facts.os.family}"-common
More values could be added to Trusted Facts by later releases of Puppet. You can see the current list at “Facts and Built-in Variables: Trusted Facts” on the Puppet docs site.
The server sets certain variables for use in manifests. Unfortunately, if the node provides facts of the same name, these values will be overridden. If you enable the following setting, the Puppet server will define a new hash of server facts that a client cannot override:
[master]trusted_server_facts=true
When this value is enabled (and the Puppet server reloaded), there will be a new hash available named $server_facts[] that provides the following values:
$server_facts['serverversion']$server_facts['servername']certname) of the server. The name used to sign all certificates if the server provides the CA function.$server_facts['serverip']$server_facts['environment']server_facts[] hash will always contain the environment used for processing the node’s catalog.Always enable trusted_server_facts. Always refer to facts[factname] for client-provided facts, and server_facts[factname] for server-validated facts. Avoid using top-scope variables due to the possibility of the node-level override.
More server facts could be added by later releases of Puppet. You can see the current list at “Language: Facts and Build-in Variables” on the Puppet docs site.
As shown in the following example, Puppet servers make every configuration setting available as $::setting::setting_name:
notice("Trusted server facts are enabled: ${::settings::trusted_server_facts}")
Note that this is not a hash but a namespace, so you cannot iterate over it to output each value.
There is no equivalent access to node configuration settings by default, other than the following:
trusted['certname']facts['clientnoop']facts['agent_specified_environment']To gain access to a node’s configuration values, add a custom fact or external fact to a Puppet module, as documented in “Adding Custom Facts”.
As discussed in “Managing Files”, every file changed by a Puppet file resource, or reviewed by the audit resource, is backed up to the directory specified in the clientbucketdir configuration setting. You can view these local file backups using the puppet filebucket --local list command.
The default configuration is a single filebucket named puppet that points to the value of $clientbucketdir:
filebucket{'puppet':path=>$clientbucketdir,}File{backup=>'puppet',}
When using a Puppet server, you can move backups of file changes to the Puppet server instead. This is enabled by defining a filebucket resource with the path attribute set to false:
filebucket{'puppet.example.com':path=>false,# This is required for remote filebuckets.server=>'puppet.example.com',# defaults to the current puppet serverport=>'8140'# defaults to the current server port}
As the defaults are always the current server, if you want to back up every file to that server the simplest declaration could be:
filebucket{'local_server':path=>false,}File{backup=>'local_server',}
This resource should generally be defined in a top-scope manifest in the environment’s manifests/ directory. You can define multiple filebucket resources, and declare within the resource or in a resource default which bucket to use:
file{'/etc/sudoers':...backup=>'security-files',}
As you have seen in previous examples, the Puppet agent will send all log messages generated by the agent (according to the log level configured) to the node’s syslog facility, or a configured logfile. Agents that connect to a Puppet server will also deliver a report to the same server by default. These reports can be stored and processed in a wide variety of ways.
Some people mistakenly attempt to use log surfing programs to observe problems with Puppet configuration. This is an attempt at deducing failure based on problems seen before. I have never found this practice to satisfactorily meet the client needs. They lose hundreds of hours trying to tune every resource with a custom log level.
It is faster and easier to access the entire Puppet node report, and select the details that interest you from that report.
Don’t waste time super-tuning the log levels of every resource. Node reports provide direct access to every detail of the Puppet convergence process.
Agents communicating with a Puppet server send a node convergence report to the same server from which they received the catalog. You can change this configuration with the following parameters in /etc/puppetlabs/puppet/puppet.conf:
[agent]report=truereport_server=$serverreport_port=$masterport
The preceding settings are enabled by default, and you could leave them out to achieve the normal submission behavior. You should only add them to the Puppet configuration file if you are changing them, such as to disable the sending of reports or to specify an alternate report processor.
puppet inspect has been completely removed in Puppet 5, in favor of more powerful and flexible compliance controls that use PuppetDB data. This section is therefore historic.If you have resources defined with the audit attribute, you can run the puppet inspect command on the node to generate a node report containing the
detailed status of all audited resources. The node report will be submitted to the default Puppet server, or to the server passed on the command line:f
[vagrant@client~]$sudopuppetinspectNotice:Finishedinspectionin1.40seconds
If you are using Puppet Dashboard, you can find the inspection report under the Node details page, as shown in “Reviewing a node’s history”.
If you have enabled a server-backed file bucket, you can add the --archive_files option to back up copies of audited file resources during the inspection:
$sudopuppetinspect--archive_files--archive_file_server=puppet.example.com
The --archive_file_server argument is optional and defaults to the configured Puppet server.
If you make use of audit, you may want to run this from cron on all client nodes:
cron{'audit-file-changes':command=>'puppet inspect --archive_files',user=>'root',hour=>'0',minute=>'0',}
You can use Puppet Dashboard to review the report, or write a custom processor to analyze and compare reports. You’ll learn how to write a custom report processor in “Creating a Custom Report Processor”.
puppet inspect was broken from Puppet 3.0 until Puppet 4.4.1; see Puppet bug PUP-5233 for the patch if you have a version before 4.4.1 and get the Could not find catalog error.The default behavior of a Puppet server is to store the reports in YAML format in the directory specified by the reportdir configuration parameter. With the settings we recommend in this book, this would default to the following settings in /etc/puppetlabs/puppet/puppet.conf:
[master]reports=storereportdir=/var/opt/puppetlabs/puppetserver/reports
You can examine this directory now and see the report from the client instance. As the report directories are owned and readable only by the Puppet server, you will have to either chown() the directories or become the puppet user to read the files:
[vagrant@puppetserver~]$sudo-upuppetbashbash-4.2$cd/var/opt/puppetlabs/puppetserver/reports/bash-4.2$ls-latotal0drwxr-x---3puppetpuppet31Aug1621:23.drwxrwxr-x12puppetpuppet139Aug706:33..drwxr-x---2puppetpuppet30Aug1621:23client.example.combash-4.2$ls-laclient.example.comtotal8drwxr-x---2puppetpuppet30Aug1621:23.drwxr-x---3puppetpuppet31Aug1621:23..-rw-r-----1puppetpuppet6706Aug1621:23201508162123.yamlbash-4.2$head-10client.example.com/201508162123.yaml---!ruby/object:Puppet::Transaction::Reportmetrics:resources:!ruby/object:Puppet::Util::Metriclabel:Resourcesname:resourcesvalues:--total-Total-7--skipped
The report contains a log message for every action taken by the node, in addition to metrics about the number of resources processed, skipped, applied, or failed and the elapsed time Puppet spent evaluating and applying resources.
On the client node, you can find the same report file at /opt/puppetlabs/puppet/cache/state/last_run_report.yaml.
If you are happy with log messages on the agent nodes, or their ability to send the logs to a centralized log server using the local logger, then you don’t need the log report handler. The Puppet agent will send each message at or above the configured log level to the configured log target (the default is syslog).
If your Puppet server has access to a centralized log server unavailable to the agent nodes, or the server is functioning as a log aggregator, then it can be helpful to have the server send all agent messages to its own logs. You can enable this by adding the log action to the list of report processors in /etc/puppetlabs/puppet/puppet.conf:
[master]reports=log,store
A Puppet master will send logs to syslog by default, or the log target defined in /etc/puppetlabs/puppet/puppet.conf. Puppet Server will send logs to the targets defined in /etc/puppetlabs/puppetserver/logback.xml.
A Puppet server can be configured to submit node reports to another system. This facility is used by Puppet Dashboard and some alternative web dashboards for Puppet.
Enable transmission of node reports to a URL by adding the http action to the list of report processors, and specifying a target with with the reporturl setting in /etc/puppetlabs/puppet/puppet.conf:
[master]reports=http,storereporturl=https://puppet-dashboard.example.com/
We’ll cover installing and using Puppet Dashboard in Part IV.
You can create your own service to process reports delivered via HTTP. The data will arrive by POST method with a Content-Type of application/x-yaml. The YAML content will be the same as the contents of the file stored on disk on both the node and the master, as described earlier.
PuppetDB provides a report processor that can be used to submit node reports to the PuppetDB server. Enable transmission of node reports to PuppetDB by adding the puppetdb action to the list of report processors in /etc/puppetlabs/puppet/puppet.conf. The normal configuration for PuppetDB would look something like this:
[master]storeconfigs=truestoreconfigs_backend=puppetdbreports=puppetdb, store
This will transmit the reports to the PuppetDB server specified in the /etc/puppetlabs/puppet/puppetdb.conf. This is covered briefly in Part IV.
Previous versions of Puppet included a report processor called tagmail, which would send email messages containing log messages that matched defined tags. This was removed from the Puppet core, and is now a separate Puppet module. To use this report processor, you’ll need to do the following on the Puppet server:
[vagrant@client~]$puppetmoduleinstallpuppetlabs-tagmailNotice:Preparingtoinstallinto/etc/puppetlabs/code/environments/production/modules...Notice:Downloadingfromhttps://forgeapi.puppetlabs.com...Notice:Installing--donotinterrupt.../etc/puppetlabs/code/environments/production/modules└──puppetlabs-tagmail(v2.1.0)
After installing it on the Puppet server, create a /etc/puppetlabs/puppet/tagmail.conf file containing a map of Puppet tags and recipients.
tagmail report handler allows tags to be used for filtering changes to specific resources as well.Each line of the [tagmap] section should contain one of the following formats:
Each log entry for a resource tagged with one of these tags, or matching the log level specified, will be added to an email sent to listed recipients. Here’s an example file showing you the ideas:
[tagmap]# Log levelsall:log-archive@example.comemerg:puppet-admins@example.com# Tagsfrontend,java:fe-dev-team@example.com,java-platform@example.comdatabase,mysql:dba@example.commongodb,!database:nosql-admins@example.com[transport]reportfrom=puppetserver@example.comsendmail=/usr/sbin/sendmail# Alternative direct SMTP delivery#smtpserver = smtp-relay.example.com#smtphelo = puppet.example.com#smtpport = 25
The settings in the [transport] section of the file should be obvious to any experienced system admin. You can enable SMTP auth settings in your mailer of choice, or utilize basic SMTP delivery by enabling the smtpserver option.
Tag reports by email are useful when you limit them to watch for specific, noteworthy conditions. For example, we notify the DBAs any time a database server configuration change takes place. That’s a few dozen nodes, and it happens roughly twice a month. When a watched event happens that affects every node in an environment, you will get buried in email.
Enable transmission of email reports by adding the tagmail action to the list of report processors in /etc/puppetlabs/puppet/puppet.conf:
[master]reports=store, tagmail
More documentation for tagmail can be found at puppetlabs/tagmail on the Puppet Forge.
Custom report processors must be written in the Ruby language and follow the rules listed here. You can write a wrapper in Ruby that calls another program, as long as it works in the following manner:
require 'puppet' at the top of the script.Puppet::Reports.register_report() with a block of code, passing in its own name as a symbol as the only parameter.desc with a text or Markdown-formatted string that describes the report processor.process that does whatever you want it to do.The process method will be an object of type Puppet::Transaction::Report. It can retrieve details of the report by querying the attributes shown at “Formats: Reports” on the Puppet docs site, or get YAML data by calling the self.to_yaml() method.
Here is an example report processor that creates a different log message for each Puppet agent run. It’s not unique or helpful as it stands, but it can be used as a starting point:
require'puppet'require'syslog/logger'log=Syslog::Logger.new'logActionTime'Puppet::Reports.register_report(:logActionTime)dodesc"Sends one log message containing agent action times."defprocesssource="#{self.time}#{self.host}"action="did#{self.kind}with result#{self.status}"version="for config#{self.configuration_version}"environment="in environment#{self.environment}"log.infosource+action+version+environmentendend
For a real report processor, you’d want to explore the self.resource_statuses and self.metrics hashes, or the self.logs array.
Add this report processor to the lib/puppet/reports directory of a Puppet module. If you don’t have a more appropriate module in mind, add it to the Puppet module you created in Part II.
Enable the report processor by adding its name to the list of report processors in /etc/puppetlabs/puppet/puppet.conf:
[master]reports=store,puppetdb,logActionTime