ipn/{ipn,ipnlocal}: add per-user policy snapshots to IPN bus (#20135)

This adds the NotifyInitialPolicy watch option and the Policy field in
Notify so that clients can receive the effective policy snapshot via IPN
bus.

This extends policyclient.Client so ipnlocal can get and watch policy
snapshots, which is used by sysPolicyChanged to notify watchers.

User-scoped policy store registration, management, and cleanup will be
added in a follow-up

Updates tailscale/corp#42259

Signed-off-by: kari <kari@tailscale.com>
This commit is contained in:
kari-ts
2026-06-30 12:44:29 -07:00
committed by GitHub
parent fad8b9b8a9
commit 07cefc083d
11 changed files with 284 additions and 15 deletions
+20 -4
View File
@@ -129,8 +129,12 @@ func getDuration(name pkey.Key, defaultValue time.Duration) (time.Duration, erro
// registerChangeCallback adds a function that will be called whenever the effective policy
// for the default scope changes. The returned function can be used to unregister the callback.
func registerChangeCallback(cb rsop.PolicyChangeCallback) (unregister func(), err error) {
effective, err := rsop.PolicyFor(setting.DefaultScope())
func registerChangeCallback(uid string, cb rsop.PolicyChangeCallback) (unregister func(), err error) {
scope := setting.DefaultScope()
if uid != "" {
scope = setting.UserScopeOf(uid)
}
effective, err := rsop.PolicyFor(scope)
if err != nil {
return nil, err
}
@@ -259,6 +263,18 @@ func (globalSyspolicy) HasAnyOf(keys ...pkey.Key) (bool, error) {
return hasAnyOf(keys...)
}
func (globalSyspolicy) RegisterChangeCallback(cb func(policyclient.PolicyChange)) (unregister func(), err error) {
return registerChangeCallback(cb)
func (globalSyspolicy) RegisterChangeCallback(uid string, cb func(policyclient.PolicyChange)) (unregister func(), err error) {
return registerChangeCallback(uid, cb)
}
func (globalSyspolicy) GetPolicySnapshot(uid string) (*policyclient.PolicySnapshot, error) {
scope := setting.DefaultScope()
if uid != "" {
scope = setting.UserScopeOf(uid)
}
p, err := rsop.PolicyFor(scope)
if err != nil {
return nil, err
}
return p.Get(), nil
}