Implement inbound caller authentication (ADR 0004); close T03 and T05

TokenReview-based caller identity with audience-scoped tokens and exact
resource.system to ServiceAccount bindings, per ops-warden's recommendation.
Deletes the unwired tenant-engine live-roles adapter (T03) and adds
make verify-posture (T05). Source implements A2; running digest is still A0
until promotion, so tenancy.current.A stays 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
tegwick 2026-08-18 15:22:52 +02:00
parent 6d82ef7f14
commit 1e1e077b27
18 changed files with 768 additions and 357 deletions

View file

@ -11,6 +11,7 @@ import (
"strings"
"testing"
"github.com/netkingdom/flex-auth/internal/callerauth"
"github.com/netkingdom/flex-auth/pkg/api"
)
@ -157,6 +158,77 @@ func TestServeOpsWardenCheckContract(t *testing.T) {
}
}
type fixedTokenReviewer struct {
identity callerauth.Identity
}
func (r fixedTokenReviewer) Review(context.Context, string) (callerauth.Identity, error) {
return r.identity, nil
}
func TestServeCallerAuthenticationBindsSystemToPrincipal(t *testing.T) {
engine, err := buildEngine(context.Background(), opsPath("registry_snapshot.json"), opsPath("policy_package.md"), "")
if err != nil {
t.Fatalf("buildEngine: %v", err)
}
authenticator, err := callerauth.New(callerauth.ModeEnforce, fixedTokenReviewer{identity: callerauth.Identity{
Username: "system:serviceaccount:ops-warden:ops-warden",
Audiences: []string{"flex-auth"},
}}, "flex-auth", map[string]string{
"ops-warden": "system:serviceaccount:ops-warden:ops-warden",
}, nil)
if err != nil {
t.Fatal(err)
}
server := httptest.NewServer(newServeMuxWithCallerAuth(engine, authenticator))
defer server.Close()
body, err := os.ReadFile(opsPath("check_request_allow_adm.json"))
if err != nil {
t.Fatal(err)
}
request, _ := http.NewRequest(http.MethodPost, server.URL+"/v1/check", bytes.NewReader(body))
request.Header.Set("content-type", "application/json")
resp, err := http.DefaultClient.Do(request)
if err != nil {
t.Fatal(err)
}
resp.Body.Close()
if resp.StatusCode != http.StatusUnauthorized {
t.Fatalf("missing token status = %d; want 401", resp.StatusCode)
}
request, _ = http.NewRequest(http.MethodPost, server.URL+"/v1/check", bytes.NewReader(body))
request.Header.Set("content-type", "application/json")
request.Header.Set("authorization", "Bearer workload-token")
resp, err = http.DefaultClient.Do(request)
if err != nil {
t.Fatal(err)
}
resp.Body.Close()
if resp.StatusCode != http.StatusOK {
t.Fatalf("bound caller status = %d; want 200", resp.StatusCode)
}
wrong, _ := callerauth.New(callerauth.ModeEnforce, fixedTokenReviewer{identity: callerauth.Identity{
Username: "system:serviceaccount:another:caller",
Audiences: []string{"flex-auth"},
}}, "flex-auth", map[string]string{"ops-warden": "system:serviceaccount:ops-warden:ops-warden"}, nil)
wrongServer := httptest.NewServer(newServeMuxWithCallerAuth(engine, wrong))
defer wrongServer.Close()
request, _ = http.NewRequest(http.MethodPost, wrongServer.URL+"/v1/check", bytes.NewReader(body))
request.Header.Set("content-type", "application/json")
request.Header.Set("authorization", "Bearer workload-token")
resp, err = http.DefaultClient.Do(request)
if err != nil {
t.Fatal(err)
}
resp.Body.Close()
if resp.StatusCode != http.StatusForbidden {
t.Fatalf("mismatched caller status = %d; want 403", resp.StatusCode)
}
}
func TestRunLoadRegistryOpsWardenProduction(t *testing.T) {
var stdout, stderr bytes.Buffer
code := run([]string{"load-registry", "--file", opsPath("production_registry_snapshot.json")}, &stdout, &stderr)