3fecf4c713
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>
132 lines
3.1 KiB
Go
132 lines
3.1 KiB
Go
package localapi
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestTokenStore_MintLookup(t *testing.T) {
|
|
path := filepath.Join(t.TempDir(), "tokens.log")
|
|
s, err := OpenTokenStore(path)
|
|
if err != nil {
|
|
t.Fatalf("open: %v", err)
|
|
}
|
|
defer s.Close()
|
|
|
|
tok, err := s.Mint(8200)
|
|
if err != nil {
|
|
t.Fatalf("mint: %v", err)
|
|
}
|
|
if tok == "" {
|
|
t.Fatal("mint returned empty token")
|
|
}
|
|
if vmid, ok := s.Lookup(tok); !ok || vmid != 8200 {
|
|
t.Fatalf("lookup: got (%d,%v), want (8200,true)", vmid, ok)
|
|
}
|
|
if _, ok := s.Lookup("not-a-real-token"); ok {
|
|
t.Fatal("lookup of unknown token succeeded")
|
|
}
|
|
if _, ok := s.Lookup(""); ok {
|
|
t.Fatal("lookup of empty token succeeded")
|
|
}
|
|
}
|
|
|
|
// The persisted file must contain only the HASH, never the plaintext token.
|
|
func TestTokenStore_PlaintextNeverPersisted(t *testing.T) {
|
|
path := filepath.Join(t.TempDir(), "tokens.log")
|
|
s, err := OpenTokenStore(path)
|
|
if err != nil {
|
|
t.Fatalf("open: %v", err)
|
|
}
|
|
tok, err := s.Mint(101)
|
|
if err != nil {
|
|
t.Fatalf("mint: %v", err)
|
|
}
|
|
s.Close()
|
|
|
|
b, err := os.ReadFile(path)
|
|
if err != nil {
|
|
t.Fatalf("read store: %v", err)
|
|
}
|
|
if strings.Contains(string(b), tok) {
|
|
t.Fatal("plaintext token found in the persisted store — must store only the hash")
|
|
}
|
|
if !strings.Contains(string(b), hashToken(tok)) {
|
|
t.Fatal("token hash not found in the persisted store")
|
|
}
|
|
}
|
|
|
|
// A re-mint for the same guest revokes the previous token (last-write-wins).
|
|
func TestTokenStore_RemintRevokesOld(t *testing.T) {
|
|
path := filepath.Join(t.TempDir(), "tokens.log")
|
|
s, err := OpenTokenStore(path)
|
|
if err != nil {
|
|
t.Fatalf("open: %v", err)
|
|
}
|
|
defer s.Close()
|
|
|
|
old, _ := s.Mint(7)
|
|
fresh, _ := s.Mint(7)
|
|
if old == fresh {
|
|
t.Fatal("re-mint produced the same token")
|
|
}
|
|
if _, ok := s.Lookup(old); ok {
|
|
t.Fatal("old token still valid after re-mint")
|
|
}
|
|
if vmid, ok := s.Lookup(fresh); !ok || vmid != 7 {
|
|
t.Fatalf("fresh token lookup: got (%d,%v), want (7,true)", vmid, ok)
|
|
}
|
|
}
|
|
|
|
// Durability: tokens survive a store reopen (replay).
|
|
func TestTokenStore_SurvivesReopen(t *testing.T) {
|
|
path := filepath.Join(t.TempDir(), "tokens.log")
|
|
s1, err := OpenTokenStore(path)
|
|
if err != nil {
|
|
t.Fatalf("open: %v", err)
|
|
}
|
|
a, _ := s1.Mint(1)
|
|
b, _ := s1.Mint(2)
|
|
// rotate guest 1
|
|
a2, _ := s1.Mint(1)
|
|
s1.Close()
|
|
|
|
s2, err := OpenTokenStore(path)
|
|
if err != nil {
|
|
t.Fatalf("reopen: %v", err)
|
|
}
|
|
defer s2.Close()
|
|
|
|
if _, ok := s2.Lookup(a); ok {
|
|
t.Fatal("rotated-out token survived reopen")
|
|
}
|
|
if vmid, ok := s2.Lookup(a2); !ok || vmid != 1 {
|
|
t.Fatalf("guest1 current token lost across reopen: (%d,%v)", vmid, ok)
|
|
}
|
|
if vmid, ok := s2.Lookup(b); !ok || vmid != 2 {
|
|
t.Fatalf("guest2 token lost across reopen: (%d,%v)", vmid, ok)
|
|
}
|
|
}
|
|
|
|
func TestTokenStore_Uniqueness(t *testing.T) {
|
|
path := filepath.Join(t.TempDir(), "tokens.log")
|
|
s, err := OpenTokenStore(path)
|
|
if err != nil {
|
|
t.Fatalf("open: %v", err)
|
|
}
|
|
defer s.Close()
|
|
seen := map[string]bool{}
|
|
for i := 1; i <= 200; i++ {
|
|
tok, err := s.Mint(i)
|
|
if err != nil {
|
|
t.Fatalf("mint %d: %v", i, err)
|
|
}
|
|
if seen[tok] {
|
|
t.Fatalf("duplicate token at %d", i)
|
|
}
|
|
seen[tok] = true
|
|
}
|
|
}
|