ipnauth

package
v0.0.0-...-1b709f2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 9, 2026 License: BSD-3-Clause Imports: 25 Imported by: 0

Documentation

Overview

Package ipnauth controls access to the LocalAPI.

Index

Constants

View Source
const (
	// Disconnect is required to disconnect (or switch from) a Tailscale profile.
	Disconnect = ProfileAccess(1 << iota)
)

Define access rights that might be granted or denied on a per-profile basis.

Variables

View Source
var ErrNotImplemented = errors.New("not implemented for GOOS=" + runtime.GOOS)

ErrNotImplemented is returned by ConnIdentity.WindowsToken when it is not implemented for the current GOOS.

Functions

func CheckDisconnectPolicy

func CheckDisconnectPolicy(actor Actor, profile ipn.LoginProfileView, reason string, auditFn AuditLogFunc) error

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 IsTailscaled

func IsTailscaled(a Actor) bool

IsTailscaled reports whether the given Actor represents Tailscaled itself, such as Self or a TODO placeholder actor.

func LookupUserFromID

func LookupUserFromID(logf logger.Logf, uid string) (*user.User, error)

LookupUserFromID is a wrapper around os/user.LookupId that works around some issues on Windows. On non-Windows platforms it's identical to user.LookupId.

Types

type Actor

type Actor interface {
	// UserID returns an OS-specific UID of the user represented by the receiver,
	// or "" if the actor does not represent a specific user on a multi-user system.
	// As of 2024-08-27, it is only used on Windows.
	UserID() ipn.WindowsUserID
	// Username returns the user name associated with the receiver,
	// or "" if the actor does not represent a specific user.
	Username() (string, error)
	// ClientID returns a non-zero ClientID and true if the actor represents
	// a connected LocalAPI client. Otherwise, it returns a zero value and false.
	ClientID() (_ ClientID, ok bool)

	// Context returns the context associated with the actor.
	// It carries additional information about the actor
	// and is canceled when the actor is done.
	Context() context.Context

	// CheckProfileAccess checks whether the actor has the necessary access rights
	// to perform a given action on the specified Tailscale profile.
	// It returns an error if access is denied.
	//
	// If the auditLogger is non-nil, it is used to write details about the action
	// to the audit log when required by the policy.
	CheckProfileAccess(profile ipn.LoginProfileView, requestedAccess ProfileAccess, auditLogFn AuditLogFunc) error

	// IsLocalSystem reports whether the actor is the Windows' Local System account.
	//
	// Deprecated: this method exists for compatibility with the current (as of 2024-08-27)
	// permission model and will be removed as we progress on tailscale/corp#18342.
	IsLocalSystem() bool

	// IsLocalAdmin reports whether the actor has administrative access to the
	// local machine, for whatever that means with respect to the current OS.
	//
	// The operatorUID is only used on Unix-like platforms and specifies the ID
	// of a local user (in the os/user.User.Uid string form) who is allowed to
	// operate tailscaled without being root or using sudo.
	//
	// Deprecated: this method exists for compatibility with the current (as of 2024-08-27)
	// permission model and will be removed as we progress on tailscale/corp#18342.
	IsLocalAdmin(operatorUID string) bool
}

Actor is any actor using the [ipnlocal.LocalBackend].

It typically represents a specific OS user, indicating that an operation is performed on behalf of this user, should be evaluated against their access rights, and performed in their security context when applicable.

var Self Actor = unrestricted{}

Self is a caller identity that represents the tailscaled itself and therefore has unlimited access.

var TODO Actor = unrestricted{}

TODO is a caller identity used when the operation is performed on behalf of a user, rather than by tailscaled itself, but the surrounding function is not yet extended to accept an Actor parameter. It grants the same unrestricted access as Self.

func WithPolicyChecks

func WithPolicyChecks(actor Actor) Actor

WithPolicyChecks returns an Actor that wraps the given actor and performs additional policy checks on top of the access checks implemented by the wrapped actor.

func WithRequestReason

func WithRequestReason(actor Actor, requestReason string) Actor

WithRequestReason returns an Actor that wraps the given actor and carries the specified request reason in its context.

func WithoutClose

func WithoutClose(actor Actor) Actor

WithoutClose returns an Actor that does not expose the ActorCloser interface. In other words, _, ok := WithoutClose(actor).(ActorCloser) will always be false, even if the original actor implements ActorCloser.

type ActorCloser

type ActorCloser interface {
	// Close releases resources associated with the receiver.
	Close() error
}

ActorCloser is an optional interface that might be implemented by an Actor that must be closed when done to release the resources.

type AuditLogFunc

type AuditLogFunc func(action tailcfg.ClientAuditAction, details string) error

AuditLogFunc is any function that can be used to log audit actions performed by an Actor.

type ClientID

type ClientID struct {
	// contains filtered or unexported fields
}

ClientID is an opaque, comparable value used to identify a connected LocalAPI client, such as a connected Tailscale GUI or CLI. It does not necessarily correspond to the same net.Conn or any physical session.

Its zero value is valid, but does not represent a specific connected client.

var NoClientID ClientID

NoClientID is the zero value of ClientID.

func ClientIDFrom

func ClientIDFrom[T comparable](v T) ClientID

ClientIDFrom returns a new ClientID derived from the specified value. ClientIDs derived from equal values are equal.

func (ClientID) MarshalJSON

func (id ClientID) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler. It is primarily used for testing.

func (ClientID) String

func (id ClientID) String() string

String implements fmt.Stringer.

func (*ClientID) UnmarshalJSON

func (id *ClientID) UnmarshalJSON(b []byte) error

UnmarshalJSON implements json.Unmarshaler. It is primarily used for testing.

type ConnIdentity

type ConnIdentity struct {
	// contains filtered or unexported fields
}

ConnIdentity represents the owner of a localhost TCP or unix socket connection connecting to the LocalAPI.

func GetConnIdentity

func GetConnIdentity(_ logger.Logf, c net.Conn) (ci *ConnIdentity, err error)

GetConnIdentity extracts the identity information from the connection based on the user who owns the other end of the connection. and couldn't. The returned connIdentity has NotWindows set to true.

func (*ConnIdentity) Creds

func (ci *ConnIdentity) Creds() PeerCreds

func (*ConnIdentity) IsReadonlyConn

func (ci *ConnIdentity) IsReadonlyConn(operatorUID string, logf logger.Logf) bool

IsReadonlyConn reports whether the connection should be considered read-only, meaning it's not allowed to change the state of the node.

Read-only also means it's not allowed to access sensitive information, which admittedly doesn't follow from the name. Consider this "IsUnprivileged". Also, Windows doesn't use this. For Windows it always returns false.

TODO(bradfitz): rename it? Also make Windows use this.

func (*ConnIdentity) IsUnixSock

func (ci *ConnIdentity) IsUnixSock() bool

func (*ConnIdentity) Pid

func (ci *ConnIdentity) Pid() int

func (*ConnIdentity) WindowsToken

func (ci *ConnIdentity) WindowsToken() (WindowsToken, error)

WindowsToken is unsupported when GOOS != windows and always returns ErrNotImplemented.

func (*ConnIdentity) WindowsUserID

func (ci *ConnIdentity) WindowsUserID() ipn.WindowsUserID

WindowsUserID returns the local machine's userid of the connection if it's on Windows. Otherwise it returns the empty string.

It's suitable for passing to LookupUserFromID (os/user.LookupId) on any operating system.

type PeerCreds

type PeerCreds interface {
	UserID() (uid string, ok bool)
	PID() (pid int, ok bool)
}

PeerCreds is the interface for a github.com/tailscale/peercred.Creds, if linked into the binary.

(It's not used on some platforms, or if ts_omit_unixsocketidentity is set.)

type ProfileAccess

type ProfileAccess uint

ProfileAccess is a bitmask representing the requested, required, or granted access rights to an ipn.LoginProfile.

It is not to be written to disk or transmitted over the network in its integer form, but rather serialized to a string or other format if ever needed.

type TestActor

type TestActor struct {
	UID         ipn.WindowsUserID // OS-specific UID of the user, if the actor represents a local Windows user
	Name        string            // username associated with the actor, or ""
	NameErr     error             // error to be returned by [TestActor.Username]
	CID         ClientID          // non-zero if the actor represents a connected LocalAPI client
	Ctx         context.Context   // context associated with the actor
	LocalSystem bool              // whether the actor represents the special Local System account on Windows
	LocalAdmin  bool              // whether the actor has local admin access
}

TestActor is an Actor used exclusively for testing purposes.

func (*TestActor) CheckProfileAccess

func (a *TestActor) CheckProfileAccess(profile ipn.LoginProfileView, _ ProfileAccess, _ AuditLogFunc) error

CheckProfileAccess implements Actor.

func (*TestActor) ClientID

func (a *TestActor) ClientID() (_ ClientID, ok bool)

ClientID implements Actor.

func (*TestActor) Context

func (a *TestActor) Context() context.Context

Context implements Actor.

func (*TestActor) IsLocalAdmin

func (a *TestActor) IsLocalAdmin(operatorUID string) bool

IsLocalAdmin implements Actor.

func (*TestActor) IsLocalSystem

func (a *TestActor) IsLocalSystem() bool

IsLocalSystem implements Actor.

func (*TestActor) UserID

func (a *TestActor) UserID() ipn.WindowsUserID

UserID implements Actor.

func (*TestActor) Username

func (a *TestActor) Username() (string, error)

Username implements Actor.

type WindowsToken

type WindowsToken interface {
	io.Closer
	// EqualUIDs reports whether other refers to the same user ID as the receiver.
	EqualUIDs(other WindowsToken) bool
	// IsAdministrator reports whether the receiver is a member of the built-in
	// Administrators group, or else an error. Use IsElevated to determine whether
	// the receiver is actually utilizing administrative rights.
	IsAdministrator() (bool, error)
	// IsUID reports whether the receiver's user ID matches uid.
	IsUID(uid ipn.WindowsUserID) bool
	// UID returns the ipn.WindowsUserID associated with the receiver, or else
	// an error.
	UID() (ipn.WindowsUserID, error)
	// IsElevated reports whether the receiver is currently executing as an
	// elevated administrative user.
	IsElevated() bool
	// IsLocalSystem reports whether the receiver is the built-in SYSTEM user.
	IsLocalSystem() bool
	// UserDir returns the special directory identified by folderID as associated
	// with the receiver. folderID must be one of the KNOWNFOLDERID values from
	// the x/sys/windows package, serialized as a stringified GUID.
	UserDir(folderID string) (string, error)
	// Username returns the user name associated with the receiver.
	Username() (string, error)
}

WindowsToken represents the current security context of a Windows user.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL