package policy import ( "net/netip" "time" "github.com/juanfont/headscale/hscontrol/policy/matcher" policyv2 "github.com/juanfont/headscale/hscontrol/policy/v2" "github.com/juanfont/headscale/hscontrol/types" "tailscale.com/tailcfg" "tailscale.com/types/views" ) type PolicyManager interface { // Filter returns the current filter rules for the entire tailnet and the associated matchers. Filter() ([]tailcfg.FilterRule, []matcher.Match) // FilterForNode returns filter rules for a specific node, handling autogroup:self FilterForNode(node types.NodeView) ([]tailcfg.FilterRule, error) // MatchersForNode returns matchers for peer relationship determination (unreduced) MatchersForNode(node types.NodeView) ([]matcher.Match, error) // BuildPeerMap constructs peer relationship maps for the given nodes BuildPeerMap(nodes views.Slice[types.NodeView]) map[types.NodeID][]types.NodeView SSHPolicy(baseURL string, node types.NodeView) (*tailcfg.SSHPolicy, error) // SSHCheckParams resolves the SSH check period for a (src, dst) pair // from the current policy, avoiding trust of client-provided URL params. SSHCheckParams(srcNodeID, dstNodeID types.NodeID) (time.Duration, bool) SetPolicy(pol []byte) (bool, error) SetUsers(users []types.User) (bool, error) SetNodes(nodes views.Slice[types.NodeView]) (bool, error) // NodeCanHaveTag reports whether the given node can have the given tag. NodeCanHaveTag(node types.NodeView, tag string) bool // TagExists reports whether the given tag is defined in the policy. TagExists(tag string) bool // NodeCanApproveRoute reports whether the given node can approve the given route. NodeCanApproveRoute(node types.NodeView, route netip.Prefix) bool Version() int DebugString() string } // NewPolicyManager returns a new policy manager. func NewPolicyManager(pol []byte, users []types.User, nodes views.Slice[types.NodeView]) (PolicyManager, error) { var ( polMan PolicyManager err error ) polMan, err = policyv2.NewPolicyManager(pol, users, nodes) if err != nil { return nil, err } return polMan, err } // PolicyManagersForTest returns all available PostureManagers to be used // in tests to validate them in tests that try to determine that they // behave the same. func PolicyManagersForTest(pol []byte, users []types.User, nodes views.Slice[types.NodeView]) ([]PolicyManager, error) { var polMans []PolicyManager for _, pmf := range PolicyManagerFuncsForTest(pol) { pm, err := pmf(users, nodes) if err != nil { return nil, err } polMans = append(polMans, pm) } return polMans, nil } func PolicyManagerFuncsForTest(pol []byte) []func([]types.User, views.Slice[types.NodeView]) (PolicyManager, error) { polmanFuncs := make([]func([]types.User, views.Slice[types.NodeView]) (PolicyManager, error), 0, 1) polmanFuncs = append(polmanFuncs, func(u []types.User, n views.Slice[types.NodeView]) (PolicyManager, error) { return policyv2.NewPolicyManager(pol, u, n) }) return polmanFuncs }