hscontrol/policy/v2: add skip entries for 25 v2 gap-filling grant tests

Update the grants compatibility test skip list with 23 new entries for
the V-series tests (V07 and V24 pass without skipping).

New skip categories introduced:
- VIA_COMPILATION (3): via routes with specific src identities where
  there is no SrcIPs format issue (V11, V12, V13)
- Additional VIA_COMPILATION_AND_SRCIPS_FORMAT (3): via with wildcard
  src (V17, V21, V23)
- Additional CAPGRANT_COMPILATION (6): app grants on specific tags,
  drive cap, autogroup:self app (V02, V03, V06, V19, V20, V25)
- Additional CAPGRANT_COMPILATION_AND_SRCIPS_FORMAT (2): mixed ip+app
  on specific tags rejected by headscale (V09, V10)
- Additional ERROR_VALIDATION_GAP (9): autogroup:internet + app,
  raw 0.0.0.0/0 and ::/0 as grant dst (V01, V04, V05, V08, V14-V16,
  V18, V22)

Test totals: 237 total, 21 pass, 216 skip, 0 fail.

Updates #2180
This commit is contained in:
Kristoffer Dalby
2026-02-23 16:44:20 +00:00
parent aa68fbafc0
commit 646a6e8266

View File

@@ -1,5 +1,5 @@
// This file is "generated" by Claude.
// It contains a data-driven test that reads 212 GRANT-*.json test files
// It contains a data-driven test that reads 237 GRANT-*.json test files
// captured from Tailscale SaaS. Each file contains:
// - A policy with grants (and optionally ACLs)
// - The expected packet_filter_rules for each of 8 test nodes
@@ -387,7 +387,7 @@ var grantSkipReasons = map[string]string{
"GRANT-P15_3": "SRCIPS_FORMAT",
// ========================================================================
// CAPGRANT_COMPILATION (41 tests)
// CAPGRANT_COMPILATION (49 tests)
//
// TODO: Implement app capability grant -> CapGrant FilterRule compilation.
//
@@ -461,13 +461,25 @@ var grantSkipReasons = map[string]string{
"GRANT-K25": "CAPGRANT_COMPILATION",
"GRANT-K27": "CAPGRANT_COMPILATION",
// V-series: App caps on specific tags, drive cap, autogroup:self app
"GRANT-V02": "CAPGRANT_COMPILATION: app grant on tag:exit — CapGrant with exit-node IPs as Dsts not compiled",
"GRANT-V03": "CAPGRANT_COMPILATION: app grant on tag:router — CapGrant with router IPs as Dsts not compiled",
"GRANT-V06": "CAPGRANT_COMPILATION: multi-dst app grant on [tag:server, tag:exit] — per-node CapGrant not compiled",
"GRANT-V19": "CAPGRANT_COMPILATION: drive cap on tag:exit — drive CapGrant + reverse drive-sharer not compiled",
"GRANT-V20": "CAPGRANT_COMPILATION: kubernetes cap on tag:router — CapGrant not compiled",
"GRANT-V25": "CAPGRANT_COMPILATION: autogroup:self app grant — self-targeting CapGrant per member not compiled",
// ========================================================================
// CAPGRANT_COMPILATION_AND_SRCIPS_FORMAT (9 tests)
// CAPGRANT_COMPILATION_AND_SRCIPS_FORMAT (11 tests)
//
// TODO: These tests have BOTH DstPorts and CapGrant FilterRules.
// They require both CapGrant compilation AND SrcIPs format fixes.
// Grants with both "ip" and "app" fields produce two separate FilterRules:
// one with DstPorts (from "ip") and one with CapGrant (from "app").
//
// V09/V10: headscale currently rejects mixed ip+app grants with
// "grants cannot specify both 'ip' and 'app' fields", but Tailscale
// accepts them and produces two FilterRules per grant.
// ========================================================================
// F-series: Mixed ip+app grants
@@ -485,8 +497,25 @@ var grantSkipReasons = map[string]string{
"GRANT-K5": "CAPGRANT_COMPILATION_AND_SRCIPS_FORMAT",
"GRANT-K28": "CAPGRANT_COMPILATION_AND_SRCIPS_FORMAT",
// V-series: Mixed ip+app on specific tags
"GRANT-V09": "CAPGRANT_COMPILATION_AND_SRCIPS_FORMAT: mixed ip+app on tag:exit — headscale rejects, Tailscale produces DstPorts + CapGrant",
"GRANT-V10": "CAPGRANT_COMPILATION_AND_SRCIPS_FORMAT: mixed ip+app on tag:router — headscale rejects, Tailscale produces DstPorts + CapGrant",
// ========================================================================
// VIA_COMPILATION_AND_SRCIPS_FORMAT (4 tests)
// VIA_COMPILATION (3 tests)
//
// TODO: Implement via route compilation in filter rules.
//
// Via routes with specific (non-wildcard) sources produce DstPorts rules
// with correctly restricted SrcIPs. These tests have no SrcIPs format
// issue because they use specific src identities (tags, groups, members).
// ========================================================================
"GRANT-V11": "VIA_COMPILATION: via tag:router + src:tag:client — SrcIPs = client IPs only",
"GRANT-V12": "VIA_COMPILATION: via tag:router + src:autogroup:member — SrcIPs = member IPs",
"GRANT-V13": "VIA_COMPILATION: via tag:router + src:group:developers + tcp:80,443 — group SrcIPs + specific ports",
// ========================================================================
// VIA_COMPILATION_AND_SRCIPS_FORMAT (7 tests)
//
// TODO: Implement via route compilation in filter rules.
//
@@ -494,12 +523,16 @@ var grantSkipReasons = map[string]string{
// CIDR should be routed through a specific tagged subnet router. The via
// field is currently parsed and validated but NOT compiled into FilterRules.
//
// These tests also have SrcIPs format differences.
// These tests also have SrcIPs format differences (wildcard src expands
// to split CGNAT ranges).
// ========================================================================
"GRANT-I1": "VIA_COMPILATION_AND_SRCIPS_FORMAT",
"GRANT-I2": "VIA_COMPILATION_AND_SRCIPS_FORMAT",
"GRANT-I3": "VIA_COMPILATION_AND_SRCIPS_FORMAT",
"GRANT-K13": "VIA_COMPILATION_AND_SRCIPS_FORMAT",
"GRANT-V17": "VIA_COMPILATION_AND_SRCIPS_FORMAT: via tag:router + multi-dst — unadvertised subnets silently dropped",
"GRANT-V21": "VIA_COMPILATION_AND_SRCIPS_FORMAT: via [tag:router, tag:exit] — only advertising nodes get rules",
"GRANT-V23": "VIA_COMPILATION_AND_SRCIPS_FORMAT: via tag:router + tcp:22,80,443 — via + multiple ports",
// ========================================================================
// AUTOGROUP_DANGER_ALL (3 tests)
@@ -519,7 +552,7 @@ var grantSkipReasons = map[string]string{
"GRANT-K8": "AUTOGROUP_DANGER_ALL",
// ========================================================================
// ERROR_VALIDATION_GAP (12 tests)
// ERROR_VALIDATION_GAP (23 tests)
//
// TODO: Implement grant validation rules that Tailscale enforces but
// headscale does not yet.
@@ -555,6 +588,22 @@ var grantSkipReasons = map[string]string{
// Tailscale requires "via" to be a tag, rejects other values.
"GRANT-I4": "ERROR_VALIDATION_GAP: via can only be a tag — headscale should reject non-tag via values",
// autogroup:internet + app grants validation:
// Tailscale rejects app grants when dst includes autogroup:internet.
"GRANT-V01": "ERROR_VALIDATION_GAP: cannot use app grants with autogroup:internet — headscale does not reject",
"GRANT-V22": "ERROR_VALIDATION_GAP: cannot use app grants with autogroup:internet — headscale returns different error (rejects mixed ip+app instead)",
// Raw default route CIDR validation:
// Tailscale rejects 0.0.0.0/0 and ::/0 as grant dst, requiring "*" or
// "autogroup:internet" instead. This applies with or without via.
"GRANT-V04": "ERROR_VALIDATION_GAP: dst 0.0.0.0/0 rejected — headscale should reject raw default route CIDRs in grant dst",
"GRANT-V05": "ERROR_VALIDATION_GAP: dst ::/0 rejected — headscale should reject raw default route CIDRs in grant dst",
"GRANT-V08": "ERROR_VALIDATION_GAP: dst 0.0.0.0/0 with ip grant — same rejection as V04",
"GRANT-V14": "ERROR_VALIDATION_GAP: dst 0.0.0.0/0 with via — rejected even with via field",
"GRANT-V15": "ERROR_VALIDATION_GAP: dst ::/0 with via — rejected even with via field",
"GRANT-V16": "ERROR_VALIDATION_GAP: dst [0.0.0.0/0, ::/0] with via — both rejected",
"GRANT-V18": "ERROR_VALIDATION_GAP: dst 0.0.0.0/0 with via + app — rejected regardless of via or app",
// Empty src/dst validation difference:
// Tailscale ACCEPTS empty src/dst arrays (producing no filter rules),
// but headscale rejects them with "grant sources/destinations cannot be empty".
@@ -576,7 +625,7 @@ var grantSkipReasons = map[string]string{
// ========================================================================
}
// TestGrantsCompat is a data-driven test that loads all 212 GRANT-*.json
// TestGrantsCompat is a data-driven test that loads all 237 GRANT-*.json
// test files captured from Tailscale SaaS and compares headscale's grants
// engine output against the real Tailscale behavior.
//