mirror of
https://github.com/juanfont/headscale.git
synced 2024-11-26 08:53:05 +00:00
initial implementation of autoApprovers support
This commit is contained in:
parent
cc0bec15ef
commit
004ebcaba1
3 changed files with 95 additions and 5 deletions
|
@ -11,11 +11,12 @@ import (
|
|||
|
||||
// ACLPolicy represents a Tailscale ACL Policy.
|
||||
type ACLPolicy struct {
|
||||
Groups Groups `json:"groups" yaml:"groups"`
|
||||
Hosts Hosts `json:"hosts" yaml:"hosts"`
|
||||
TagOwners TagOwners `json:"tagOwners" yaml:"tagOwners"`
|
||||
ACLs []ACL `json:"acls" yaml:"acls"`
|
||||
Tests []ACLTest `json:"tests" yaml:"tests"`
|
||||
Groups Groups `json:"groups" yaml:"groups"`
|
||||
Hosts Hosts `json:"hosts" yaml:"hosts"`
|
||||
TagOwners TagOwners `json:"tagOwners" yaml:"tagOwners"`
|
||||
ACLs []ACL `json:"acls" yaml:"acls"`
|
||||
Tests []ACLTest `json:"tests" yaml:"tests"`
|
||||
AutoApprovers AutoApprovers `json:"autoApprovers" yaml:"autoApprovers"`
|
||||
}
|
||||
|
||||
// ACL is a basic rule for the ACL Policy.
|
||||
|
@ -42,6 +43,13 @@ type ACLTest struct {
|
|||
Deny []string `json:"deny,omitempty" yaml:"deny,omitempty"`
|
||||
}
|
||||
|
||||
// AutoApprovers specify which users (namespaces?), groups or tags have their advertised routes
|
||||
// or exit node status automatically enabled
|
||||
type AutoApprovers struct {
|
||||
Routes map[string][]string `json:"routes" yaml:"routes"`
|
||||
ExitNode []string `json:"exitNode" yaml:"exitNode"`
|
||||
}
|
||||
|
||||
// UnmarshalJSON allows to parse the Hosts directly into netaddr objects.
|
||||
func (hosts *Hosts) UnmarshalJSON(data []byte) error {
|
||||
newHosts := Hosts{}
|
||||
|
|
75
machine.go
75
machine.go
|
@ -930,6 +930,81 @@ func (h *Headscale) EnableRoutes(machine *Machine, routeStrs ...string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
for _, advertisedRoute := range machine.HostInfo.RoutableIPs {
|
||||
log.Debug().
|
||||
Uint64("machine", machine.ID).
|
||||
Str("advertisedRoute", advertisedRoute.String()).
|
||||
Msg("Client requested to advertise route")
|
||||
|
||||
approved := false
|
||||
routeApprovers := h.aclPolicy.AutoApprovers.Routes[advertisedRoute.String()]
|
||||
|
||||
if advertisedRoute.Bits() == 0 {
|
||||
routeApprovers = h.aclPolicy.AutoApprovers.ExitNode
|
||||
}
|
||||
|
||||
if len(routeApprovers) > 0 {
|
||||
for _, approvedAlias := range routeApprovers {
|
||||
|
||||
approvedIps, err := expandAlias(machines, *h.aclPolicy, approvedAlias, h.cfg.OIDC.StripEmaildomain)
|
||||
|
||||
if err != nil {
|
||||
log.Err(err).
|
||||
Str("alias", approvedAlias).
|
||||
Msg("Failed to expand alias when processing autoApprovers policy")
|
||||
return err
|
||||
}
|
||||
|
||||
for _, machineIp := range machine.IPAddresses {
|
||||
for _, approvedIp := range approvedIps {
|
||||
approved = machineIp.String() == approvedIp
|
||||
|
||||
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 {
|
||||
approvedRoutes = append(approvedRoutes, advertisedRoute)
|
||||
}
|
||||
}
|
||||
|
||||
for _, approvedRoute := range approvedRoutes {
|
||||
if !contains(machine.EnabledRoutes, approvedRoute) {
|
||||
log.Info().
|
||||
Str("route", approvedRoute.String()).
|
||||
Uint64("client", machine.ID).
|
||||
Msg("Enabling autoApproved route for client")
|
||||
machine.EnabledRoutes = append(machine.EnabledRoutes, approvedRoute)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (machine *Machine) RoutesToProto() *v1.Routes {
|
||||
availableRoutes := machine.GetAdvertisedRoutes()
|
||||
|
||||
|
|
|
@ -42,7 +42,14 @@ func (h *Headscale) handlePollCommon(
|
|||
Str("machine", machine.Hostname).
|
||||
Err(err)
|
||||
}
|
||||
|
||||
// update routes with peer information
|
||||
err = h.EnableAutoApprovedRoutes(machine)
|
||||
if err != nil {
|
||||
//TODO
|
||||
}
|
||||
}
|
||||
|
||||
// From Tailscale client:
|
||||
//
|
||||
// ReadOnly is whether the client just wants to fetch the MapResponse,
|
||||
|
|
Loading…
Reference in a new issue