diff --git a/hscontrol/policy/v2/tailscale_grants_compat_test.go b/hscontrol/policy/v2/tailscale_grants_compat_test.go index d48c15ec..f983aeff 100644 --- a/hscontrol/policy/v2/tailscale_grants_compat_test.go +++ b/hscontrol/policy/v2/tailscale_grants_compat_test.go @@ -324,52 +324,36 @@ func loadGrantTestFile(t *testing.T, path string) grantTestFile { return tf } -// Skip categories document WHY tests are expected to fail and WHAT needs to be -// implemented to fix them. Tests are grouped by root cause to identify high-impact -// changes. +// Skip categories document WHY tests are expected to differ from Tailscale SaaS. +// Tests are grouped by root cause. // -// Impact summary (highest first): +// USER_PASSKEY_WILDCARD - 2 tests: user:*@passkey wildcard pattern not supported // -// USER_PASSKEY_WILDCARD - 2 tests: user:*@passkey wildcard pattern unresolvable -// -// Total: 2 tests skipped, ~235 tests expected to pass. +// Total: 2 tests skipped, ~246 tests expected to pass. var grantSkipReasons = map[string]string{ - // ======================================================================== // USER_PASSKEY_WILDCARD (2 tests) // - // TODO: Handle user:*@passkey wildcard pattern in grant src/dst. - // // Tailscale SaaS policies can use user:*@passkey as a wildcard matching - // all passkey-authenticated users. headscale's convertPolicyUserEmails - // only converts specific user@passkey addresses (not the wildcard form), - // so the filter compiler logs "user not found: token user:*@passkey" - // and produces no rules. - // - // Fix: Either convert user:*@passkey to a headscale-compatible wildcard, - // or resolve it to all known users during filter compilation. - // ======================================================================== - "GRANT-K20": "USER_PASSKEY_WILDCARD: src=user:*@passkey, dst=tag:server — source can't be resolved, no rules produced", - "GRANT-K21": "USER_PASSKEY_WILDCARD: src=*, dst=user:*@passkey — destination can't be resolved, no rules produced", + // all passkey-authenticated users. headscale does not support passkey + // authentication and has no equivalent for this wildcard pattern. + "GRANT-K20": "USER_PASSKEY_WILDCARD: src=user:*@passkey not supported in headscale", + "GRANT-K21": "USER_PASSKEY_WILDCARD: dst=user:*@passkey not supported in headscale", } -// TestGrantsCompat is a data-driven test that loads all 237 GRANT-*.json +// TestGrantsCompat is a data-driven test that loads all GRANT-*.json // test files captured from Tailscale SaaS and compares headscale's grants // engine output against the real Tailscale behavior. // // Each JSON file contains: // - A full policy (groups, tagOwners, hosts, autoApprovers, grants, optionally acls) -// - For success cases: expected packet_filter_rules per node (8 nodes) +// - For success cases: expected packet_filter_rules per node // - For error cases: expected error message // // The test converts Tailscale user email formats (@passkey, @dalby.cc) to // headscale format (@example.com) and runs the policy through unmarshalPolicy, // validate, compileFilterRulesForNode, and ReduceFilterRules. // -// Skip category impact summary (highest first): -// -// USER_PASSKEY_WILDCARD - 2 tests: user:*@passkey wildcard pattern unresolvable -// -// Total: 2 tests skipped, ~235 tests expected to pass. +// 2 tests are skipped for user:*@passkey wildcard (not supported in headscale). func TestGrantsCompat(t *testing.T) { t.Parallel() diff --git a/hscontrol/policy/v2/tailscale_ssh_data_compat_test.go b/hscontrol/policy/v2/tailscale_ssh_data_compat_test.go index b94460e9..75c9420a 100644 --- a/hscontrol/policy/v2/tailscale_ssh_data_compat_test.go +++ b/hscontrol/policy/v2/tailscale_ssh_data_compat_test.go @@ -204,12 +204,11 @@ func loadSSHTestFile(t *testing.T, path string) sshTestFile { // // 37 of 39 tests are expected to pass. var sshSkipReasons = map[string]string{ - // user:*@domain source alias not yet implemented. - // These tests use "src": ["user:*@passkey"] which requires UserWildcard - // alias type support. Will be added in a follow-up PR that implements - // user:*@domain across all contexts (ACLs, grants, tagOwners, autoApprovers). - "SSH-B5": "user:*@domain source alias not yet implemented", - "SSH-D10": "user:*@domain source alias not yet implemented", + // user:*@passkey wildcard pattern not supported in headscale. + // headscale does not support passkey authentication and has no + // equivalent for this wildcard pattern. + "SSH-B5": "user:*@passkey wildcard not supported in headscale", + "SSH-D10": "user:*@passkey wildcard not supported in headscale", } // TestSSHDataCompat is a data-driven test that loads all SSH-*.json test files diff --git a/hscontrol/policy/v2/types.go b/hscontrol/policy/v2/types.go index 732d18c8..2b3fc4fa 100644 --- a/hscontrol/policy/v2/types.go +++ b/hscontrol/policy/v2/types.go @@ -69,14 +69,10 @@ var ( var ( ErrGrantMissingIPOrApp = errors.New("grants must specify either 'ip' or 'app' field") ErrGrantInvalidViaTag = errors.New("grant 'via' tag is not defined in policy") - ErrGrantViaNotSupported = errors.New("grant 'via' routing is not yet supported in headscale") - ErrGrantEmptySources = errors.New("grant sources cannot be empty") - ErrGrantEmptyDestinations = errors.New("grant destinations cannot be empty") ErrProtocolPortInvalidFormat = errors.New("expected only one colon in Internet protocol and port type") ErrCapNameInvalidForm = errors.New("capability name must have the form {domain}/{path}") ErrCapNameTailscaleDomain = errors.New("capability name must not be in the tailscale.com domain") ErrGrantAutogroupSelfInvalidSource = errors.New("autogroup:self can only be used with users, groups, or supported autogroups") - ErrGrantViaOnlyTag = errors.New("via can only be a tag") ErrGrantAppWithAutogroupInternet = errors.New("cannot use app grants with autogroup:internet") ErrGrantDefaultRouteCIDR = errors.New("to allow all IP addresses, use \"*\" or \"autogroup:internet\"") ) @@ -1899,7 +1895,6 @@ type Grant struct { InternetProtocols []ProtocolPort `json:"ip,omitempty"` App tailcfg.PeerCapMap `json:"app,omitzero"` - // TODO(kradalby): implement via Via []Tag `json:"via,omitzero"` }