From 88339d8ff1152f01ed066b8542352179d6c37533 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sat, 31 Oct 2026 14:20:27 +0000 Subject: [PATCH] servertest: pin the refusal of a policy naming autogroup:admin The replay rewrites the autogroup away, so nothing showed this difference. --- hscontrol/servertest/mapstream_compat_test.go | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/hscontrol/servertest/mapstream_compat_test.go b/hscontrol/servertest/mapstream_compat_test.go index 196d36e0c..d487a0b3d 100644 --- a/hscontrol/servertest/mapstream_compat_test.go +++ b/hscontrol/servertest/mapstream_compat_test.go @@ -1594,6 +1594,40 @@ func (r *stepReplay) applyUserRole(t *testing.T, step testcapture.Step) { } } +// TestAdminRolePolicyRefusedCompat pins NO_USER_ROLES on the policy the replay +// rewrites: SaaS accepts a policy naming autogroup:admin, and headscale, which +// has no user roles, refuses all of it. +func TestAdminRolePolicyRefusedCompat(t *testing.T) { + t.Parallel() + + c := readStepCapture(t, userRoleID) + srv := servertest.NewServer(t) + refused := 0 + + for _, a := range c.Steps[0].Actions { + if a.Method != http.MethodPost || !strings.HasPrefix(a.Path, "/tailnet/-/acl") { + continue + } + + require.Equal(t, http.StatusOK, a.Status, "%s: SaaS accepted this policy", a.Path) + + // A HuJSON body is recorded as a string, a JSON one as it was sent. + body := a.Body + + var text string + if json.Unmarshal(a.Body, &text) == nil { + body = []byte(text) + } + + require.Contains(t, string(body), "autogroup:admin", a.Path) + require.ErrorContains(t, srv.State().ValidatePolicy(body), "autogroup", a.Path) + + refused++ + } + + require.Positive(t, refused) +} + // adminPolicy replaces autogroup:admin in policy with the owner and the // names [stepReplay.roleRename] gives admins. func adminPolicy(owner, policy string) string {