mirror of
https://github.com/juanfont/headscale.git
synced 2026-09-26 02:04:53 +09:00
policy/v2: compare peer CapMap against SaaS route captures
SaaS stamps suggest-exit-node on approved exit peers without nodeAttrs.
Updates #3415
(cherry picked from commit 0e8a3bba54)
This commit is contained in:
committed by
Kristoffer Dalby
parent
8490631f06
commit
694bafee0a
@@ -1507,6 +1507,76 @@ func TestRoutesCompatPeerAllowedIPs(t *testing.T) {
|
||||
)
|
||||
}
|
||||
|
||||
// TestRoutesCompatPeerCapMap validates the peer-view CapMap against SaaS
|
||||
// for route scenarios, whose policies carry no nodeAttrs. SaaS stamps
|
||||
// suggest-exit-node on approved exit peers regardless of policy; the
|
||||
// Apple 1.102+ GUI hides the exit-node list without it (issue #3415).
|
||||
func TestRoutesCompatPeerCapMap(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files, err := filepath.Glob(
|
||||
filepath.Join("testdata", "routes_results", "routes-*.hujson"),
|
||||
)
|
||||
require.NoError(t, err, "failed to glob test files")
|
||||
require.NotEmpty(t, files)
|
||||
|
||||
issue3212, err := filepath.Glob(
|
||||
filepath.Join("testdata", "issue_3212", "routes-*.hujson"),
|
||||
)
|
||||
require.NoError(t, err, "failed to glob issue_3212 files")
|
||||
require.NotEmpty(t, issue3212)
|
||||
|
||||
files = append(files, issue3212...)
|
||||
|
||||
for _, file := range files {
|
||||
tf := loadRoutesTestFile(t, file)
|
||||
if tf.Error {
|
||||
continue
|
||||
}
|
||||
|
||||
t.Run(tf.TestID, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
users, nodes := buildRoutesUsersAndNodes(t, tf.Topology)
|
||||
policyJSON := convertPolicyUserEmails(tf.Input.FullPolicy)
|
||||
|
||||
pm, err := NewPolicyManager(policyJSON, users, nodes.ViewSlice())
|
||||
require.NoError(t, err, "%s: failed to create policy manager", tf.TestID)
|
||||
|
||||
capMaps := pm.NodeCapMaps()
|
||||
|
||||
for viewerName, capture := range tf.Captures {
|
||||
if capture.Netmap == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, nmPeer := range capture.Netmap.Peers {
|
||||
peerName, _, _ := strings.Cut(nmPeer.Name(), ".")
|
||||
|
||||
peer := findNodeByGivenName(nodes, peerName)
|
||||
if peer == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
got := stripUnmodelledTailnetStateCaps(
|
||||
PeerCapMap(peer.View(), capMaps[peer.ID]),
|
||||
)
|
||||
want := stripUnmodelledTailnetStateCaps(
|
||||
capMapFromView(nmPeer.CapMap()),
|
||||
)
|
||||
|
||||
if diff := cmp.Diff(want, got, cmpopts.EquateEmpty()); diff != "" {
|
||||
t.Errorf(
|
||||
"%s/%s/peer=%s: Peer.CapMap mismatch (-tailscale +headscale):\n%s",
|
||||
tf.TestID, viewerName, peerName, diff,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// testRoutesError verifies that an invalid policy produces the expected error.
|
||||
func testRoutesError(t *testing.T, tf *testcapture.Capture) {
|
||||
t.Helper()
|
||||
|
||||
Reference in New Issue
Block a user