Skip to content

Commit

Permalink
Split GetRouteApprovers from EnableAutoApprovedRoutes
Browse files Browse the repository at this point in the history
  • Loading branch information
tsujamin committed Aug 25, 2022
1 parent 004ebca commit 7653ad4
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 40 deletions.
25 changes: 25 additions & 0 deletions acls_types.go
Expand Up @@ -108,3 +108,28 @@ func (policy ACLPolicy) IsZero() bool {

return false
}

// Returns the list of autoApproving namespaces, groups or tags for a given IPPrefix
func (autoApprovers *AutoApprovers) GetRouteApprovers(
prefix netaddr.IPPrefix,
) ([]string, error) {
if prefix.Bits() == 0 {
return autoApprovers.ExitNode, nil // 0.0.0.0/0, ::/0 or equivalent
}

approverAliases := []string{}

for autoApprovedPrefix, autoApproverAliases := range autoApprovers.Routes {
autoApprovedPrefix, err := netaddr.ParseIPPrefix(autoApprovedPrefix)
if err != nil {
return nil, err
}

if autoApprovedPrefix.Bits() >= prefix.Bits() &&
autoApprovedPrefix.Contains(prefix.IP()) {
approverAliases = append(approverAliases, autoApproverAliases...)
}
}

return approverAliases, nil
}
68 changes: 28 additions & 40 deletions machine.go
Expand Up @@ -931,60 +931,48 @@ func (h *Headscale) EnableRoutes(machine *Machine, routeStrs ...string) error {
}

// Enabled any routes advertised by a machine that match the ACL autoApprovers policy
// TODO simplify by expanding only for current machine, and by checking if approvedIPs contains machine.IPs[0]
func (h *Headscale) EnableAutoApprovedRoutes(machine *Machine) error {
approvedRoutes := make([]netaddr.IPPrefix, 0, len(machine.HostInfo.RoutableIPs))
machines, err := h.ListMachines()

if err != nil {
log.Err(err)
return err
if len(machine.IPAddresses) == 0 {
return nil // This machine has no IPAddresses, so can't possibly match any autoApprovers ACLs
}

approvedRoutes := make([]netaddr.IPPrefix, 0, len(machine.HostInfo.RoutableIPs))
thisMachine := []Machine{*machine}

for _, advertisedRoute := range machine.HostInfo.RoutableIPs {
log.Debug().
Uint64("machine", machine.ID).
Str("advertisedRoute", advertisedRoute.String()).
Msg("Client requested to advertise route")

if contains(machine.EnabledRoutes, advertisedRoute) {
continue // Skip routes that are already enabled for the node
}

approved := false
routeApprovers := h.aclPolicy.AutoApprovers.Routes[advertisedRoute.String()]
routeApprovers, err := h.aclPolicy.AutoApprovers.GetRouteApprovers(advertisedRoute)

if advertisedRoute.Bits() == 0 {
routeApprovers = h.aclPolicy.AutoApprovers.ExitNode
if err != nil {
log.Err(err).
Str("advertisedRoute", advertisedRoute.String()).
Uint64("machineId", machine.ID).
Msg("Failed to resolve autoApprovers for advertised route")
return err
}

if len(routeApprovers) > 0 {
for _, approvedAlias := range routeApprovers {

approvedIps, err := expandAlias(machines, *h.aclPolicy, approvedAlias, h.cfg.OIDC.StripEmaildomain)
for _, approvedAlias := range routeApprovers {

if err != nil {
log.Err(err).
Str("alias", approvedAlias).
Msg("Failed to expand alias when processing autoApprovers policy")
return err
}
approvedIps, err := expandAlias(thisMachine, *h.aclPolicy, approvedAlias, h.cfg.OIDC.StripEmaildomain)

for _, machineIp := range machine.IPAddresses {
for _, approvedIp := range approvedIps {
approved = machineIp.String() == approvedIp
if err != nil {
log.Err(err).
Str("alias", approvedAlias).
Msg("Failed to expand alias when processing autoApprovers policy")
return err
}

if approved {
break
}
}
// approvedIPs should contain all of machine's IPs if it matches the rule, so check for first
approved = contains(approvedIps, machine.IPAddresses[0].String())

if approved {
break
}
}
if approved {
break
}
} else {
log.Debug().
Uint64("client", machine.ID).
Str("advertisedRoute", advertisedRoute.String()).
Msg("Advertised route is not automatically approved")
}

if approved {
Expand Down

0 comments on commit 7653ad4

Please sign in to comment.