mirror of
https://github.com/tailscale/tailscale.git
synced 2025-02-28 19:27:41 +00:00

In this PR, we move the code that checks the AlwaysOn policy from ipnserver.actor to ipnauth. It is intended to be used by ipnauth.Actor implementations, and we temporarily make it exported while these implementations reside in ipnserver and in corp. We'll unexport it later. We also update [ipnauth.Actor.CheckProfileAccess] to accept an auditLogger, which is called to write details about the action to the audit log when required by the policy, and update LocalBackend.EditPrefsAs to use an auditLogger that writes to the regular backend log. Updates tailscale/corp#26146 Signed-off-by: Nick Khyl <nickk@tailscale.com>
47 lines
1.8 KiB
Go
47 lines
1.8 KiB
Go
// Copyright (c) Tailscale Inc & AUTHORS
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package ipnauth
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"tailscale.com/ipn"
|
|
"tailscale.com/util/syspolicy"
|
|
)
|
|
|
|
// CheckDisconnectPolicy checks if the policy allows the specified actor to disconnect
|
|
// Tailscale with the given optional reason. It returns nil if the operation is allowed,
|
|
// or an error if it is not. If auditLogger is non-nil, it is called to log the action
|
|
// when required by the policy.
|
|
//
|
|
// Note: this function only checks the policy and does not check whether the actor has
|
|
// the necessary access rights to the device or profile. It is intended to be used by
|
|
// [Actor] implementations on platforms where [syspolicy] is supported.
|
|
//
|
|
// TODO(nickkhyl): unexport it when we move [ipn.Actor] implementations from [ipnserver]
|
|
// and corp to this package.
|
|
func CheckDisconnectPolicy(actor Actor, profile ipn.LoginProfileView, reason string, auditLogger AuditLogFunc) error {
|
|
if alwaysOn, _ := syspolicy.GetBoolean(syspolicy.AlwaysOn, false); !alwaysOn {
|
|
return nil
|
|
}
|
|
if allowWithReason, _ := syspolicy.GetBoolean(syspolicy.AlwaysOnOverrideWithReason, false); !allowWithReason {
|
|
return errors.New("disconnect not allowed: always-on mode is enabled")
|
|
}
|
|
if reason == "" {
|
|
return errors.New("disconnect not allowed: reason required")
|
|
}
|
|
if auditLogger != nil {
|
|
var details string
|
|
if username, _ := actor.Username(); username != "" { // best-effort; we don't have it on all platforms
|
|
details = fmt.Sprintf("%q is being disconnected by %q: %v", profile.Name(), username, reason)
|
|
} else {
|
|
details = fmt.Sprintf("%q is being disconnected: %v", profile.Name(), reason)
|
|
}
|
|
// TODO(nickkhyl,barnstar): use a const for DISCONNECT_NODE.
|
|
auditLogger("DISCONNECT_NODE", details)
|
|
}
|
|
return nil
|
|
}
|