Files
felhom-agent/internal/hub/wg_client_test.go
T
admin 0daae92c4f wgtunnel: S3 Part 1 — pure-Go keygen + hub wire (WireWireguard, report stanza, RegisterWG)
key.go: create-once 0600/0700, corrupt-refusal (never overwrite — may be escrowed
identity), clamp for CANONICAL STORED form (x/crypto X25519 clamps derivation
internally — discovered during red-proof (c); the stored-clamped test is the
real anchor). Fixed vectors generated with real wg pubkey (provenance in test).
hub: WireDesiredState.Wireguard + WireguardStatus report stanza + RegisterWG
client (typed errors, token-free). S2 golden copied BYTE-IDENTICAL + field-exact
decode test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-04 07:00:19 +02:00

76 lines
2.3 KiB
Go

package hub
// S3 Group C — RegisterWG client (POST /hosts/{id}/wg, per-host key). Typed-error mapping and
// the no-token-in-errors invariant, same scaffolding as the desired-state client tests.
import (
"context"
"errors"
"io"
"net/http"
"strings"
"testing"
)
func TestRegisterWG_PathAuthBodyAndDecode(t *testing.T) {
var gotPath, gotAuth, gotMethod, gotBody string
c := testClient(func(r *http.Request) (*http.Response, error) {
gotPath = r.URL.Path
gotAuth = r.Header.Get("Authorization")
gotMethod = r.Method
b, _ := io.ReadAll(r.Body)
gotBody = string(b)
return httpResp(200, `{"pubkey":"PK","assigned_ip":"10.77.0.2/32","existed":false,"generation":3,"sync":"ok"}`), nil
})
resp, err := c.RegisterWG(context.Background(), "PK")
if err != nil {
t.Fatalf("RegisterWG: %v", err)
}
if gotMethod != http.MethodPost || gotPath != "/api/v1/hosts/demo-host-01/wg" {
t.Errorf("request = %s %s, want POST /api/v1/hosts/demo-host-01/wg", gotMethod, gotPath)
}
if gotAuth != "Bearer super-secret-bearer-key" {
t.Errorf("auth = %q", gotAuth)
}
if gotBody != `{"pubkey":"PK"}` {
t.Errorf("body = %s", gotBody)
}
if resp.AssignedIP != "10.77.0.2/32" || resp.Existed || resp.Generation != 3 || resp.Sync != "ok" {
t.Errorf("resp = %+v", resp)
}
}
func TestRegisterWG_TypedErrors(t *testing.T) {
for _, tc := range []struct {
status int
body string
}{
{403, "Forbidden: host_id mismatch"},
{404, "Unknown host_id"},
{409, "wg endpoint not configured"},
{409, "pubkey already registered elsewhere"},
} {
c := testClient(func(r *http.Request) (*http.Response, error) {
return httpResp(tc.status, tc.body), nil
})
_, err := c.RegisterWG(context.Background(), "PK")
var he *HTTPError
if !errors.As(err, &he) || he.StatusCode != tc.status {
t.Errorf("status %d: err = %v, want HTTPError %d", tc.status, err, tc.status)
}
if strings.Contains(err.Error(), "super-secret-bearer-key") {
t.Fatalf("bearer token leaked into error: %v", err)
}
}
// Transport failure → TransportError, token-free.
c := testClient(func(r *http.Request) (*http.Response, error) {
return nil, errors.New("dial tcp: connection refused")
})
_, err := c.RegisterWG(context.Background(), "PK")
var te *TransportError
if !errors.As(err, &te) {
t.Errorf("transport err = %v, want TransportError", err)
}
}