Skip to content

Add a compiler VM, and put pp_role in every certificate - #63

Merged
miharp merged 1 commit into
productionfrom
feat/compiler-vm
Jul 25, 2026
Merged

Add a compiler VM, and put pp_role in every certificate#63
miharp merged 1 commit into
productionfrom
feat/compiler-vm

Conversation

@miharp

@miharp miharp commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Two changes that only make sense together, and groundwork for codavox — which distributes code to compilers, and this estate had none.

Every certificate now carries a pp_role

Written into csr_attributes.yaml before enrolment:

node pp_role
puppet openvox_server
compiler openvox_compiler
agent01, agent02 openvox_agent

It has to happen at provisioning because pp_role is an X.509 extension — it cannot be added to a signed certificate afterwards without re-issuing it. On the primary that means replacing the certificate puppetserver is actively serving with, so doing it from first boot makes a rebuilt estate correct by construction instead of needing a repair step.

Why it matters: role is the only thing separating "this node holds a certificate from our CA" from "this node is allowed to do X", and every agent in the estate clears the first bar. codavox's publisher refuses a peer without an allowed pp_role; auth.conf works the same way.

The compiler

Runs the same openvox-server package as the primary and differs in what it may do: CA service disabled, enrolled against the primary, so the estate keeps exactly one authority. That is set up in provisioning because it must be in place before the node holds a certificate at all.

Modelled on codavox's integration harness, which stands up the same shape and is known to work.

Verification

onceover — all five roles compile, including the new one:

role::compiler:        P
role::database_server: P P
role::example:         P P
role::puppet_master:   P
role::webserver:       P P

role::compiler runs against a new factset derived from the primary's — same OS and architecture — with identity facts and the pp_role trusted extension corrected.

The Vagrantfile parses (ruby -c), and the compiler's provisioner was extracted and shellcheck'd clean at warning level, since a syntactically valid Ruby heredoc can still contain broken shell.

profile lint and validate clean.

Deliberately not included

  • inventory.yaml — Bolt validation targets the agents, and reaching the compiler would also need the bolt key authorization the agent provisioners set up. Both together, if wanted.
  • The role module's pre-existing whitespace lint errors in database_server.pp, example.pp and webserver.pp. Identical on clean production; compiler.pp contributes none.

Next

This is what codavox needs to be worth wiring in: a publisher on the primary distributing to a real compiler, rather than a primary serving itself. That PR follows.

Two changes that only make sense together.

Every node's certificate now carries a pp_role, written into
csr_attributes.yaml before enrolment: openvox_server on the primary,
openvox_compiler on the new node, openvox_agent on the agents. It has to
happen there because pp_role is an X.509 extension — it cannot be added
to a signed certificate afterwards without re-issuing it, which on the
primary means replacing the certificate puppetserver is currently serving
with. Provisioning it from first boot makes a rebuilt estate correct by
construction rather than needing a repair step.

That matters because authorization by role is the only thing separating
'this node holds a certificate from our CA' from 'this node is allowed to
do X', and every agent in the estate clears the first bar. The immediate
consumer is codavox, whose publisher refuses a peer without an allowed
pp_role, but auth.conf works the same way.

The compiler runs the same openvox-server package as the primary and
differs in what it may do: its CA service is disabled and it enrols
against the primary, so the estate keeps exactly one authority. That
setup happens in provisioning because it has to be in place before the
node holds a certificate at all. Modelled on codavox's own integration
harness, which stands up the same shape and is known to work.

onceover covers it: role::compiler compiles against a new factset derived
from the primary's, since they are the same OS and architecture, with the
identity facts and the pp_role trusted extension corrected. All five roles
still pass.

Not included: the compiler is absent from inventory.yaml, because Bolt
validation targets the agents and reaching the compiler would also need
the bolt key authorization the agent provisioners do. Add both together if
that is wanted.

The role module's pre-existing whitespace lint errors are untouched and
unrelated; compiler.pp contributes none.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@miharp
miharp merged commit b572676 into production Jul 25, 2026
3 checks passed
miharp added a commit that referenced this pull request Jul 26, 2026
)

Reverts #63, #64, and #65: the compiler VM, the pp_role csr_attributes, and all
the codavox wiring. The tree is now identical to 0a7c5f8 apart from one Puppetfile
line.

This repo is a dev environment — an edit to production has to appear on the next
agent run with no deploy step. codavox distributes sealed, immutable,
content-addressed versions. The two models are structurally opposed, and
everything added to reconcile them was paying for the mismatch: a directory of
environments nested inside an environment so the publisher had something other
than the working tree to seal; a working tree that cannot be sealed at all,
because .onceover/ holds rspec-puppet fixture symlinks pointing at absolute macOS
host paths; a compiler that could never serve production, since codavox replaces
environmentpath rather than adding to it; and static catalogs turned off on the
primary, a real capability lost purely to the conflict.

The compiler VM goes too. Without codavox it had no code — no synced mount, and a
stock empty production skeleton — so it installed openvox-server on a node that
could only compile empty catalogs. codavox was the only thing that ever fed it.

codavox validation moves to a control repo built for it, where r10k deploys a
clean tree and static catalogs stay on.

puppetlabs/yumrepo_core is kept because it is the one fix here that had nothing
to do with codavox. yumrepo left Puppet core, and while
site-modules/profile/.fixtures.yml already declared it for the module's own specs,
the control repo never shipped it — so onceover could not compile any RedHat role,
failing with "Unknown resource type: 'yumrepo'". Real nodes were unaffected
because openvox-agent bundles it, which is why it went unnoticed.

Verified: onceover passes all four remaining roles, and the profile suite is back
to 96 examples with no failures.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant