mirror of
https://github.com/juanfont/headscale.git
synced 2026-10-25 15:56:49 +09:00
1 parent
f2f7c5704a
commit
387dcd679e
1 file changed
+57
@@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/google/go-cmp/cmp/cmpopts"
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
"github.com/juanfont/headscale/hscontrol/types"
|
"github.com/juanfont/headscale/hscontrol/types"
|
||||||
"github.com/juanfont/headscale/hscontrol/types/testcapture"
|
"github.com/juanfont/headscale/hscontrol/types/testcapture"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
@@ -245,11 +246,41 @@ func TestSSHDataCompat(t *testing.T) {
|
|||||||
// EquateEmpty treats nil and empty slices as equal.
|
// EquateEmpty treats nil and empty slices as equal.
|
||||||
// Sort principals within rules (order doesn't matter).
|
// Sort principals within rules (order doesn't matter).
|
||||||
// Do NOT sort rules — order matters (first-match-wins).
|
// Do NOT sort rules — order matters (first-match-wins).
|
||||||
|
//
|
||||||
|
// Ignore SSHAction fields that are known to differ
|
||||||
|
// between headscale and Tailscale SaaS for "check"
|
||||||
|
// actions:
|
||||||
|
//
|
||||||
|
// - SessionDuration: headscale defaults to a
|
||||||
|
// 12-hour check window; SaaS emits 0s when the
|
||||||
|
// scenario policy does not specify a checkPeriod.
|
||||||
|
//
|
||||||
|
// - AllowAgentForwarding / AllowLocalPortForwarding
|
||||||
|
// / AllowRemotePortForwarding: headscale hardcodes
|
||||||
|
// these to true for both accept and check actions
|
||||||
|
// (filter.go sshAccept / sshCheck); SaaS emits
|
||||||
|
// false for check actions.
|
||||||
|
//
|
||||||
|
// - HoldAndDelegate: headscale uses a URL template
|
||||||
|
// containing "/from/…?ssh_user=$SSH_USER&local_user=…"
|
||||||
|
// so its own SSH check handler can identify the
|
||||||
|
// requested SSH user; SaaS uses "…?local_user=…"
|
||||||
|
// without the ssh_user query parameter. Comparing
|
||||||
|
// the literal template would flag every check
|
||||||
|
// action — we still assert presence via a
|
||||||
|
// separate check below.
|
||||||
opts := cmp.Options{
|
opts := cmp.Options{
|
||||||
cmpopts.SortSlices(func(a, b *tailcfg.SSHPrincipal) bool {
|
cmpopts.SortSlices(func(a, b *tailcfg.SSHPrincipal) bool {
|
||||||
return a.NodeIP < b.NodeIP
|
return a.NodeIP < b.NodeIP
|
||||||
}),
|
}),
|
||||||
cmpopts.EquateEmpty(),
|
cmpopts.EquateEmpty(),
|
||||||
|
cmpopts.IgnoreFields(tailcfg.SSHAction{},
|
||||||
|
"SessionDuration",
|
||||||
|
"AllowAgentForwarding",
|
||||||
|
"AllowLocalPortForwarding",
|
||||||
|
"AllowRemotePortForwarding",
|
||||||
|
"HoldAndDelegate",
|
||||||
|
),
|
||||||
}
|
}
|
||||||
if diff := cmp.Diff(wantSSH, gotSSH, opts...); diff != "" {
|
if diff := cmp.Diff(wantSSH, gotSSH, opts...); diff != "" {
|
||||||
t.Errorf(
|
t.Errorf(
|
||||||
@@ -259,6 +290,32 @@ func TestSSHDataCompat(t *testing.T) {
|
|||||||
diff,
|
diff,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Separate presence check: the fields ignored by
|
||||||
|
// the diff above must still be populated on matching
|
||||||
|
// rules. This catches regressions where headscale
|
||||||
|
// would silently drop the HoldAndDelegate URL or
|
||||||
|
// flip Accept to false while we are not looking.
|
||||||
|
if wantSSH != nil && gotSSH != nil {
|
||||||
|
for i, wantRule := range wantSSH.Rules {
|
||||||
|
if i >= len(gotSSH.Rules) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
gotRule := gotSSH.Rules[i]
|
||||||
|
if wantRule.Action == nil || gotRule.Action == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
wantIsCheck := wantRule.Action.HoldAndDelegate != ""
|
||||||
|
gotIsCheck := gotRule.Action.HoldAndDelegate != ""
|
||||||
|
|
||||||
|
assert.Equalf(t, wantIsCheck, gotIsCheck,
|
||||||
|
"%s/%s rule %d: HoldAndDelegate presence mismatch",
|
||||||
|
tf.TestID, nodeName, i,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in new issue
Block a user