diff --git a/acls.go b/acls.go index 63c3955..6446b67 100644 --- a/acls.go +++ b/acls.go @@ -2,6 +2,7 @@ package headscale import ( "encoding/json" + "errors" "fmt" "io" "os" @@ -251,7 +252,21 @@ func expandAlias( if strings.HasPrefix(alias, "tag:") { owners, err := expandTagOwners(aclPolicy, alias, stripEmailDomain) if err != nil { - return ips, err + if errors.Is(err, errInvalidTag) { + for _, machine := range machines { + for _, t := range machine.ForcedTags { + if alias == t { + ips = append(ips, machine.IPAddresses.ToStringSlice()...) + } + } + } + if len(ips) == 0 { + return ips, fmt.Errorf("%w. %v isn't owned by a TagOwner and no forced tags are defined.", errInvalidTag, alias) + } + return ips, nil + } else { + return ips, err + } } for _, namespace := range owners { machines := filterMachinesByNamespace(machines, namespace) @@ -328,6 +343,9 @@ func excludeCorrectlyTaggedNodes( break } } + if len(machine.ForcedTags) > 0 { + found = true + } if !found { out = append(out, machine) } diff --git a/acls_test.go b/acls_test.go index 9dcc40b..6818336 100644 --- a/acls_test.go +++ b/acls_test.go @@ -1017,6 +1017,44 @@ func Test_expandAlias(t *testing.T) { want: []string{}, wantErr: true, }, + { + name: "Forced tag defined", + args: args{ + alias: "tag:hr-webserver", + machines: []Machine{ + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "joe"}, + ForcedTags: []string{"tag:hr-webserver"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "joe"}, + ForcedTags: []string{"tag:hr-webserver"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.3"), + }, + Namespace: Namespace{Name: "marc"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.4"), + }, + Namespace: Namespace{Name: "mickael"}, + }, + }, + aclPolicy: ACLPolicy{}, + stripEmailDomain: true, + }, + want: []string{"100.64.0.1", "100.64.0.2"}, + wantErr: false, + }, { name: "list host in namespace without correctly tagged servers", args: args{ @@ -1143,6 +1181,47 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { }, }, }, + { + name: "exclude nodes with valid tags and with forced tags", + args: args{ + aclPolicy: ACLPolicy{ + TagOwners: TagOwners{"tag:accountant-webserver": []string{"joe"}}, + }, + nodes: []Machine{ + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "joe"}, + HostInfo: HostInfo{ + OS: "centos", + Hostname: "foo", + RequestTags: []string{"tag:accountant-webserver"}, + }, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "joe"}, + ForcedTags: []string{"tag:accountant-webserver"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.4"), + }, + Namespace: Namespace{Name: "joe"}, + }, + }, + namespace: "joe", + }, + want: []Machine{ + { + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, + Namespace: Namespace{Name: "joe"}, + }, + }, + }, { name: "all nodes have invalid tags, don't exclude them", args: args{