Files
tailscale/client/local/syspolicy.go
kari-ts 5f47f9ce49 client/local, cmd/tailscale/cli: reload syspolicy for current user (#21712)
This makes the syspolicy cli use the caller's user scope instead of the
generic user scope. In tailscale/tailscale#21701, we made the LocalAPI
policy endpoint resolve unscoped policy requests to the connected user's
policy. However, the cli serialized setting.DefaultScope() as
/policy/User, which selected the general user policy and not the User(SID) policy used by
IPN watchers.

This was tested by changing the AlwaysOn policy and verifying that the
User(SID) policy was reloaded and the gui's IPN policy change callbacks
fired.

Updates tailscale/corp#41463

Signed-off-by: kari <kari@tailscale.com>
2026-10-14 09:15:08 -07:00

64 lines
2.0 KiB
Go

// Copyright (c) Tailscale Inc & contributors
// SPDX-License-Identifier: BSD-3-Clause
//go:build !ts_omit_syspolicy
package local
import (
"context"
"net/http"
"tailscale.com/util/syspolicy/setting"
)
// GetEffectivePolicy returns the effective policy for the specified scope.
//
// API maturity: this method is not considered a stable API and is
// subject to change between releases.
func (lc *Client) GetEffectivePolicy(ctx context.Context, scope setting.PolicyScope) (*setting.Snapshot, error) {
scopeID, err := scope.MarshalText()
if err != nil {
return nil, err
}
body, err := lc.get200(ctx, "/localapi/v0/policy/"+string(scopeID))
if err != nil {
return nil, err
}
return decodeJSON[*setting.Snapshot](body)
}
// GetEffectivePolicyForCurrentUser returns the effective policy for the
// user associated with the LocalAPI request.
func (lc *Client) GetEffectivePolicyForCurrentUser(ctx context.Context) (*setting.Snapshot, error) {
body, err := lc.get200(ctx, "/localapi/v0/policy/")
if err != nil {
return nil, err
}
return decodeJSON[*setting.Snapshot](body)
}
// ReloadEffectivePolicy reloads the effective policy for the specified scope
// by reading and merging policy settings from all applicable policy sources.
func (lc *Client) ReloadEffectivePolicy(ctx context.Context, scope setting.PolicyScope) (*setting.Snapshot, error) {
scopeID, err := scope.MarshalText()
if err != nil {
return nil, err
}
body, err := lc.send(ctx, "POST", "/localapi/v0/policy/"+string(scopeID), 200, http.NoBody)
if err != nil {
return nil, err
}
return decodeJSON[*setting.Snapshot](body)
}
// ReloadEffectivePolicyForCurrentUser reloads the effective policy for the
// user associated with the LocalAPI request.
func (lc *Client) ReloadEffectivePolicyForCurrentUser(ctx context.Context) (*setting.Snapshot, error) {
body, err := lc.send(ctx, "POST", "/localapi/v0/policy/", 200, http.NoBody)
if err != nil {
return nil, err
}
return decodeJSON[*setting.Snapshot](body)
}