package taskexecution import ( "bytes" "context" "encoding/json" "github.com/netkingdom/access-engine/internal/callerauth" "github.com/netkingdom/access-engine/pkg/api" "testing" "time" ) type serviceReviewer struct { identity callerauth.Identity err error calls int } func (r *serviceReviewer) Review(_ context.Context, _ string) (callerauth.Identity, error) { r.calls++ return r.identity, r.err } func serviceRequest(t *testing.T, now time.Time) api.CheckRequest { t.Helper() r := api.CheckRequest{Tenant: "tenant:platform", Subject: api.SubjectRef{ID: "secrets-engine", Type: "service"}, Action: "execute-ccr", Resource: api.ResourceRef{ID: "catalog:synthetic", Type: "secret-catalog-lane", System: "secrets-engine", Attributes: map[string]any{"stage": "prod"}}, Context: map[string]any{"human_control": true, "service_actor_binding": DeclaredServiceBinding(), "execution_contract": map[string]any{"contract_version": "SECRETS-EXEC-20261011-v1", "operation": "metadata-apply-ccr", "execution_actor": "service:secrets-engine", "operation_deadline": now.Add(60 * time.Second).Format(time.RFC3339Nano)}}} return r } func TestServicePilotAuthenticatedBinding(t *testing.T) { now := time.Now() reviewer := &serviceReviewer{identity: callerauth.Identity{Username: ServicePilotPrincipal, Audiences: []string{"flex-auth"}, NotAfter: now.Add(120 * time.Second)}} a, e := NewServicePilotInputs(reviewer) if e != nil { t.Fatal(e) } r := serviceRequest(t, now) s, e := a.Prepare(context.Background(), "Bearer synthetic", r, now) if e != nil || reviewer.calls != 1 { t.Fatal("source TokenReview path") } out, e := s.Request() if e != nil || api.RequestDigest(out) != api.RequestDigest(r) || s.Caller().Principal != ServicePilotPrincipal { t.Fatal("binding changed") } r.Context["service_actor_binding"].(map[string]any)["subject_id"] = "mutated" again, _ := s.Request() if again.Context["service_actor_binding"].(map[string]any)["subject_id"] != "secrets-engine" { t.Fatal("opaque input retained mutable caller map") } if _, e := (ServiceInput{}).Request(); e == nil { t.Fatal("zero input trusted") } } func TestServicePilotRefusals(t *testing.T) { now := time.Now() cases := map[string]func(*api.CheckRequest, *serviceReviewer){"human": func(r *api.CheckRequest, _ *serviceReviewer) { r.Subject.Type = "human" }, "subject": func(r *api.CheckRequest, _ *serviceReviewer) { r.Subject.ID = "another" }, "legacy apply": func(r *api.CheckRequest, _ *serviceReviewer) { r.Action = "apply" }, "foreigntenant": func(r *api.CheckRequest, _ *serviceReviewer) { r.Tenant = "tenant:coulomb" }, "wrong service principal": func(_ *api.CheckRequest, p *serviceReviewer) { p.identity.Username = "system:serviceaccount:other:other" }, "wrong audience": func(_ *api.CheckRequest, p *serviceReviewer) { p.identity.Audiences = []string{"openbao"} }, "expired transport": func(_ *api.CheckRequest, p *serviceReviewer) { p.identity.NotAfter = now }, "missing expiry": func(_ *api.CheckRequest, p *serviceReviewer) { p.identity.NotAfter = time.Time{} }, "caller verified": func(r *api.CheckRequest, _ *serviceReviewer) { r.Context["verified"] = true }, "human projection": func(r *api.CheckRequest, _ *serviceReviewer) { r.Context["task_execution_projection"] = map[string]any{"subject": "human"} }, "delegation": func(r *api.CheckRequest, _ *serviceReviewer) { r.Context["delegation"] = false }, "forged binding": func(r *api.CheckRequest, _ *serviceReviewer) { r.Context["service_actor_binding"].(map[string]any)["subject_id"] = "other" }, "lifetime": func(r *api.CheckRequest, _ *serviceReviewer) { r.Context["execution_contract"].(map[string]any)["operation_deadline"] = now.Add(240 * time.Second).Format(time.RFC3339Nano) }} for name, mutate := range cases { t.Run(name, func(t *testing.T) { r := serviceRequest(t, now) p := &serviceReviewer{identity: callerauth.Identity{Username: ServicePilotPrincipal, Audiences: []string{"flex-auth"}, NotAfter: now.Add(120 * time.Second)}} mutate(&r, p) a, _ := NewServicePilotInputs(p) if _, e := a.Prepare(context.Background(), "Bearer synthetic", r, now); e == nil { t.Fatal("invalid input accepted") } }) } p := &serviceReviewer{identity: callerauth.Identity{Username: ServicePilotPrincipal, Audiences: []string{"flex-auth"}, NotAfter: now.Add(time.Minute)}} a, _ := NewServicePilotInputs(p) if _, e := a.Prepare(context.Background(), "", serviceRequest(t, now), now); e == nil { t.Fatal("missing header accepted") } if _, e := NewServicePilotInputs(nil); e == nil { t.Fatal("missing owner reviewer accepted") } } func TestServiceInputRuntimeRecheckAndStrictHTTPDecode(t *testing.T) { now := time.Now().UTC() r := serviceRequest(t, now) reviewer := &serviceReviewer{identity: callerauth.Identity{Username: ServicePilotPrincipal, Audiences: []string{"flex-auth"}, NotAfter: now.Add(120 * time.Second)}} adapter, _ := NewServicePilotInputs(reviewer) input, err := adapter.Prepare(context.Background(), "Bearer synthetic", r, now) if err != nil { t.Fatal(err) } if _, err := input.RequestAt(now); err != nil { t.Fatal(err) } for _, when := range []time.Time{time.Time{}, now.Add(60 * time.Second), now.Add(120 * time.Second)} { if _, err := input.RequestAt(when); err == nil { t.Fatal("stale/invalid runtime input accepted") } } raw, _ := json.Marshal(r) decoded, err := DecodeServiceRequest(bytes.NewReader(raw)) if err != nil || api.RequestDigest(decoded) != api.RequestDigest(r) { t.Fatal("valid decode changed canonical submitted input") } bad := [][]byte{append(append([]byte{}, raw...), []byte(" {}")...), []byte(`{"action":"execute-ccr","action":"apply"}`), []byte(`{"context":{"human_control":true,"human_control":false}}`), []byte(`{"unknown_task_flag":true}`), bytes.Repeat([]byte(" "), 524289)} for _, body := range bad { if _, err := DecodeServiceRequest(bytes.NewReader(body)); err == nil { t.Fatal("malformed/oversized task request accepted") } } }