policy/v2: validate autogroup:interet only in dst (#2552)

This commit is contained in:
Kristoffer Dalby 2025-05-02 13:58:12 +03:00 committed by GitHub
parent 7dc86366b4
commit e4d10ad964
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 128 additions and 3 deletions

View File

@ -382,13 +382,13 @@ func (p Prefix) Resolve(_ *Policy, _ types.Users, nodes types.Nodes) (*netipx.IP
type AutoGroup string
const (
AutoGroupInternet = "autogroup:internet"
AutoGroupInternet AutoGroup = "autogroup:internet"
)
var autogroups = []string{AutoGroupInternet}
var autogroups = []AutoGroup{AutoGroupInternet}
func (ag AutoGroup) Validate() error {
if slices.Contains(autogroups, string(ag)) {
if slices.Contains(autogroups, ag) {
return nil
}
@ -412,6 +412,14 @@ func (ag AutoGroup) Resolve(_ *Policy, _ types.Users, _ types.Nodes) (*netipx.IP
return nil, nil
}
func (ag *AutoGroup) Is(c AutoGroup) bool {
if ag == nil {
return false
}
return *ag == c
}
type Alias interface {
Validate() error
UnmarshalJSON([]byte) error
@ -928,6 +936,32 @@ func (p *Policy) validate() error {
if !p.Hosts.exist(*h) {
errs = append(errs, fmt.Errorf(`Host %q is not defined in the Policy, please define or remove the reference to it`, *h))
}
case *AutoGroup:
ag := src.(*AutoGroup)
if ag.Is(AutoGroupInternet) {
errs = append(errs, fmt.Errorf(`"autogroup:internet" used in source, it can only be used in ACL destinations`))
}
}
}
}
for _, ssh := range p.SSHs {
for _, src := range ssh.Sources {
switch src.(type) {
case *AutoGroup:
ag := src.(*AutoGroup)
if ag.Is(AutoGroupInternet) {
errs = append(errs, fmt.Errorf(`"autogroup:internet" used in SSH source, it can only be used in ACL destinations`))
}
}
}
for _, dst := range ssh.Destinations {
switch dst.(type) {
case *AutoGroup:
ag := dst.(*AutoGroup)
if ag.Is(AutoGroupInternet) {
errs = append(errs, fmt.Errorf(`"autogroup:internet" used in SSH destination, it can only be used in ACL destinations`))
}
}
}
}

View File

@ -420,6 +420,97 @@ func TestUnmarshalPolicy(t *testing.T) {
},
},
},
{
name: "autogroup:internet-in-dst-allowed",
input: `
{
"acls": [
{
"action": "accept",
"src": [
"10.0.0.1"
],
"dst": [
"autogroup:internet:*"
]
}
]
}
`,
want: &Policy{
ACLs: []ACL{
{
Action: "accept",
Sources: Aliases{
pp("10.0.0.1/32"),
},
Destinations: []AliasWithPorts{
{
Alias: ptr.To(AutoGroup("autogroup:internet")),
Ports: []tailcfg.PortRange{tailcfg.PortRangeAny},
},
},
},
},
},
},
{
name: "autogroup:internet-in-src-not-allowed",
input: `
{
"acls": [
{
"action": "accept",
"src": [
"autogroup:internet"
],
"dst": [
"10.0.0.1:*"
]
}
]
}
`,
wantErr: `"autogroup:internet" used in source, it can only be used in ACL destinations`,
},
{
name: "autogroup:internet-in-ssh-src-not-allowed",
input: `
{
"ssh": [
{
"action": "accept",
"src": [
"autogroup:internet"
],
"dst": [
"tag:test"
]
}
]
}
`,
wantErr: `"autogroup:internet" used in SSH source, it can only be used in ACL destinations`,
},
{
name: "autogroup:internet-in-ssh-dst-not-allowed",
input: `
{
"ssh": [
{
"action": "accept",
"src": [
"tag:test"
],
"dst": [
"autogroup:internet"
]
}
]
}
`,
wantErr: `"autogroup:internet" used in SSH destination, it can only be used in ACL destinations`,
},
}
cmps := append(util.Comparers, cmp.Comparer(func(x, y Prefix) bool {