mirror of
https://github.com/juanfont/headscale.git
synced 2026-11-04 04:34:07 +09:00
policy/v2: resolve user:*@domain to that domain's users
SaaS accepts it and lists those users' nodes. It was accepted here too, then compiled to nothing with no log line.
This commit is contained in:
1 parent
6647cb2e05
commit
98b3900470
3 files changed
+17
-16
No files matched your search
@@ -141,19 +141,7 @@ func loadGrantTestFile(t *testing.T, path string) *testcapture.Capture {
|
||||
|
||||
// Skip categories document WHY tests are expected to differ from Tailscale SaaS.
|
||||
// Tests are grouped by root cause.
|
||||
//
|
||||
// USER_PASSKEY_WILDCARD - 2 tests: user:*@passkey wildcard pattern not supported
|
||||
//
|
||||
// Total: 2 tests skipped, ~246 tests expected to pass.
|
||||
var grantSkipReasons = map[string]string{
|
||||
// USER_PASSKEY_WILDCARD (2 tests)
|
||||
//
|
||||
// Tailscale SaaS policies can use user:*@passkey as a wildcard matching
|
||||
// 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",
|
||||
|
||||
// SaaS lists contiguous source addresses one by one and writes
|
||||
// autogroup:internet as address ranges; headscale merges sources into
|
||||
// ranges and writes the internet as prefixes. The address sets match;
|
||||
|
||||
@@ -124,10 +124,7 @@ func TestSSHForwardingDataCompat(t *testing.T) {
|
||||
// sshSkipReasons documents captures the upstream control plane accepts
|
||||
// but headscale cannot yet represent, keyed <test_id> for the whole capture
|
||||
// or <test_id>/<node>/<check>. Each entry names the feature gap.
|
||||
var sshSkipReasons = map[string]string{
|
||||
"ssh-b5": "headscale has no passkey authentication; user:*@passkey wildcard unsupported",
|
||||
"ssh-d10": "headscale has no passkey authentication; user:*@passkey wildcard unsupported",
|
||||
}
|
||||
var sshSkipReasons = map[string]string{}
|
||||
|
||||
// sshRejectSkipReasons documents captures the upstream control plane
|
||||
// rejects for reasons headscale cannot apply, keyed <test_id> for the whole
|
||||
|
||||
@@ -498,6 +498,22 @@ func (u *Username) Resolve(_ *Policy, users types.Users, nodes views.Slice[types
|
||||
func (u *Username) resolve(_ *Policy, users types.Users, nodes views.Slice[types.NodeView]) (*netipx.IPSet, error) {
|
||||
var ips netipx.IPSetBuilder
|
||||
|
||||
// user:*@domain names every user of that email domain, as on SaaS.
|
||||
if domain, ok := strings.CutPrefix(string(*u), "user:*@"); ok {
|
||||
for _, node := range nodes.All() {
|
||||
if node.IsTagged() || !node.User().Valid() {
|
||||
continue
|
||||
}
|
||||
|
||||
_, emailDomain, found := strings.CutLast(node.User().Email(), "@")
|
||||
if found && strings.EqualFold(emailDomain, domain) {
|
||||
node.AppendToIPSet(&ips)
|
||||
}
|
||||
}
|
||||
|
||||
return ips.IPSet()
|
||||
}
|
||||
|
||||
user, err := u.resolveUser(users)
|
||||
if err != nil {
|
||||
// Users may be missing before registration (#2863), or become
|
||||
|
||||
Reference in new issue
Block a user