Skip to content

feat(security): replace the leaked CA, and add tooling to issue certs - #34

Merged
Gerrrt merged 1 commit into
mainfrom
feat/cert-tooling
Aug 19, 2026
Merged

feat(security): replace the leaked CA, and add tooling to issue certs#34
Gerrrt merged 1 commit into
mainfrom
feat/cert-tooling

Conversation

@Gerrrt

@Gerrrt Gerrrt commented Aug 19, 2026

Copy link
Copy Markdown
Owner

Replaces the CA and leaf keys that were purged from history, and adds the tooling to issue more.

What changed

  • scripts/gen-certs.sh — create the CA, issue leaves, list what exists
  • make certs ARGS=...
  • docs/runbooks/generate-certificates.md
  • certificates/ added to the never-tracked assertions in CI and validate.sh
  • certificates/ and .rendered/ allowlisted for the gitleaks filesystem scan

Why

The old CA and leaf keys were committed to a public repository and removed by
rewriting every commit. They have to be treated as compromised, so they needed
replacing — and there was no tooling at all, which is how a lab ends up
improvising a CA on the day something needs one.

Nothing terminates TLS yet. Prometheus, Alertmanager, Loki and Grafana all
publish plain HTTP. So this deliberately promises nothing: it creates the CA
deliberately and once, and the Grafana-TLS roadmap item now reads as wiring
rather than PKI.

Naming follows the lab as it is today — matrix.elysium, matching pfSense’s own
hostname — rather than the Gandalf.Gondor.Lab of the leaked set.

Two failure modes the script enforces rather than lets you discover

  • No subjectAltName → rejected outright by every current browser and by
    Go’s crypto/tls, which is what this stack is built on. The error names the
    Common Name field and reads like a trust problem rather than a missing one.
  • Leaf lifetime over 825 days → rejected by browsers. A ten-year leaf looks
    like less future work and produces something nothing will trust.

Every issued certificate is verified against the CA before success is reported.

Two gaps the original leak should have taught us

certificates/ was not on the never-tracked list — the one directory whose
contents forced a history rewrite. Now asserted by CI and make validate.

make validate was permanently red on any host that had actually deployed.
The gitleaks filesystem scan reported 8 findings — the new CA and leaf keys, and
the decrypted SNMP communities in .rendered/. All gitignored, all working as
designed, none visible to CI because it scans a fresh checkout. Allowlisting
them is not a weakening: gitleaks was never the control there, never becoming a
tracked file is, and that is asserted directly. A check that is permanently red
for a known reason is a check nobody reads — the same argument that retired
.gitleaksignore.

Blast radius

Nothing deployed changes. No service, no config, no port, no credential in
secrets/. The generated keys are gitignored and local to the monitoring host.

  • No change to network segmentation or firewall rules
  • No new port published to a VLAN that could not already reach the service
  • No credential added outside secrets/*.sops.yaml

Verification

$ make certs ARGS=--ca            # refuses a second time without --force
$ make certs ARGS="--host grafana.matrix.elysium --ip 10.0.99.20"
$ make certs ARGS=--list
  ca.pem                       valid  until Aug 16 2036
  grafana.matrix.elysium.pem   valid  until Nov 21 2028

Certificate checked by hand, not just by exit status: SAN carries both
DNS:grafana.matrix.elysium and IP:10.0.99.20; basicConstraints CA:FALSE
critical; keyUsage digitalSignature + keyEncipherment; EKU serverAuth; chain
verifies against the CA; public key matches the private key. CA is CA:TRUE, pathlen:0 with keyCertSign/cRLSign.

Guard rails exercised: leaf-before-CA refused, CA clobber refused, leaf clobber
refused, --days 3650 refused.

./scripts/validate.sh passes. gitleaks clean on both the working tree (with
the keys present on disk) and full history. shellcheck and
markdownlint-cli2 clean. Nothing under certificates/ appears in
git status.

  • make validate passes
  • Deployed to the lab and confirmed working
  • Docs updated

The previous CA and leaf keys were committed to a public repository and removed
by rewriting every commit. This replaces them and makes issuing a certificate a
command rather than a research project.

scripts/gen-certs.sh creates the CA once, issues leaves signed by it, and lists
what exists with expiry. It refuses to clobber an existing CA — regenerating one
invalidates every leaf it has signed and every trust store holding it — and
verifies each issued certificate against the CA before reporting success, so a
chain that does not build fails at issue time rather than at deploy time.

Two limits are enforced rather than left to be discovered. A certificate with no
subjectAltName is rejected by every current browser and by Go's crypto/tls,
which is what Prometheus, Alertmanager and Grafana are built on; the error names
the Common Name field and reads like a trust problem. And leaf lifetimes over
825 days are rejected by browsers, so a ten-year leaf looks like less future
work and produces something nothing will trust.

Naming follows the lab as it exists now — matrix.elysium, matching pfSense's own
hostname — rather than the Gandalf.Gondor.Lab of the leaked set.

Nothing terminates TLS yet, so this issues no promises: Grafana is the first
candidate and that roadmap item now says wiring rather than PKI.

Also closes two gaps the leak should have already taught us:

certificates/ is added to the never-tracked assertion in CI and validate.sh. It
is the one directory whose contents forced a history rewrite and it was not on
that list.

certificates/ and .rendered/ are allowlisted for the gitleaks filesystem scan.
Both hold real secrets on purpose and are gitignored, so on any host that has
actually deployed the scan reported eight findings that were all working as
designed. CI scans a fresh checkout and never saw them. gitleaks was never the
control there — never becoming a tracked file is, and that is asserted directly.

Refs docs/runbooks/generate-certificates.md
@Gerrrt
Gerrrt merged commit b658ece into main Aug 19, 2026
3 checks passed
@Gerrrt
Gerrrt deleted the feat/cert-tooling branch August 19, 2026 21:42
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