Report Processing¶
The openvox-operator supports forwarding Puppet reports to external endpoints via the ReportProcessor CRD. Reports can be sent to PuppetDB, Splunk, Elasticsearch, or any generic HTTP webhook.
How It Works¶
flowchart LR
Agent["Puppet Agent"] -->|"report"| PS["Puppet Server"]
PS -->|"webhook.rb"| Shim["Ruby Shim"]
Shim -->|"stdin (JSON)"| Binary["openvox-report binary"]
Binary -->|"reads"| Secret["report-webhook.yaml<br/>(from Secret)"]
Binary -->|"HTTP POST"| EP1["PuppetDB"]
Binary -->|"HTTP POST"| EP2["Splunk / Elasticsearch / Webhook"]
- A Puppet Agent completes a catalog run and sends its report to Puppet Server
- Puppet Server calls the
webhookreport processor (webhook.rb) - The Ruby shim serializes the report as JSON and pipes it to the
openvox-reportbinary via stdin - The binary reads its endpoint configuration from
report-webhook.yaml(mounted from a Secret) - For each configured endpoint, the binary transforms (if needed) and forwards the report via HTTP POST
Multiple ReportProcessors can reference the same Config. All endpoints receive every report.
Architecture¶
The report processing pipeline is split into two stages:
Stage 1: Ruby Shim (webhook.rb)¶
The Ruby shim is a Puppet report processor that bridges Puppet Server's internal report mechanism to the Go binary. It:
- Registers as a Puppet report processor named
webhook - Calls
self.to_data_hash.to_jsonto serialize the full report - Pipes the JSON to
/opt/puppetlabs/server/bin/openvox-reportvia stdin - Has a 120-second timeout to prevent Puppet Server thread blocking
The shim is intentionally thin -- it contains no endpoint-specific logic.
Stage 2: Go Binary (openvox-report)¶
The Go binary handles transformation, authentication, and HTTP delivery:
- Reads endpoint configuration from
/etc/puppetlabs/puppet/report-webhook.yaml - For
processor: puppetdb: transforms the report to PuppetDB Wire Format v8 - For generic endpoints: forwards the report JSON as-is
- Supports mTLS, Bearer, Basic, and custom token authentication
- Reports errors on stderr (visible in Puppet Server logs)
Processor Types¶
Generic (default)¶
When processor is empty (or omitted), the report JSON from to_data_hash is forwarded as-is. This works for any endpoint that accepts Puppet report JSON, such as Splunk HEC, Elasticsearch, or custom webhooks.
PuppetDB¶
When processor: puppetdb is set, the binary transforms the report from Puppet's to_data_hash format to PuppetDB Wire Format v8. Key transformations include:
to_data_hash field |
Wire Format v8 field | Notes |
|---|---|---|
host |
certname |
Agent's certname (same value, different key) |
time |
start_time |
Report start time |
| (calculated) | end_time |
start_time + metrics.time.total |
| (added) | producer |
From server_used or host as fallback |
| (added) | producer_timestamp |
Current time at submission |
resource_statuses (map) |
resources (array) |
Keys dropped, title → resource_title, time → timestamp |
metrics (nested hash) |
metrics (flat array) |
[{category, name, value}] format |
Events: desired_value |
Events: new_value |
Converted to string |
Events: previous_value |
Events: old_value |
Converted to string |
The transformed report is wrapped in a command envelope and POSTed to <url>/pdb/cmd/v1:
Authentication Methods¶
| Method | Description | Use Case |
|---|---|---|
mtls |
Mutual TLS using Puppet SSL certificates | PuppetDB with Puppet CA trust |
token |
Custom HTTP header with token value | Services with custom auth headers |
bearer |
Authorization: Bearer header | Generic API services |
basic |
HTTP Basic Authentication | Elasticsearch, legacy services |
At most one authentication method may be configured per ReportProcessor.
Config Integration¶
When at least one ReportProcessor references a Config, the operator automatically:
- Adds
webhookto thereportssetting in puppet.conf - Renders
report-webhook.yamlinto a Secret and mounts it into Server pods - Triggers a rolling restart via annotation hash when the configuration changes
apiVersion: openvox.voxpupuli.org/v1alpha1
kind: Config
metadata:
name: production
spec:
authorityRef: production-ca
image:
repository: ghcr.io/slauger/openvox-server
tag: "8.12.1"
apiVersion: openvox.voxpupuli.org/v1alpha1
kind: ReportProcessor
metadata:
name: openvoxdb
spec:
configRef: production
processor: puppetdb
url: "https://openvoxdb:8081"
auth:
mtls: true
No changes to the Config resource are needed -- the operator detects ReportProcessors via configRef and injects the report processor configuration automatically.
For the full CRD reference, see ReportProcessor.