wgtunnel: S3 Part 3 — FELHOM_WG sudoers + capabilities + config (DEFAULT OFF) + main wiring + escrow join
Sudoers: fixed-path conf install, enable/restart/disable, latest-handshakes-only wg read (dump FORBIDDEN — the S1 incident). 6 capability-manifest entries (Critical=false until S4 makes the tunnel load-bearing). WGTunnelConfig with enabled=false DEFAULT (the safety gate: a v0.64.0 rollout without explicit config is a no-op). Daemon wiring mirrors lanresolver + AddConsumer + SetWireguardReporter; --selftest=wgtunnel single-shot. IdentityBundle +wg_private_key (omitempty; pre-S3 blobs cannot be retrofitted — documented) with escrow-create auto-inject (field name only in logs). Red-proof (e) run. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
package escrow
|
||||
|
||||
// S3 Group D — the WG-key escrow join. Red-proof (e): remove the auto-inject call and the
|
||||
// bundle-contains-key assertion fails.
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAttachWGKey(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
keyPath := filepath.Join(dir, "private.key")
|
||||
|
||||
// Missing key file → clean no-attach (pre-S3 bundles stay byte-compatible).
|
||||
b := &IdentityBundle{TunnelToken: "tt", PBSToken: "pt"}
|
||||
attached, err := AttachWGKey(b, keyPath)
|
||||
if err != nil || attached {
|
||||
t.Fatalf("missing file: attached=%v err=%v", attached, err)
|
||||
}
|
||||
raw, _ := json.Marshal(b)
|
||||
if string(raw) != `{"tunnel_token":"tt","pbs_token":"pt"}` {
|
||||
t.Fatalf("bundle without key marshals with extra fields: %s", raw)
|
||||
}
|
||||
|
||||
// Present key file → attached, field carried.
|
||||
key := base64.StdEncoding.EncodeToString(make([]byte, 32))
|
||||
os.WriteFile(keyPath, []byte(key+"\n"), 0o600)
|
||||
attached, err = AttachWGKey(b, keyPath)
|
||||
if err != nil || !attached {
|
||||
t.Fatalf("present file: attached=%v err=%v", attached, err)
|
||||
}
|
||||
if b.WGPrivateKey != key {
|
||||
t.Fatalf("bundle key = %q", b.WGPrivateKey)
|
||||
}
|
||||
raw, _ = json.Marshal(b)
|
||||
var back IdentityBundle
|
||||
json.Unmarshal(raw, &back)
|
||||
if back.WGPrivateKey != key {
|
||||
t.Fatal("wg_private_key does not survive the bundle round-trip")
|
||||
}
|
||||
|
||||
// Corrupt key file → error (the operator must know their escrow would lack the identity).
|
||||
os.WriteFile(keyPath, []byte("garbage"), 0o600)
|
||||
if _, err := AttachWGKey(&IdentityBundle{}, keyPath); err == nil {
|
||||
t.Fatal("corrupt key file attached silently")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user