Files
privatae-bastion/client-go/baselinesign_test.go
T
Privatae e4c9b69b46
ci / personal-data (push) Successful in 5s
ci / test (push) Successful in 3m4s
ci / fuzz (push) Successful in 3m45s
bastion 0.53.2
2026-10-20 04:42:14 +00:00

952 lines
37 KiB
Go

package main
// baselinesign_test.go — the accounting's signature.
//
// EVERY TEST HERE BUILDS A REAL CA AND A REAL LEAF with crypto/x509, the way
// the bridge issues an operator certificate, and drives baselineSave /
// baselineLoad / baselineVerify on the resulting files. None asserts a value it
// supplied a seam above the code under test.
//
// The last test is a FIXTURE GENERATOR: when BASELINE_FIXTURE_OUT names a
// directory it writes a signed accounting, the CA and the fingerprint there.
// The host-side test suite verifies THAT artefact — so the two
// languages are checked against one signed document, not each against its own
// fake. That is the cross-language claim baselinesign.go rests on, and it is
// tested rather than asserted.
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
"crypto/x509"
"crypto/x509/pkix"
"encoding/base64"
"encoding/json"
"encoding/pem"
"fmt"
"math/big"
"net/url"
"os"
"path/filepath"
"strings"
"testing"
"time"
)
// fixtureNotBefore is the start of every fixture certificate's validity: well
// before sampleBaseline's taken_at, so the accounting never predates its own
// certificate.
var fixtureNotBefore = time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
// signingFixture is a CA, a leaf issued by it carrying the fingerprint SAN the
// bridge puts in an operator certificate, and the leaf's key — the same shape
// pair.go's CSR and the bridge's issuance produce.
type signingFixture struct {
caPEM, leafPEM, keyPEM string
fp string
}
func newSigningFixture(t *testing.T, fp string) signingFixture {
t.Helper()
uris, err := fpURIs(fp, true)
if err != nil {
t.Fatal(err)
}
return newSigningFixtureWithURIs(t, fp, uris)
}
// newSigningFixtureWithURIs issues the leaf with exactly these URI SANs, for
// the certificates a platform or an older Host issues.
func newSigningFixtureWithURIs(t *testing.T, fp string, uris []*url.URL) signingFixture {
t.Helper()
caKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
t.Fatal(err)
}
caTpl := &x509.Certificate{
SerialNumber: big.NewInt(1), Subject: pkix.Name{CommonName: "test CEIGAS CA"},
// VALID ACROSS THE SAMPLE'S taken_at. Both verifiers judge the
// certificate at the moment the accounting was taken, and the sample is
// stamped 2026-09-19T10:00:00Z — a certificate minted "now minus an hour"
// post-dated the accounting and every host-side test failed with
// cert_not_valid, which was the fixture's fault, not the verifier's.
NotBefore: fixtureNotBefore, NotAfter: fixtureNotBefore.Add(10 * 365 * 24 * time.Hour),
IsCA: true, BasicConstraintsValid: true,
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageDigitalSignature,
}
caDER, err := x509.CreateCertificate(rand.Reader, caTpl, caTpl, &caKey.PublicKey, caKey)
if err != nil {
t.Fatal(err)
}
caCert, _ := x509.ParseCertificate(caDER)
leafKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
t.Fatal(err)
}
leafTpl := &x509.Certificate{
SerialNumber: big.NewInt(2), Subject: pkix.Name{CommonName: "operator"},
NotBefore: fixtureNotBefore, NotAfter: fixtureNotBefore.Add(10 * 365 * 24 * time.Hour),
KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
URIs: uris,
}
leafDER, err := x509.CreateCertificate(rand.Reader, leafTpl, caCert, &leafKey.PublicKey, caKey)
if err != nil {
t.Fatal(err)
}
keyDER, _ := x509.MarshalECPrivateKey(leafKey)
return signingFixture{
caPEM: string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: caDER})),
leafPEM: string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: leafDER})),
keyPEM: string(pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: keyDER})),
fp: fp,
}
}
// newChainedSigningFixture is the shape a real pairing holds: the pairing's CA
// is the ROOT, the operator certificate is issued by an INTERMEDIATE, and
// operator_cert carries the leaf followed by that intermediate — twice, as the
// bridge returns it on the fleet. newSigningFixture issues the leaf straight
// from the CA, which is why every test passed while every real accounting was
// refused as "not issued by this pairing's CA".
func newChainedSigningFixture(t *testing.T, fp string) signingFixture {
t.Helper()
uris, err := fpURIs(fp, true)
if err != nil {
t.Fatal(err)
}
return newChainedSigningFixtureWithURIs(t, fp, uris)
}
// newChainedSigningFixtureWithURIs is newChainedSigningFixture with the leaf's
// URI SANs chosen by the caller.
func newChainedSigningFixtureWithURIs(t *testing.T, fp string, uris []*url.URL) signingFixture {
t.Helper()
key := func() *ecdsa.PrivateKey {
k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
t.Fatal(err)
}
return k
}
issue := func(tpl, parent *x509.Certificate, pub *ecdsa.PublicKey, signer *ecdsa.PrivateKey) (*x509.Certificate, []byte) {
tpl.NotBefore, tpl.NotAfter = fixtureNotBefore, fixtureNotBefore.Add(10*365*24*time.Hour)
if parent == nil {
parent = tpl
}
der, err := x509.CreateCertificate(rand.Reader, tpl, parent, pub, signer)
if err != nil {
t.Fatal(err)
}
c, _ := x509.ParseCertificate(der)
return c, der
}
rootKey, interKey, leafKey := key(), key(), key()
root, rootDER := issue(&x509.Certificate{SerialNumber: big.NewInt(1), Subject: pkix.Name{CommonName: "test Root CA"},
IsCA: true, BasicConstraintsValid: true, KeyUsage: x509.KeyUsageCertSign}, nil, &rootKey.PublicKey, rootKey)
inter, interDER := issue(&x509.Certificate{SerialNumber: big.NewInt(2), Subject: pkix.Name{CommonName: "test Entity Intermediate"},
IsCA: true, BasicConstraintsValid: true, MaxPathLenZero: true, KeyUsage: x509.KeyUsageCertSign}, root, &interKey.PublicKey, rootKey)
_, leafDER := issue(&x509.Certificate{SerialNumber: big.NewInt(3), Subject: pkix.Name{CommonName: "operator"},
KeyUsage: x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
BasicConstraintsValid: true, URIs: uris}, inter, &leafKey.PublicKey, interKey)
enc := func(der []byte) string {
return string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: der}))
}
keyDER, _ := x509.MarshalECPrivateKey(leafKey)
return signingFixture{
caPEM: enc(rootDER),
leafPEM: enc(leafDER) + enc(interDER) + enc(interDER),
keyPEM: string(pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: keyDER})),
fp: fp,
}
}
// chainFixture issues root -> interCA[0] -> interCA[1] ... -> leaf, where each
// entry says whether that intermediate is a CA. The chain PEM is the leaf
// followed by the intermediates, nearest first. For the shapes the fleet never
// sends and both verifiers must refuse the same way.
func chainFixture(t *testing.T, fp string, interCA []bool) signingFixture {
t.Helper()
key := func() *ecdsa.PrivateKey {
k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
t.Fatal(err)
}
return k
}
serial := int64(1)
issue := func(tpl, parent *x509.Certificate, pub *ecdsa.PublicKey, signer *ecdsa.PrivateKey) (*x509.Certificate, []byte) {
tpl.SerialNumber = big.NewInt(serial)
serial++
tpl.NotBefore, tpl.NotAfter = fixtureNotBefore, fixtureNotBefore.Add(10*365*24*time.Hour)
tpl.BasicConstraintsValid = true
if parent == nil {
parent = tpl
}
der, err := x509.CreateCertificate(rand.Reader, tpl, parent, pub, signer)
if err != nil {
t.Fatal(err)
}
c, _ := x509.ParseCertificate(der)
return c, der
}
enc := func(der []byte) string {
return string(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: der}))
}
rootKey := key()
parent, rootDER := issue(&x509.Certificate{Subject: pkix.Name{CommonName: "chain root"},
IsCA: true, KeyUsage: x509.KeyUsageCertSign}, nil, &rootKey.PublicKey, rootKey)
parentKey := rootKey
var inters []string
for i, isCA := range interCA {
k := key()
tpl := &x509.Certificate{Subject: pkix.Name{CommonName: fmt.Sprintf("chain intermediate %d", i)}, IsCA: isCA}
if isCA {
tpl.KeyUsage = x509.KeyUsageCertSign
}
c, der := issue(tpl, parent, &k.PublicKey, parentKey)
inters = append([]string{enc(der)}, inters...)
parent, parentKey = c, k
}
leafKey := key()
fpURIList, _ := fpURIs(fp, true)
_, leafDER := issue(&x509.Certificate{Subject: pkix.Name{CommonName: "operator"},
KeyUsage: x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
URIs: fpURIList}, parent, &leafKey.PublicKey, parentKey)
keyDER, _ := x509.MarshalECPrivateKey(leafKey)
return signingFixture{
caPEM: enc(rootDER),
leafPEM: enc(leafDER) + strings.Join(inters, ""),
keyPEM: string(pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: keyDER})),
fp: fp,
}
}
// writeSigningPairing installs one active pairing holding the fixture's key,
// cert, CA and fingerprint — what `pair` writes at redeem.
func writeSigningPairing(t *testing.T, host string, fx signingFixture) {
t.Helper()
pd, err := pairingsDir()
if err != nil {
t.Fatal(err)
}
cfg := Config{HostName: host, OperatorKey: fx.keyPEM, OperatorCert: fx.leafPEM,
CACert: fx.caPEM, Fingerprint: fx.fp, State: pairingActive}
b, _ := json.MarshalIndent(cfg, "", " ")
if err := os.WriteFile(filepath.Join(pd, host+".json"), b, 0o600); err != nil {
t.Fatal(err)
}
}
func sampleBaseline() baselineFile {
return baselineFile{
Version: baselineVersion, TakenAt: "2026-09-19T10:00:00Z",
Coverage: "processes=all,schedulers=all",
Entries: []baselineEntry{
{FP: "aaa", Kind: "process", Exe: "/usr/sbin/sshd", ExeDigest: "sha256:aaa",
User: "root", Unit: "ssh.service", ArgvShape: "sshd -D"},
// A path with characters both encoders must agree on: a quote, a
// backslash, a non-ASCII rune, and the HTML characters Go escapes by
// default and this scheme turns off.
{FP: "bbb", Kind: "process", Exe: `/opt/naïve <app> & "co"\bin`, ExeDigest: "sha256:bbb",
User: "alice", ArgvShape: "app --serve", Endpoints: []string{"http://127.0.0.1:11434"}},
},
Unreadable: 3,
}
}
func TestASavedAccountingIsSignedAndVerifies(t *testing.T) {
isolateConfigDir(t)
fx := newSigningFixture(t, "fp-one")
writeSigningPairing(t, "one.host.privatae.ai", fx)
if err := baselineSave(sampleBaseline()); err != nil {
t.Fatal(err)
}
f, digestOK, err := baselineLoad()
if err != nil || !digestOK {
t.Fatalf("load: ok=%v err=%v", digestOK, err)
}
if f.Attestation == nil {
t.Fatalf("the accounting was written unsigned: %q", f.UnsignedReason)
}
if f.Attestation.SignedBy != "one.host.privatae.ai" || f.Attestation.Alg != baselineSigAlg {
t.Fatalf("attestation names %+v", f.Attestation)
}
ok, note := baselineVerify(f, fx.caPEM, fx.fp)
if !ok {
t.Fatalf("a freshly signed accounting did not verify: %s", note)
}
if n := baselineAttestationNote(f); n != "" {
t.Fatalf("the on-disk check disagrees with the direct one: %q", n)
}
}
// The self-digest and the attestation answer two questions and must not be
// coupled: signing must not change the digest, and the digest must not cover
// the signature.
func TestTheDigestDoesNotCoverTheAttestation(t *testing.T) {
isolateConfigDir(t)
fx := newSigningFixture(t, "fp-one")
writeSigningPairing(t, "one.host.privatae.ai", fx)
unsigned := sampleBaseline()
d1, _ := baselineDigestOf(unsigned)
if err := baselineSave(unsigned); err != nil {
t.Fatal(err)
}
f, ok, _ := baselineLoad()
if !ok {
t.Fatal("digest broke on save")
}
if f.Digest != d1 {
t.Fatalf("signing changed the digest: %s -> %s", d1, f.Digest)
}
}
func TestEditedContentFailsTheSignatureAndNamesTheReason(t *testing.T) {
isolateConfigDir(t)
fx := newSigningFixture(t, "fp-one")
writeSigningPairing(t, "one.host.privatae.ai", fx)
if err := baselineSave(sampleBaseline()); err != nil {
t.Fatal(err)
}
p, _ := baselinePath()
b, _ := os.ReadFile(p)
edited := strings.Replace(string(b), `"unreadable": 3`, `"unreadable": 0`, 1)
if edited == string(b) {
t.Fatal("the fixture edit did not apply, so this test proves nothing")
}
if err := os.WriteFile(p, []byte(edited), 0o600); err != nil {
t.Fatal(err)
}
f, _, err := baselineLoad()
if err != nil {
t.Fatal(err)
}
ok, note := baselineVerify(f, fx.caPEM, fx.fp)
if ok {
t.Fatal("an edited accounting verified")
}
if !strings.Contains(note, "content has changed") {
t.Fatalf("the note must name a content change, got %q", note)
}
}
func TestACertificateFromAnotherCAIsRefused(t *testing.T) {
isolateConfigDir(t)
fx := newSigningFixture(t, "fp-one")
other := newSigningFixture(t, "fp-one") // same fingerprint, different CA
writeSigningPairing(t, "one.host.privatae.ai", fx)
if err := baselineSave(sampleBaseline()); err != nil {
t.Fatal(err)
}
f, _, _ := baselineLoad()
ok, note := baselineVerify(f, other.caPEM, fx.fp)
if ok || !strings.Contains(note, "not issued by") {
t.Fatalf("a foreign CA must be refused by name: ok=%v note=%q", ok, note)
}
}
// THE FLEET'S SHAPE. A leaf issued by an intermediate, with the intermediate
// carried after it, verifies against a pairing that holds only the root — and
// the machine's own note, which is what rides the beat, is clean.
func TestAnAccountingSignedUnderAnIntermediateVerifiesAgainstTheRoot(t *testing.T) {
isolateConfigDir(t)
fx := newChainedSigningFixture(t, "fp-one")
writeSigningPairing(t, "one.host.privatae.ai", fx)
if err := baselineSave(sampleBaseline()); err != nil {
t.Fatal(err)
}
f, _, _ := baselineLoad()
if ok, note := baselineVerify(f, fx.caPEM, fx.fp); !ok {
t.Fatalf("an accounting signed under the pairing's intermediate was refused: %q", note)
}
if note := baselineAttestationNote(f); note != "" {
t.Fatalf("the note the beat carries must be clean for the fleet's chain, got %q", note)
}
}
// Carrying an intermediate must not let a chain END somewhere else: the same
// shape under a different root is still refused by name.
func TestAnIntermediateFromAnotherRootIsRefused(t *testing.T) {
isolateConfigDir(t)
fx := newChainedSigningFixture(t, "fp-one")
other := newChainedSigningFixture(t, "fp-one")
writeSigningPairing(t, "one.host.privatae.ai", fx)
if err := baselineSave(sampleBaseline()); err != nil {
t.Fatal(err)
}
f, _, _ := baselineLoad()
ok, note := baselineVerify(f, other.caPEM, fx.fp)
if ok || !strings.Contains(note, "not issued by") {
t.Fatalf("a chain ending at a foreign root must be refused by name: ok=%v note=%q", ok, note)
}
}
// verifyChainShape signs the sample under fx and judges it against fx's root.
func verifyChainShape(t *testing.T, fx signingFixture, edit func(signerCert string) string) (bool, string) {
t.Helper()
isolateConfigDir(t)
writeSigningPairing(t, "one.host.privatae.ai", fx)
if err := baselineSave(sampleBaseline()); err != nil {
t.Fatal(err)
}
p, _ := baselinePath()
raw, _ := os.ReadFile(p)
if edit != nil {
var doc map[string]any
if err := json.Unmarshal(raw, &doc); err != nil {
t.Fatal(err)
}
att := doc["attestation"].(map[string]any)
att["signer_cert"] = edit(att["signer_cert"].(string))
raw, _ = json.Marshal(doc)
}
return baselineVerifyBytes(raw, fx.caPEM, fx.fp)
}
// The shape helper itself verifies at one CA intermediate, so every refusal
// below is about the shape and not a fixture that refuses everything.
func TestTheChainHelperVerifiesAtOneIntermediate(t *testing.T) {
if ok, note := verifyChainShape(t, chainFixture(t, "fp-one", []bool{true}), nil); !ok {
t.Fatalf("root -> CA intermediate -> leaf must verify: %q", note)
}
}
func TestAChainThroughTwoIntermediatesIsRefused(t *testing.T) {
ok, note := verifyChainShape(t, chainFixture(t, "fp-one", []bool{true, true}), nil)
if ok || !strings.Contains(note, "longer than one intermediate") {
t.Fatalf("the host accepts one intermediate at most, and so must the box: ok=%v note=%q", ok, note)
}
}
func TestAnIntermediateThatIsNotACAIsRefused(t *testing.T) {
ok, note := verifyChainShape(t, chainFixture(t, "fp-one", []bool{false}), nil)
if ok || !strings.Contains(note, "not issued by") {
t.Fatalf("a CA:FALSE certificate cannot vouch for a leaf: ok=%v note=%q", ok, note)
}
}
// afterLeaf splits a signer text after the leaf's END line.
func afterLeaf(s string) (string, string) {
i := strings.Index(s, "-----END CERTIFICATE-----\n") + len("-----END CERTIFICATE-----\n")
return s[:i], s[i:]
}
// THE SIGNER TEXT MUST BE THE CANONICAL PEM OF ITS CERTIFICATES. Every shape
// here was, at some point, read one way by pem.Decode and another by the
// host's parser — some accepted on one side only. Each is refused on both.
// The same shapes are in the host's suite.
func TestANonCanonicalSignerTextIsRefused(t *testing.T) {
const blockKey = "-----BEGIN EC PRIVATE KEY-----\nAAAA\n-----END EC PRIVATE KEY-----\n"
for name, edit := range map[string]func(string) string{
"leading text": func(s string) string { return "operator certificate:\n" + s },
"leading space": func(s string) string { return " " + s },
"key block first": func(s string) string { return blockKey + s },
"key block inside": func(s string) string { h, t := afterLeaf(s); return h + blockKey + t },
"other label": func(s string) string {
h, t := afterLeaf(s)
return h + strings.ReplaceAll(t, "CERTIFICATE-----", "X509 CERTIFICATE-----")
},
"indented intermediate": func(s string) string { h, t := afterLeaf(s); return h + " " + t },
"malformed trailing": func(s string) string { return s + "-----BEGIN CERTIFICATE-----\nAAAA\n-----END CERTIFICATE-----\n" },
"undecodable decoy": func(s string) string { return "-----BEGIN CERTIFICATE-----\n!!!!\n-----END CERTIFICATE-----\n" + s },
"header in leaf": func(s string) string {
return strings.Replace(s, "-----BEGIN CERTIFICATE-----\n", "-----BEGIN CERTIFICATE-----\nProc-Type: 4,ENCRYPTED\n\n", 1)
},
"space after BEGIN": func(s string) string {
return strings.Replace(s, "-----BEGIN CERTIFICATE-----\n", "-----BEGIN CERTIFICATE----- \n", 1)
},
"text after leaf END": func(s string) string { h, t := afterLeaf(s); return strings.TrimSuffix(h, "\n") + " trailing\n" + t },
"CRLF": func(s string) string { return strings.ReplaceAll(s, "\n", "\r\n") },
"no final newline": func(s string) string { return strings.TrimSuffix(s, "\n") },
"re-wrapped base64": func(s string) string { return strings.Replace(s, "\n", "", 2) },
"just a BEGIN line": func(string) string { return "-----BEGIN CERTIFICATE-----" },
"empty": func(string) string { return "" },
"extra final newline": func(s string) string { return s + "\n" },
"text after last END": func(s string) string { return s + "trailing text\n" },
} {
ok, note := verifyChainShape(t, newChainedSigningFixture(t, "fp-one"), edit)
if ok || !strings.Contains(note, "signer certificate on this accounting") {
t.Fatalf("%s: a non-canonical signer text must be refused before it is read: ok=%v note=%q", name, ok, note)
}
}
}
// The canonical form is exactly what the fleet sends, so the check refuses
// nothing real: the chained fixture untouched verifies.
func TestTheCanonicalSignerTextVerifies(t *testing.T) {
if ok, note := verifyChainShape(t, newChainedSigningFixture(t, "fp-one"), func(s string) string { return s }); !ok {
t.Fatalf("the canonical chain must verify: %q", note)
}
}
func TestACertificateForAnotherMachineIsRefused(t *testing.T) {
isolateConfigDir(t)
fx := newSigningFixture(t, "fp-one")
writeSigningPairing(t, "one.host.privatae.ai", fx)
if err := baselineSave(sampleBaseline()); err != nil {
t.Fatal(err)
}
f, _, _ := baselineLoad()
ok, note := baselineVerify(f, fx.caPEM, "fp-two")
if ok || !strings.Contains(note, "different machine") {
t.Fatalf("a foreign fingerprint must be refused by name: ok=%v note=%q", ok, note)
}
}
// The anchor's key signs on an anchored box even when other hosts are paired.
func TestTheAnchorPairingSignsOnAnAnchoredBox(t *testing.T) {
isolateConfigDir(t)
anchorFx := newSigningFixture(t, "fp-one")
memberFx := newSigningFixture(t, "fp-one")
writeSigningPairing(t, "anchor.host.privatae.ai", anchorFx)
writeSigningPairing(t, "member.host.privatae.ai", memberFx)
cfgs, _ := loadPairings()
// Two hosts, no anchor: nobody speaks for the machine.
if signer, why := baselineSignerPairing(cfgs); signer != nil || why != baselineUnsignedNoAnchor {
t.Fatalf("two unanchored hosts must not pick a signer: %v %q", signer, why)
}
}
func TestAMultiHostBoxWithNoAnchorWritesUnsignedAndSaysWhy(t *testing.T) {
isolateConfigDir(t)
writeSigningPairing(t, "a.host.privatae.ai", newSigningFixture(t, "fp-one"))
writeSigningPairing(t, "b.host.privatae.ai", newSigningFixture(t, "fp-one"))
if err := baselineSave(sampleBaseline()); err != nil {
t.Fatal(err)
}
f, _, _ := baselineLoad()
if f.Attestation != nil {
t.Fatal("an unanchored multi-host box signed with one host's key")
}
if f.UnsignedReason != baselineUnsignedNoAnchor {
t.Fatalf("the reason must be recorded in the file: %q", f.UnsignedReason)
}
if n := baselineAttestationNote(f); n != "" {
t.Fatalf("an honestly-unsigned file must not read as a problem: %q", n)
}
}
func TestANoPairingBoxWritesUnsignedAndSaysWhy(t *testing.T) {
isolateConfigDir(t)
if err := baselineSave(sampleBaseline()); err != nil {
t.Fatal(err)
}
f, _, _ := baselineLoad()
if f.Attestation != nil || f.UnsignedReason != baselineUnsignedNoPairing {
t.Fatalf("got attestation=%v reason=%q", f.Attestation, f.UnsignedReason)
}
}
// A key that is PRESENT but unreadable is an error, not a silent unsigned file:
// a reader cannot tell "meant to be unsigned" from "failed to sign".
func TestAnUnreadableOperatorKeyIsAnErrorNotAnUnsignedFile(t *testing.T) {
isolateConfigDir(t)
fx := newSigningFixture(t, "fp-one")
fx.keyPEM = "-----BEGIN EC PRIVATE KEY-----\nnot a key\n-----END EC PRIVATE KEY-----\n"
writeSigningPairing(t, "one.host.privatae.ai", fx)
if err := baselineSave(sampleBaseline()); err == nil {
t.Fatal("a corrupt operator key produced no error")
}
if _, err := os.Stat(func() string { p, _ := baselinePath(); return p }()); !os.IsNotExist(err) {
t.Fatal("an accounting was written despite the signing failure")
}
}
func TestTheAccountingIsMirroredIntoTheStore(t *testing.T) {
isolateConfigDir(t)
fx := newSigningFixture(t, "fp-one")
writeSigningPairing(t, "one.host.privatae.ai", fx)
if err := baselineSave(sampleBaseline()); err != nil {
t.Fatal(err)
}
p, _ := baselinePath()
root, _ := storeDir()
a, _ := os.ReadFile(p)
b, err := os.ReadFile(filepath.Join(root, "baseline.json"))
if err != nil {
t.Fatalf("no mirror in the store: %v", err)
}
if string(a) != string(b) {
t.Fatal("the store copy differs from the state-dir copy")
}
fi, _ := os.Stat(filepath.Join(root, "baseline.json"))
if fi.Mode().Perm() != 0o600 {
t.Fatalf("mirror is %v, want 0600", fi.Mode().Perm())
}
}
// Canonical form is stable across a round trip through the file, and the two
// derived keys never enter it.
func TestCanonicalFormIsStableAndExcludesDerivedKeys(t *testing.T) {
f := sampleBaseline()
c1, err := baselineCanonical(f)
if err != nil {
t.Fatal(err)
}
f.Digest = "anything"
f.Attestation = &baselineAttestation{Signature: "x"}
f.UnsignedReason = ""
c2, _ := baselineCanonical(f)
if string(c1) != string(c2) {
t.Fatal("digest or attestation leaked into the canonical form")
}
if strings.Contains(string(c1), `"digest"`) || strings.Contains(string(c1), `"attestation"`) {
t.Fatalf("derived keys present: %s", c1)
}
// TOP LEVEL ONLY. The host drops the two keys only at the top level; a
// recursive delete here would diverge on any entry that ever carried a
// `digest` field. Latent today (entries carry exe_digest), and a mutation
// making the delete recursive survived — so it is pinned.
nested, err := baselineCanonicalBytes([]byte(`{"entries":[{"digest":"keep","fp":"a"}],"digest":"drop","attestation":{"x":1}}`))
if err != nil {
t.Fatal(err)
}
if string(nested) != `{"entries":[{"digest":"keep","fp":"a"}]}` {
t.Fatalf("nested derived-key names must be preserved, got %s", nested)
}
// No HTML escaping (a raw `<`, never `\u003c`) and non-ASCII raw: what the
// Python side produces. The first version of this assertion had the sign
// backwards and failed on correct output.
if strings.Contains(string(c1), `\u003c`) || !strings.Contains(string(c1), `<app>`) ||
!strings.Contains(string(c1), "naïve") {
t.Fatalf("canonical escaping differs from the host's: %s", c1)
}
}
// THE CROSS-LANGUAGE FIXTURE. Set BASELINE_FIXTURE_OUT=<dir> to write a signed
// accounting, its CA and its fingerprint for the host-side verifier's own
// test suite. Skipped otherwise.
func TestWriteCrossLanguageFixture(t *testing.T) {
out := os.Getenv("BASELINE_FIXTURE_OUT")
if out == "" {
t.Skip("set BASELINE_FIXTURE_OUT to write the fixture the host verifies")
}
isolateConfigDir(t)
// The fleet's shape (root CA, intermediate-issued leaf), so the host's
// verifier is proven against what machines actually send.
// Only the name a Host with no platform reads: the fixture ships in that
// Host's source, and its verifier must need no other name.
u, err := url.Parse(hostFPSANPrefix + "fp-fixture-0001")
if err != nil {
t.Fatal(err)
}
fx := newChainedSigningFixtureWithURIs(t, "fp-fixture-0001", []*url.URL{u})
writeSigningPairing(t, "fixture.host.example.test", fx)
if err := baselineSave(sampleBaseline()); err != nil {
t.Fatal(err)
}
p, _ := baselinePath()
b, _ := os.ReadFile(p)
if err := os.MkdirAll(out, 0o755); err != nil {
t.Fatal(err)
}
for name, body := range map[string]string{
"baseline.json": string(b), "ca.pem": fx.caPEM, "fingerprint": fx.fp + "\n",
} {
if err := os.WriteFile(filepath.Join(out, name), []byte(body), 0o644); err != nil {
t.Fatal(err)
}
}
t.Logf("fixture written to %s", out)
}
// THE NOTE IS WHAT THE MACHINE READS. `observe:baseline:show` and the delta
// pass both judge the accounting through baselineAttestationNote, not through
// baselineVerify directly — so a mutation that made the note ignore a failed
// verification survived every test above. This drives the note on an edited
// file and, where the pass can run, checks the note rides the delta's notes and
// so the beat.
func TestAnEditedAccountingIsFlaggedByTheNoteAndRidesTheDelta(t *testing.T) {
isolateConfigDir(t)
fx := newSigningFixture(t, "fp-one")
writeSigningPairing(t, "one.host.privatae.ai", fx)
if err := baselineSave(sampleBaseline()); err != nil {
t.Fatal(err)
}
p, _ := baselinePath()
b, _ := os.ReadFile(p)
edited := strings.Replace(string(b), `"unreadable": 3`, `"unreadable": 0`, 1)
if edited == string(b) {
t.Fatal("the fixture edit did not apply, so this test proves nothing")
}
// Keep the self-digest VALID so the only thing wrong is the signature —
// otherwise the integrity note fires and the attestation note is untested.
var f baselineFile
if err := json.Unmarshal([]byte(edited), &f); err != nil {
t.Fatal(err)
}
d, _ := baselineDigestOf(f)
f.Digest = d
re, _ := json.MarshalIndent(f, "", " ")
if err := os.WriteFile(p, re, 0o600); err != nil {
t.Fatal(err)
}
loaded, digestOK, _ := baselineLoad()
if !digestOK {
t.Fatal("the fixture's digest is not valid, so the integrity note would mask this")
}
n := baselineAttestationNote(loaded)
if !strings.Contains(n, "content has changed") {
t.Fatalf("the note did not flag an edited accounting: %q", n)
}
if !processIsRoot() {
t.Log("not root: the delta pass cannot run here; the note itself is verified above")
return
}
r := deltaPass(&digestCache{}, time.Now(), deltaRoleOperator)
found := false
for _, note := range r.Notes {
if strings.HasPrefix(note, "attestation: ") && strings.Contains(note, "content has changed") {
found = true
}
}
if !found {
t.Fatalf("the delta pass did not carry the attestation failure in its notes: %v", r.Notes)
}
}
// The canonical form REFUSES what the two encoders disagree on, so adding a
// float or a big integer to the accounting fails here — loudly, at signing —
// rather than as a false "tampered" verdict on every host.
func TestCanonicalRefusesNumbersTheEncodersDisagreeOn(t *testing.T) {
for _, c := range []struct{ name, json string }{
{"a float", `{"unreadable": 1.5}`},
{"an integral float", `{"unreadable": 1.0}`},
{"a small exponent", `{"unreadable": 1e-7}`},
{"an integer past 2^53", `{"unreadable": 9223372036854775807}`},
} {
dec := json.NewDecoder(strings.NewReader(c.json))
dec.UseNumber()
var m map[string]any
if err := dec.Decode(&m); err != nil {
t.Fatal(err)
}
if err := baselineCheckNumbers(m, "$"); err == nil {
t.Fatalf("%s was accepted into the canonical form", c.name)
}
}
// And the accounting as it actually is — one small integer — is fine.
if _, err := baselineCanonical(sampleBaseline()); err != nil {
t.Fatalf("a real accounting was refused: %v", err)
}
// THE 2^53 BOUNDARY, probed AT the boundary. The cases above jump straight
// to max-int64, so a mutation widening the bound to 2^60 survived: 2^54
// would then be accepted here and refused by the host — a live asymmetry.
for _, c := range []struct {
lit string
accept bool
}{
{"9007199254740992", true}, // 2^53
{"9007199254740993", false}, // 2^53 + 1
{"-9007199254740992", true}, // -2^53
{"-9007199254740993", false}, // -(2^53 + 1)
{"18014398509481984", false}, // 2^54
} {
d := json.NewDecoder(strings.NewReader(`{"unreadable": ` + c.lit + `}`))
d.UseNumber()
var mm map[string]any
_ = d.Decode(&mm)
err := baselineCheckNumbers(mm, "$")
if (err == nil) != c.accept {
t.Fatalf("%s: accepted=%v, want %v", c.lit, err == nil, c.accept)
}
}
// -0: the one form neither side would otherwise catch.
dec := json.NewDecoder(strings.NewReader(`{"unreadable": -0}`))
dec.UseNumber()
var m map[string]any
_ = dec.Decode(&m)
if err := baselineCheckNumbers(m, "$"); err == nil {
t.Fatal("-0 was accepted into the canonical form")
}
// A number INSIDE the derived keys is dropped before it can be refused —
// the host does the same, and the two must agree.
if _, err := baselineCanonicalBytes([]byte(`{"unreadable":1,"attestation":{"key_version":2.5},"digest":"d"}`)); err != nil {
t.Fatalf("a number inside a derived key was refused, which the host would verify: %v", err)
}
}
// ── signing review round ────────────────────────────────────────────────────
// THE GOLDEN VECTOR. The canonical bytes for a fixed accounting, as a literal.
// This is the cross-language contract: the box signs and verifies the same
// bytes, so a change here (a kept trailing newline, HTML escaping back on, a
// dropped key) passes every self-consistency test while breaking every host.
// Only a pinned literal catches it. If this changes deliberately, the Python
// side's fixture must be regenerated in the same change.
func TestCanonicalBytesAreTheGoldenVector(t *testing.T) {
f := baselineFile{
Version: "privatae-baseline-v2", TakenAt: "2026-09-19T10:00:00Z",
Coverage: "processes=all,schedulers=all",
Entries: []baselineEntry{{FP: "aaa", Kind: "process", Exe: `/opt/naïve <app> & "co"\bin`,
User: "root", ArgvShape: "x --y"}},
Unreadable: 3, Digest: "ignored", UnsignedReason: "",
}
got, err := baselineCanonical(f)
if err != nil {
t.Fatal(err)
}
want := `{"coverage":"processes=all,schedulers=all","entries":[{"argv_shape":"x --y","exe":"/opt/naïve <app> & \"co\"\\bin","fp":"aaa","kind":"process","user":"root"}],"taken_at":"2026-09-19T10:00:00Z","unreadable":3,"version":"privatae-baseline-v2"}`
if string(got) != want {
t.Fatalf("canonical bytes moved.\n got: %s\nwant: %s", got, want)
}
}
func TestAKeylessPairingWritesAnUnsignedAccountingWithTheReason(t *testing.T) {
isolateConfigDir(t)
fx := newSigningFixture(t, "fp-one")
fx.keyPEM = "" // an older pairing that never held an operator key
writeSigningPairing(t, "one.host.privatae.ai", fx)
if err := baselineSave(sampleBaseline()); err != nil {
t.Fatalf("a keyless pairing must not block the accounting: %v", err)
}
f, _, _ := baselineLoad()
if f.Attestation != nil || f.UnsignedReason != baselineUnsignedNoKey {
t.Fatalf("attestation=%v reason=%q", f.Attestation, f.UnsignedReason)
}
}
// Validity is judged at the moment the accounting was TAKEN. A certificate
// that has since expired still verifies an accounting taken while it was
// valid; one that was not yet valid when the accounting was taken is refused,
// and by name.
func TestCertificateValidityIsJudgedWhenTheAccountingWasTaken(t *testing.T) {
isolateConfigDir(t)
fx := newSigningFixture(t, "fp-one")
writeSigningPairing(t, "one.host.privatae.ai", fx)
if err := baselineSave(sampleBaseline()); err != nil {
t.Fatal(err)
}
p, _ := baselinePath()
raw, _ := os.ReadFile(p)
// The same bytes with taken_at moved BEFORE the certificate existed.
before := strings.Replace(string(raw), `"taken_at": "2026-09-19T10:00:00Z"`,
`"taken_at": "2025-01-01T00:00:00Z"`, 1)
if before == string(raw) {
t.Fatal("the fixture edit did not apply")
}
// (Content changed, so the signature fails too — assert the validity check
// fires FIRST and names itself.)
ok, note := baselineVerifyBytes([]byte(before), fx.caPEM, fx.fp)
if ok || !strings.Contains(note, "not valid at the time this accounting was taken") {
t.Fatalf("a certificate not yet valid at taken_at must be refused by name: ok=%v %q", ok, note)
}
// And the real file, whose certificate will one day expire, still verifies
// because it is judged at its own taken_at, not at now.
if ok, note := baselineVerifyBytes(raw, fx.caPEM, fx.fp); !ok {
t.Fatalf("judged at taken_at the real accounting must verify: %s", note)
}
}
func TestAnUnknownAlgorithmIsRefusedByName(t *testing.T) {
isolateConfigDir(t)
fx := newSigningFixture(t, "fp-one")
writeSigningPairing(t, "one.host.privatae.ai", fx)
if err := baselineSave(sampleBaseline()); err != nil {
t.Fatal(err)
}
p, _ := baselinePath()
raw, _ := os.ReadFile(p)
edited := strings.Replace(string(raw), `"alg": "ecdsa-p256-sha256"`, `"alg": "rsa-pss-sha512"`, 1)
if edited == string(raw) {
t.Fatal("the fixture edit did not apply")
}
ok, note := baselineVerifyBytes([]byte(edited), fx.caPEM, fx.fp)
if ok || !strings.Contains(note, "rsa-pss-sha512") {
t.Fatalf("an unknown alg must be refused by name: ok=%v %q", ok, note)
}
}
// A newer bastion's extra field must not read as tampering on an older one:
// the box verifies from the file's own bytes, not through a lossy parse.
func TestAFieldThisBinaryDoesNotKnowStillVerifies(t *testing.T) {
isolateConfigDir(t)
fx := newSigningFixture(t, "fp-one")
writeSigningPairing(t, "one.host.privatae.ai", fx)
// Build the document as a MAP with an unknown field, sign it the way the
// box does, and hand the bytes to the verifier.
m := map[string]any{
"version": baselineVersion, "taken_at": "2026-09-19T10:00:00Z",
"coverage": "processes=all,schedulers=all", "entries": []any{},
"unreadable": 0, "digest": "d",
"future_field": "written by bastion 9.0",
}
rawUnsigned, _ := json.Marshal(m)
canon, err := baselineCanonicalBytes(rawUnsigned)
if err != nil {
t.Fatal(err)
}
key, _ := parseECPrivateKeyPEM(fx.keyPEM)
sum := sha256.Sum256(canon)
sig, _ := ecdsa.SignASN1(rand.Reader, key, sum[:])
m["attestation"] = baselineAttestation{Alg: baselineSigAlg, SignedBy: "one.host.privatae.ai",
SignerCert: fx.leafPEM, Signature: base64.StdEncoding.EncodeToString(sig)}
raw, _ := json.Marshal(m)
ok, note := baselineVerifyBytes(raw, fx.caPEM, fx.fp)
if !ok {
t.Fatalf("a version-skewed file read as tampered on the box: %s", note)
}
}
// unsigned_reason is COVERED by the signature — only digest and attestation
// are dropped — so planting one on a signed file is a content change.
func TestEditingTheUnsignedReasonOnASignedFileFails(t *testing.T) {
isolateConfigDir(t)
fx := newSigningFixture(t, "fp-one")
writeSigningPairing(t, "one.host.privatae.ai", fx)
if err := baselineSave(sampleBaseline()); err != nil {
t.Fatal(err)
}
p, _ := baselinePath()
raw, _ := os.ReadFile(p)
edited := strings.Replace(string(raw), `"attestation": {`, `"unsigned_reason": "planted",
"attestation": {`, 1)
if edited == string(raw) {
t.Fatal("the fixture edit did not apply")
}
if ok, _ := baselineVerifyBytes([]byte(edited), fx.caPEM, fx.fp); ok {
t.Fatal("an edited unsigned_reason verified — it is not covered by the signature")
}
}
// A platform-issued certificate names the fingerprint under the platform's name
// only, a Host with no platform's under its own; each verifies alone.
func TestAFingerprintUnderEitherNameVerifies(t *testing.T) {
for _, prefix := range []string{fpSANPrefix, hostFPSANPrefix} {
isolateConfigDir(t)
u, _ := url.Parse(prefix + "fp-one")
fx := newSigningFixtureWithURIs(t, "fp-one", []*url.URL{u})
writeSigningPairing(t, "one.host.example.test", fx)
if err := baselineSave(sampleBaseline()); err != nil {
t.Fatal(err)
}
f, _, _ := baselineLoad()
if ok, note := baselineVerify(f, fx.caPEM, "fp-one"); !ok {
t.Fatalf("%s: a fingerprint under this name alone must verify: %q", prefix, note)
}
}
}
// Two names carrying two different fingerprints name two machines; the
// verifier refuses rather than picking one.
func TestACertificateNamingTwoMachinesIsRefused(t *testing.T) {
isolateConfigDir(t)
a, _ := url.Parse(fpSANPrefix + "fp-one")
b, _ := url.Parse(hostFPSANPrefix + "fp-two")
fx := newSigningFixtureWithURIs(t, "fp-one", []*url.URL{a, b})
writeSigningPairing(t, "one.host.example.test", fx)
if err := baselineSave(sampleBaseline()); err != nil {
t.Fatal(err)
}
f, _, _ := baselineLoad()
ok, note := baselineVerify(f, fx.caPEM, "")
if ok || !strings.Contains(note, "two different device fingerprints") {
t.Fatalf("two fingerprints must be refused by name: ok=%v note=%q", ok, note)
}
}