From 82df3e088a06d3b06ee4a40732aa8a80fc9e7591 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Wed, 30 Sep 2026 15:03:20 +0000 Subject: [PATCH] servertest: test client drops SSH rules on policy removal Updates #3508 --- hscontrol/servertest/policy_test.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/hscontrol/servertest/policy_test.go b/hscontrol/servertest/policy_test.go index 5bc6bc4a3..569328cc5 100644 --- a/hscontrol/servertest/policy_test.go +++ b/hscontrol/servertest/policy_test.go @@ -129,6 +129,34 @@ func TestPolicyChanges(t *testing.T) { } }) + // https://github.com/juanfont/headscale/issues/3508 + t.Run("ssh_removal_clears_client_ssh_policy", func(t *testing.T) { + t.Parallel() + h := servertest.NewHarness(t, 2) + + h.ChangePolicy(t, []byte(`{ + "acls": [], + "ssh": [{ + "action": "accept", + "src": ["autogroup:member"], + "dst": ["autogroup:self"], + "users": ["root"] + }] + }`)) + + h.Client(0).WaitForCondition(t, "SSH rules present", 10*time.Second, + func(nm *netmap.NetworkMap) bool { + return nm.SSHPolicy != nil && len(nm.SSHPolicy.Rules) > 0 + }) + + h.ChangePolicy(t, []byte(`{"acls": []}`)) + + h.Client(0).WaitForCondition(t, "SSH rules cleared", 10*time.Second, + func(nm *netmap.NetworkMap) bool { + return nm.SSHPolicy != nil && len(nm.SSHPolicy.Rules) == 0 + }) + }) + t.Run("policy_with_multiple_users", func(t *testing.T) { t.Parallel()