slice 8A (agent half): local-API server + provisioning back-half (v0.10.0)
internal/localapi: per-guest local-API server (doc 03 §6) — 7 self-scoped endpoints, hashed per-guest token store, persisted self-signed leaf with stable SHA-256 pin, optional 6th daemon goroutine. internal/provision: back-half — mint token, render bootstrap.json (no registry cred), write 0600, chown 100000:100000, attach pct-set bind mount (host-side, F3, no pct exec). --selftest=provision. build-golden.sh bakes the controller image + bootstrap unit. sudoers FELHOM_PROVISION; firewall narrowing artifact. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
package localapi
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// The leaf is generated once and its fingerprint stays STABLE across "restarts" (re-loads from
|
||||
// disk) — a fresh cert each boot would invalidate every already-baked bootstrap pin.
|
||||
func TestEnsureLeaf_StableFingerprintAcrossReload(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
certPath := filepath.Join(dir, "leaf.crt")
|
||||
keyPath := filepath.Join(dir, "leaf.key")
|
||||
|
||||
cert1, fp1, err := EnsureLeaf(certPath, keyPath, "192.168.0.162")
|
||||
if err != nil {
|
||||
t.Fatalf("first ensure: %v", err)
|
||||
}
|
||||
cert2, fp2, err := EnsureLeaf(certPath, keyPath, "192.168.0.162")
|
||||
if err != nil {
|
||||
t.Fatalf("second ensure: %v", err)
|
||||
}
|
||||
if fp1 != fp2 {
|
||||
t.Fatalf("fingerprint changed across reload: %s != %s", fp1, fp2)
|
||||
}
|
||||
// The reported fingerprint must equal the SHA-256 of the served leaf DER (the pin the
|
||||
// controller checks against).
|
||||
got := sha256.Sum256(cert2.Certificate[0])
|
||||
if hex.EncodeToString(got[:]) != fp2 {
|
||||
t.Fatal("reported fingerprint does not match the served leaf DER")
|
||||
}
|
||||
if len(fp1) != 64 {
|
||||
t.Fatalf("fingerprint is not a 64-hex SHA-256: %q", fp1)
|
||||
}
|
||||
_ = cert1
|
||||
}
|
||||
|
||||
// The generated leaf is a usable TLS server cert whose presented leaf matches the pin.
|
||||
func TestEnsureLeaf_ServesPinnableLeaf(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
cert, fp, err := EnsureLeaf(filepath.Join(dir, "c"), filepath.Join(dir, "k"), "10.0.0.1")
|
||||
if err != nil {
|
||||
t.Fatalf("ensure: %v", err)
|
||||
}
|
||||
if len(cert.Certificate) == 0 {
|
||||
t.Fatal("no leaf in cert chain")
|
||||
}
|
||||
if cert.PrivateKey == nil {
|
||||
t.Fatal("generated cert has no private key")
|
||||
}
|
||||
sum := sha256.Sum256(cert.Certificate[0])
|
||||
if hex.EncodeToString(sum[:]) != fp {
|
||||
t.Fatal("pin mismatch against served leaf")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user