rotate: 4 SaaS-token/app-signing drivers + data-separated proof tracking
Add gitlab, cloudflare, ghactions (MOCK-ONLY) and appsecret (LIVE-VM) one-file Rotators, each with a table-driven cutover-proof + leak-check test. gitlab/ cloudflare/ghactions are in-place SaaS-token rolls (self/rotate, value-roll, sealed-secret overwrite) so RevokeOld is a no-op; ghactions seals via nacl/box.SealAnonymous (no new go.mod dep). appsecret regenerates a local app signing secret and rewrites it in place across every target file (atomic, mode- preserving, redacted errors), discoverable via exact-match app-signing key names in env.go. Keep real-rotation code distinct from mock code: how each driver's cutover was validated lives as DATA in internal/rotate/proofs.go (single source of truth) + docs/ROTATION-PROOFS.md, surfaced as a PROOF column in `incredigo rotate` so a MOCK-ONLY driver can never be mistaken for a LIVE-VM one. appsecret proven LIVE-VM against real local files in the sandbox VM. 82 tests green, -race clean on rotate/sink/vault. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
package rotate
|
||||
|
||||
// Proof tracking — DATA, deliberately kept OUT of the driver code.
|
||||
//
|
||||
// Every Rotator in this package contains ONLY real rotation code: it talks to a
|
||||
// real service (HTTP API, DB client, SSH, local files). None of them contain
|
||||
// simulation branches or test awareness — the only thing a test injects is an
|
||||
// endpoint/HTTPClient, which the real deployment also configures.
|
||||
//
|
||||
// What differs between drivers is HOW their real-cutover path has been *validated*.
|
||||
// That validation status is data, not behavior, so it lives here in one table
|
||||
// rather than as prose scattered through (and easily confused with) the drivers.
|
||||
// docs/ROTATION-PROOFS.md is the human-facing mirror of this same data; `incredigo
|
||||
// rotate` surfaces it so a mock-only driver can never be mistaken for a live one.
|
||||
|
||||
// ProofLevel records how a driver's real-cutover behaviour has been validated.
|
||||
type ProofLevel int
|
||||
|
||||
const (
|
||||
// ProofUnproven: no cutover proof recorded (e.g. the dry-run noop helper).
|
||||
ProofUnproven ProofLevel = iota
|
||||
// ProofMockOnly: cutover proven only against an emulator — our own httptest /
|
||||
// in-process SSH server, OR a third-party mock (e.g. moto for AWS). NOT proven
|
||||
// against the real target service.
|
||||
ProofMockOnly
|
||||
// ProofLiveVM: cutover proven against the REAL target software running in the
|
||||
// sandbox VM (real PostgreSQL/MariaDB/Redis/wireguard-tools/Gitea/local files).
|
||||
ProofLiveVM
|
||||
)
|
||||
|
||||
// String renders the level as the token shown in the CLI and the manifest.
|
||||
func (p ProofLevel) String() string {
|
||||
switch p {
|
||||
case ProofLiveVM:
|
||||
return "LIVE-VM"
|
||||
case ProofMockOnly:
|
||||
return "MOCK-ONLY"
|
||||
default:
|
||||
return "UNPROVEN"
|
||||
}
|
||||
}
|
||||
|
||||
// proofLevels maps a driver's Name() to how its real-cutover path was validated.
|
||||
// This is the single source of truth; keep docs/ROTATION-PROOFS.md in sync.
|
||||
//
|
||||
// IMPORTANT honesty note: a driver running in the VM is NOT automatically LIVE-VM.
|
||||
// AWS ran in the VM but only against moto (a mock AWS), so it is MOCK-ONLY. LIVE-VM
|
||||
// means the real target software validated the cutover.
|
||||
var proofLevels = map[string]ProofLevel{
|
||||
// proven against the real target software in the sandbox VM:
|
||||
"postgres": ProofLiveVM, // real PostgreSQL (lab-provision-pg.sh)
|
||||
"mysql": ProofLiveVM, // real MariaDB (lab-provision-dbclones.sh)
|
||||
"redis": ProofLiveVM, // real redis-server(lab-provision-dbclones.sh)
|
||||
"wireguard": ProofLiveVM, // real wg (lab-provision-wg.sh)
|
||||
"gitea": ProofLiveVM, // real Gitea (lab-provision-gitea.sh)
|
||||
"appsecret": ProofLiveVM, // real local files (lab-provision-appsec.sh)
|
||||
|
||||
// proven only against an emulator / mock:
|
||||
"aws": ProofMockOnly, // moto mock AWS in VM; real AWS never hit
|
||||
"sshkey": ProofMockOnly, // in-process SSH server; live VM POC not run
|
||||
"openwrt": ProofMockOnly, // in-process SSH server; live QEMU deferred
|
||||
"mullvad": ProofMockOnly, // httptest emulator; needs a paid account
|
||||
"cloudflare": ProofMockOnly, // httptest emulator; no self-host
|
||||
"ghactions": ProofMockOnly, // httptest emulator; no self-host
|
||||
"gitlab": ProofMockOnly, // httptest emulator; GitLab CE too heavy for the VM
|
||||
}
|
||||
|
||||
// ProofLevelOf returns the recorded proof level for a driver name. Unknown or
|
||||
// proofless drivers (e.g. the noop dry-run helper) report ProofUnproven.
|
||||
func ProofLevelOf(name string) ProofLevel { return proofLevels[name] }
|
||||
Reference in New Issue
Block a user