Secure Puppet agent and server communication through SSL certificates, certificate signing, and autosign. Learn RBAC and the node classifier in Puppet Enterprise, plus secret storage with Hiera eyaml.

In episode 12 you learned how Code Manager and r10k manage environments from git so Puppet code is well controlled. But tidy code doesn't mean secure infrastructure. Unmanaged certificates, nodes allowed in without verification, and secrets sitting in manifests are a recipe for disaster.
Puppet uses X.509-based PKI to ensure communication between agents and the server is always encrypted and authenticated. On the other side, user access control for the console is managed by RBAC (Role-Based Access Control) in Puppet Enterprise. And for sensitive data like passwords, we use Hiera with eyaml encryption.
In this episode we'll cover the SSL certificate flow, the puppetserver ca commands, the autosign concept, secure agent-server communication, RBAC and the node classifier in PE, and storing secrets with Hiera eyaml.
When a Puppet agent runs for the first time, it creates a certificate signing request (CSR) and sends it to the server. The server doesn't trust the agent immediately; the internal certificate authority (CA) on the server must sign the CSR first.
1. Agent : create key + CSR, send to server
2. Server : internal CA signs the CSR
3. Server : send the signed certificate to the agent
4. Agent : SSL communication begins securelyOn the server, you can see the list of CSRs awaiting signing:
puppetserver ca listAfter confirming the node name is correct, sign it:
puppetserver ca sign --certname web01.example.comOn the agent side, certificate status can be verified with puppet ssl show, and when the certificate has issues you can re-request it with puppet ssl bootstrap.
Note
The puppet ssl syntax was introduced in Puppet 6.4 and replaces the old puppet certificate and puppet cert commands. On the server, all CA operations are now grouped under the puppetserver ca command.
Manual signing for one or two nodes is still fine, but when you spin up many ephemeral instances, for example for autoscaling, manual signing becomes a bottleneck. Puppet provides autosign so CSRs are signed automatically based on certain rules.
The simplest way is an autosign.conf file with hostname patterns:
*.infra.example.com
loadtest*.example.comWarning
Never make autosign too permissive. Autosign that accepts every node name lets anyone who can guess a hostname send a fake catalog and take over a node. Restrict it to internal hostname patterns you actually control.
For JVM-based puppetserver, you can point to an external script that validates a token or cloud metadata before signing:
autosign:
mode: external
script: /usr/local/bin/policy-autosign.shCertificate errors are the most common reason agents fail to talk to the server. The two most frequent cases:
SSL_connect returned=1 errno=0 peer did not return a certificate.server_list or server setting in the agent's puppet.conf.A quick fix for a wrong node: remove the certificate on the agent and re-request it.
puppet ssl clean
puppet ssl bootstrapIn Puppet Enterprise, console access is managed via RBAC. Each user belongs to a group with specific permissions, for example the Operators role may only view nodes, while Code Deployers may run code deploys.
| Role | Capabilities |
|---|---|
| Administrators | Full console and API access |
| Code Deployers | Deploy code environments |
| Operators | View nodes, run status, and reports |
| Viewers | Read-only, no actions |
Under the hood, the console uses the node classifier to determine which classes are applied to which nodes. Fact-based rules can group nodes, for example all nodes with the Linux kernel and a specific custom fact go into a certain group.
{
"name": "Web Servers",
"rule": ["and", ["=", ["fact", "kernel"], "Linux"], ["=", ["fact", "is_web"], true]],
"classes": {
"profile::webserver": {}
}
}Nodes belonging to several groups receive classes from all of those groups. The Classification page in the console stores these rules as structured data, not as hardcoded manifests.
Hiera stores hierarchical data, but storing passwords in plain text in a repository is a serious violation. The solution is hiera-eyaml, which allows selectively encrypting values inside data files.
First, make sure the eyaml plugin is installed on the server and agents:
gem install hiera-eyamlTo create a key pair:
eyaml createkeysTo encrypt a value:
eyaml encrypt -s 's3cr3t-password'The encrypted result goes into a hieradata file:
profile::db::password: >-
ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCC...]Important
The eyaml private key must stay secret and be deployed securely to the Puppet server, never committed to the control repository. The public key can be shared so developers can encrypt new values without being able to decrypt them. In Puppet Enterprise, the private key lives at /etc/puppetlabs/puppet/eyaml/private_key.pkcs7.pem.
The presence of the ENC[...] marker keeps code review working: developers can see that secrets exist there, but their contents are unreadable in git.
In this episode 13 you understood that Puppet security is layered: SSL certificates secure agent-server communication, autosign accelerates new node provisioning in a controlled way, RBAC limits who can touch the PE console, and Hiera eyaml keeps secrets encrypted in the repository.
Key takeaways:
puppetserver ca sign.So far we've mostly used modules we wrote ourselves. But in the real world, most of the work happens on top of public modules. In episode 14 we'll cover Learn Puppet - Modules & Forge: finding quality modules on Puppet Forge, evaluating their maintainers, and developing your own modules with PDK.