Documentation
¶
Index ¶
- Constants
- Variables
- func Start(ctx context.Context, opt Opt, logger *slog.Logger) error
- type AuthRequest
- func (*AuthRequest) Descriptor() ([]byte, []int)deprecated
- func (x *AuthRequest) GetAuthorizedKey() []byte
- func (x *AuthRequest) GetClientVersion() string
- func (x *AuthRequest) GetLocalAddr() string
- func (x *AuthRequest) GetRemoteAddr() string
- func (*AuthRequest) ProtoMessage()
- func (x *AuthRequest) ProtoReflect() protoreflect.Message
- func (x *AuthRequest) Reset()
- func (x *AuthRequest) String() string
- type CreateSessionRequest
- func (*CreateSessionRequest) Descriptor() ([]byte, []int)deprecated
- func (x *CreateSessionRequest) GetClientAuthorizedKeys() [][]byte
- func (x *CreateSessionRequest) GetGeneration() uint64
- func (x *CreateSessionRequest) GetHostKeyProof() []byte
- func (x *CreateSessionRequest) GetHostPublicKeys() [][]byte
- func (x *CreateSessionRequest) GetHostUser() string
- func (x *CreateSessionRequest) GetSessionSecret() []byte
- func (*CreateSessionRequest) ProtoMessage()
- func (x *CreateSessionRequest) ProtoReflect() protoreflect.Message
- func (x *CreateSessionRequest) Reset()
- func (x *CreateSessionRequest) String() string
- type CreateSessionResponse
- func (*CreateSessionResponse) Descriptor() ([]byte, []int)deprecated
- func (x *CreateSessionResponse) GetNodeAddr() string
- func (x *CreateSessionResponse) GetSessionID() string
- func (x *CreateSessionResponse) GetSessionKeyRedial() bool
- func (x *CreateSessionResponse) GetSshUser() string
- func (*CreateSessionResponse) ProtoMessage()
- func (x *CreateSessionResponse) ProtoReflect() protoreflect.Message
- func (x *CreateSessionResponse) Reset()
- func (x *CreateSessionResponse) String() string
- type ErrSessionNotFound
- type HostCertSigner
- type MemoryProvider
- type NetworkOptions
- type NetworkProvider
- type Opt
- type Registration
- type Route
- type SSHDDialListener
- type SSHRouting
- type Server
- type ServerInfo
- type Session
- type SessionDialListener
- type SessionManager
- func (sm *SessionManager) CreateSession(session *Session) (string, error)
- func (sm *SessionManager) DeleteSession(sessionID string) error
- func (sm *SessionManager) GetEncodeDecoder() routing.EncodeDecoder
- func (sm *SessionManager) GetEntry(sessionID string) (StoreEntry, error)
- func (sm *SessionManager) GetRoutingMode() routing.Mode
- func (sm *SessionManager) GetSession(sessionID string) (*Session, error)
- func (sm *SessionManager) GetStore() SessionStore
- func (sm *SessionManager) LeaseTTL() time.Duration
- func (sm *SessionManager) Observe(fn func(epoch, index uint64, entries map[string]StoreEntry))
- func (sm *SessionManager) RefreshRoute(ctx context.Context, sshUser string, attempted Route) (fresh *Session, moved bool, err error)
- func (sm *SessionManager) Register(ctx context.Context, s *Session) (*Registration, string, error)
- func (sm *SessionManager) Release(ctx context.Context, reg *Registration) error
- func (sm *SessionManager) Renew(ctx context.Context, reg *Registration) error
- func (sm *SessionManager) Reregister(ctx context.Context, reg *Registration) (*Registration, error)
- func (sm *SessionManager) ResolveSSHUser(sshUser string) (sessionID, nodeAddr string, err error)
- func (sm *SessionManager) Shutdown(ctx context.Context, nodeAddr string) (err error)
- type SessionManagerConfig
- type SessionManagerOption
- type SessionStore
- type StoreEntry
- type UnixProvider
- type UserCertChecker
- type UserCertSigner
Constants ¶
const ( DefaultSessionTTL = 30 * time.Minute // Default TTL for session data in Consul DefaultConsulTimeout = 5 * time.Second // Default timeout for Consul operations DefaultWatchTimeout = 10 * time.Minute // Default timeout for Consul watch operations (long-polling) DefaultMaxRetries = 3 // Default number of retries for Consul operations DefaultRetryDelay = 100 * time.Millisecond // Default delay between retries DefaultKeyPrefix = "uptermd" // Default key prefix for Consul storage UnusedNodeAddress = "localhost" // Placeholder address for node registration (not used but required by Consul) )
const DefaultHandshakeTimeout = 60 * time.Second
Variables ¶
var ( // ErrSuperseded refuses a registration that doesn't supersede the one the // store holds for its ID. ErrSuperseded = errors.New("superseded by a newer registration") // ErrLeaseLost is the definite answer that a registration no longer holds // its entry, as opposed to a renewal that merely failed. ErrLeaseLost = errors.New("session lease lost") )
var ErrListnerClosed = errors.New("routing: listener closed")
var File_server_proto protoreflect.FileDescriptor
Functions ¶
Types ¶
type AuthRequest ¶
type AuthRequest struct {
ClientVersion string `protobuf:"bytes,1,opt,name=client_version,json=clientVersion,proto3" json:"client_version,omitempty"`
RemoteAddr string `protobuf:"bytes,2,opt,name=remote_addr,json=remoteAddr,proto3" json:"remote_addr,omitempty"`
AuthorizedKey []byte `protobuf:"bytes,3,opt,name=authorized_key,json=authorizedKey,proto3" json:"authorized_key,omitempty"`
// The relay's own end of the guest's connection, as remote_addr is the
// guest's: the server half of the SSH_CONNECTION a guest's forced command
// sees. Empty from a relay that predates it.
LocalAddr string `protobuf:"bytes,4,opt,name=local_addr,json=localAddr,proto3" json:"local_addr,omitempty"`
// contains filtered or unexported fields
}
func (*AuthRequest) Descriptor
deprecated
func (*AuthRequest) Descriptor() ([]byte, []int)
Deprecated: Use AuthRequest.ProtoReflect.Descriptor instead.
func (*AuthRequest) GetAuthorizedKey ¶
func (x *AuthRequest) GetAuthorizedKey() []byte
func (*AuthRequest) GetClientVersion ¶
func (x *AuthRequest) GetClientVersion() string
func (*AuthRequest) GetLocalAddr ¶ added in v0.37.0
func (x *AuthRequest) GetLocalAddr() string
func (*AuthRequest) GetRemoteAddr ¶
func (x *AuthRequest) GetRemoteAddr() string
func (*AuthRequest) ProtoMessage ¶
func (*AuthRequest) ProtoMessage()
func (*AuthRequest) ProtoReflect ¶ added in v0.5.0
func (x *AuthRequest) ProtoReflect() protoreflect.Message
func (*AuthRequest) Reset ¶
func (x *AuthRequest) Reset()
func (*AuthRequest) String ¶
func (x *AuthRequest) String() string
type CreateSessionRequest ¶
type CreateSessionRequest struct {
HostUser string `protobuf:"bytes,1,opt,name=hostUser,proto3" json:"hostUser,omitempty"`
HostPublicKeys [][]byte `protobuf:"bytes,2,rep,name=hostPublicKeys,proto3" json:"hostPublicKeys,omitempty"`
ClientAuthorizedKeys [][]byte `protobuf:"bytes,3,rep,name=clientAuthorizedKeys,proto3" json:"clientAuthorizedKeys,omitempty"`
// The next three fields claim a session ID derived from the host's key. The
// relay honours them only with a proof; a request without one gets a random
// ID.
//
// The per-run secret the ID derives from, together with the single host key
// in hostPublicKeys.
SessionSecret []byte `protobuf:"bytes,4,opt,name=sessionSecret,proto3" json:"sessionSecret,omitempty"`
// Orders registrations of the same ID; at least 1.
Generation uint64 `protobuf:"varint,5,opt,name=generation,proto3" json:"generation,omitempty"`
// The host key's signature over this connection's SSH session ID, the
// secret and the generation.
HostKeyProof []byte `protobuf:"bytes,6,opt,name=hostKeyProof,proto3" json:"hostKeyProof,omitempty"`
// contains filtered or unexported fields
}
func (*CreateSessionRequest) Descriptor
deprecated
func (*CreateSessionRequest) Descriptor() ([]byte, []int)
Deprecated: Use CreateSessionRequest.ProtoReflect.Descriptor instead.
func (*CreateSessionRequest) GetClientAuthorizedKeys ¶
func (x *CreateSessionRequest) GetClientAuthorizedKeys() [][]byte
func (*CreateSessionRequest) GetGeneration ¶ added in v0.34.0
func (x *CreateSessionRequest) GetGeneration() uint64
func (*CreateSessionRequest) GetHostKeyProof ¶ added in v0.34.0
func (x *CreateSessionRequest) GetHostKeyProof() []byte
func (*CreateSessionRequest) GetHostPublicKeys ¶
func (x *CreateSessionRequest) GetHostPublicKeys() [][]byte
func (*CreateSessionRequest) GetHostUser ¶
func (x *CreateSessionRequest) GetHostUser() string
func (*CreateSessionRequest) GetSessionSecret ¶ added in v0.34.0
func (x *CreateSessionRequest) GetSessionSecret() []byte
func (*CreateSessionRequest) ProtoMessage ¶
func (*CreateSessionRequest) ProtoMessage()
func (*CreateSessionRequest) ProtoReflect ¶ added in v0.5.0
func (x *CreateSessionRequest) ProtoReflect() protoreflect.Message
func (*CreateSessionRequest) Reset ¶
func (x *CreateSessionRequest) Reset()
func (*CreateSessionRequest) String ¶
func (x *CreateSessionRequest) String() string
type CreateSessionResponse ¶
type CreateSessionResponse struct {
SessionID string `protobuf:"bytes,1,opt,name=sessionID,proto3" json:"sessionID,omitempty"`
NodeAddr string `protobuf:"bytes,2,opt,name=nodeAddr,proto3" json:"nodeAddr,omitempty"`
SshUser string `protobuf:"bytes,3,opt,name=ssh_user,json=sshUser,proto3" json:"ssh_user,omitempty"` // SSH username for client connections
// True when this relay admits any host key (no --authorized-keys), so a
// host can authenticate a redial with its session key alone.
SessionKeyRedial bool `protobuf:"varint,4,opt,name=sessionKeyRedial,proto3" json:"sessionKeyRedial,omitempty"`
// contains filtered or unexported fields
}
func (*CreateSessionResponse) Descriptor
deprecated
func (*CreateSessionResponse) Descriptor() ([]byte, []int)
Deprecated: Use CreateSessionResponse.ProtoReflect.Descriptor instead.
func (*CreateSessionResponse) GetNodeAddr ¶
func (x *CreateSessionResponse) GetNodeAddr() string
func (*CreateSessionResponse) GetSessionID ¶
func (x *CreateSessionResponse) GetSessionID() string
func (*CreateSessionResponse) GetSessionKeyRedial ¶ added in v0.34.0
func (x *CreateSessionResponse) GetSessionKeyRedial() bool
func (*CreateSessionResponse) GetSshUser ¶ added in v0.15.0
func (x *CreateSessionResponse) GetSshUser() string
func (*CreateSessionResponse) ProtoMessage ¶
func (*CreateSessionResponse) ProtoMessage()
func (*CreateSessionResponse) ProtoReflect ¶ added in v0.5.0
func (x *CreateSessionResponse) ProtoReflect() protoreflect.Message
func (*CreateSessionResponse) Reset ¶
func (x *CreateSessionResponse) Reset()
func (*CreateSessionResponse) String ¶
func (x *CreateSessionResponse) String() string
type ErrSessionNotFound ¶ added in v0.15.1
type ErrSessionNotFound struct {
SessionID string
}
ErrSessionNotFound represents a non-retryable session not found error
func (*ErrSessionNotFound) Error ¶ added in v0.15.1
func (e *ErrSessionNotFound) Error() string
type HostCertSigner ¶ added in v0.5.0
type HostCertSigner struct {
Hostnames []string
}
type MemoryProvider ¶
type MemoryProvider struct {
SocketPath string
// contains filtered or unexported fields
}
func (*MemoryProvider) Name ¶
func (p *MemoryProvider) Name() string
func (*MemoryProvider) Opts ¶
func (p *MemoryProvider) Opts() string
func (*MemoryProvider) SSHD ¶
func (p *MemoryProvider) SSHD() SSHDDialListener
func (*MemoryProvider) Session ¶
func (p *MemoryProvider) Session() SessionDialListener
func (*MemoryProvider) SetOpts ¶
func (p *MemoryProvider) SetOpts(opts NetworkOptions) error
type NetworkOptions ¶
type NetworkProvider ¶
type NetworkProvider interface {
SetOpts(opts NetworkOptions) error
Session() SessionDialListener
SSHD() SSHDDialListener
Name() string
Opts() string
}
type Opt ¶
type Opt struct {
HandshakeTimeout time.Duration `mapstructure:"handshake-timeout"`
SSHAddr string `mapstructure:"ssh-addr"`
SSHProxyProtocol bool `mapstructure:"ssh-proxy-protocol"`
WSAddr string `mapstructure:"ws-addr"`
NodeAddr string `mapstructure:"node-addr"`
AuthorizedKeysFiles []string `mapstructure:"authorized-keys"`
PrivateKeys []string `mapstructure:"private-key"`
Hostnames []string `mapstructure:"hostname"`
Network string `mapstructure:"network"`
NetworkOpts []string `mapstructure:"network-opt"`
MetricAddr string `mapstructure:"metric-addr"`
Debug bool `mapstructure:"debug"`
Routing routing.Mode `mapstructure:"routing"`
ConsulURL string `mapstructure:"consul-url"`
ConsulSessionTTL string `mapstructure:"consul-session-ttl"`
SentryDSN string `mapstructure:"sentry-dsn"`
}
func (*Opt) ResolvedRouting ¶ added in v0.25.0
ResolvedRouting returns the effective routing mode. It resolves ModeAuto against whether a Consul URL was configured, and supplies the ModeEmbedded default for a zero value.
type Registration ¶ added in v0.34.0
type Registration struct {
Session *Session
// ConfirmedAt is the send time of the lock-session creation this
// registration's lease came from (memory: taken before the write). The
// expiry budget counts from it, and the lease's TTL clock can't have
// started earlier, so the budget can only end early.
ConfirmedAt time.Time
// contains filtered or unexported fields
}
Registration is one stored claim to a session ID. Whatever later renews, releases or rebuilds the entry acts through the handle, so it can only touch its own claim, never a successor's.
func (*Registration) Capable ¶ added in v0.34.0
func (r *Registration) Capable() bool
Capable reports whether the host proved its key, and so can reconnect. A legacy registration keeps today's behaviour.
func (*Registration) Generation ¶ added in v0.34.0
func (r *Registration) Generation() uint64
func (*Registration) ID ¶ added in v0.34.0
func (r *Registration) ID() string
func (*Registration) Same ¶ added in v0.34.0
func (r *Registration) Same(o *Registration) bool
Same reports whether r and o are the same registration. A rebuild stores the same registration again under a new lease, and its handle stands in for the one it replaced, so this compares identity rather than handles.
type Route ¶ added in v0.34.0
Route is where a guest's upstream was sent: the node, and the registration that was current when it was resolved.
type SSHDDialListener ¶
type SSHRouting ¶
type SSHRouting struct {
HandshakeTimeout time.Duration
HostSigners []ssh.Signer
Auth *proxyAuth
Logger *slog.Logger
MetricsProvider provider.Provider
// contains filtered or unexported fields
}
func (*SSHRouting) Shutdown ¶
func (p *SSHRouting) Shutdown() error
type Server ¶
type Server struct {
HandshakeTimeout time.Duration
NodeAddr string
AuthorizedKeysFiles []string
HostSigners []ssh.Signer
Signers []ssh.Signer
NetworkProvider NetworkProvider
MetricsProvider provider.Provider
SessionManager *SessionManager
Logger *slog.Logger
// contains filtered or unexported fields
}
func (*Server) ServeWithContext ¶
func (*Server) Shutdown ¶
Shutdown cancels serving and waits for it to finish. It deliberately does not close sshln or wsln: each is owned by the component serving it, which closes it from its own run.Group interrupt as the context unwinds. Closing them here as well made every listener close twice with no ordering between the two, and the loser of that race reported "use of closed network connection" from whichever side it landed on.
type ServerInfo ¶
type ServerInfo struct {
NodeAddr string
}
type Session ¶ added in v0.15.0
type Session struct {
ID string
NodeAddr string
// Generation orders registrations of the same ID. 0 is a legacy
// registration: a random ID with no proof behind it.
Generation uint64
HostUser string
HostPublicKeys []ssh.PublicKey
ClientAuthorizedKeys []ssh.PublicKey
}
Session represents the complete session information
func NewSession ¶ added in v0.15.0
func NewSession(sessionID, nodeAddr, hostUser string, hostPublicKeys, clientAuthorizedKeys [][]byte) *Session
NewSession creates Session from session parameters
func (*Session) IsClientKeyAllowed ¶ added in v0.15.0
IsClientKeyAllowed checks if a client key is authorized for this session
func (*Session) MarshalJSON ¶ added in v0.15.0
MarshalJSON implements custom JSON marshaling for Session
func (*Session) UnmarshalJSON ¶ added in v0.15.0
UnmarshalJSON implements custom JSON unmarshaling for Session
type SessionDialListener ¶
type SessionDialListener interface {
Listen(sesisonID string) (net.Listener, error)
Dial(sessionID string) (net.Conn, error)
DialContext(ctx context.Context, sessionID string) (net.Conn, error)
}
DialContext is part of these interfaces rather than an optional capability discovered by type assertion: the SSH front door bounds upstream establishment with it, so a provider that offered only Dial would compile, serve every Dial-based path, and then fail every SSH connection after downstream authentication had already succeeded.
type SessionManager ¶ added in v0.15.0
type SessionManager struct {
// contains filtered or unexported fields
}
SessionManager provides a high-level interface for session management, combining session storage with connection ID encoding based on routing mode
func NewSessionManager ¶ added in v0.15.0
func NewSessionManager(mode routing.Mode, opts ...SessionManagerOption) (*SessionManager, error)
NewSessionManager creates a new SessionManager with the specified routing mode and options
Examples:
// Embedded mode (simple, with default logger)
sm, err := NewSessionManager(routing.ModeEmbedded)
// Embedded mode with custom logger
sm, err := NewSessionManager(routing.ModeEmbedded, WithSessionManagerLogger(logger))
// Consul mode with minimal configuration
sm, err := NewSessionManager(routing.ModeConsul, WithSessionManagerConsulURL("http://localhost:8500"))
// Consul mode with full configuration
sm, err := NewSessionManager(routing.ModeConsul,
WithSessionManagerLogger(logger),
WithSessionManagerConsulURL("http://consul.example.com:8500"),
WithSessionManagerConsulTTL(1*time.Hour))
func (*SessionManager) CreateSession ¶ added in v0.15.0
func (sm *SessionManager) CreateSession(session *Session) (string, error)
CreateSession stores the session and returns the encoded SSH user identifier
func (*SessionManager) DeleteSession ¶ added in v0.15.0
func (sm *SessionManager) DeleteSession(sessionID string) error
DeleteSession removes a session by ID
func (*SessionManager) GetEncodeDecoder ¶ added in v0.15.0
func (sm *SessionManager) GetEncodeDecoder() routing.EncodeDecoder
GetEncodeDecoder returns the EncodeDecoder used by this session manager
func (*SessionManager) GetEntry ¶ added in v0.36.0
func (sm *SessionManager) GetEntry(sessionID string) (StoreEntry, error)
GetEntry is GetSession, with the lock session that holds the entry.
func (*SessionManager) GetRoutingMode ¶ added in v0.15.0
func (sm *SessionManager) GetRoutingMode() routing.Mode
GetRoutingMode returns the routing mode of this session manager
func (*SessionManager) GetSession ¶ added in v0.15.0
func (sm *SessionManager) GetSession(sessionID string) (*Session, error)
GetSession retrieves a session by ID
func (*SessionManager) GetStore ¶ added in v0.15.0
func (sm *SessionManager) GetStore() SessionStore
GetStore returns the underlying SessionStore for compatibility
func (*SessionManager) LeaseTTL ¶ added in v0.34.0
func (sm *SessionManager) LeaseTTL() time.Duration
LeaseTTL is how long an unrenewed registration lasts; 0 if it doesn't expire.
func (*SessionManager) Observe ¶ added in v0.34.0
func (sm *SessionManager) Observe(fn func(epoch, index uint64, entries map[string]StoreEntry))
Observe has fn called with each view of every entry the store's watch delivers: entries maps each session ID to its stored session and the lock session holding it, as of index in epoch. Indexes order only within an epoch, which advances when the watch's index goes backwards; a Registration records both. fn runs on the watch's goroutine and holds up the next delivery, so it must not make store calls; entries is shared with the other observers, and is theirs only to read. A store no other writer shares never calls fn.
func (*SessionManager) RefreshRoute ¶ added in v0.34.0
func (sm *SessionManager) RefreshRoute(ctx context.Context, sshUser string, attempted Route) (fresh *Session, moved bool, err error)
RefreshRoute reads sshUser's session from the store itself, skipping any cache, and reports whether it has moved from attempted to another node or another registration. It compares with the route an attempt was actually sent on, never with the cache: the watch may have updated that while the attempt was failing, and would then hide the move.
func (*SessionManager) Register ¶ added in v0.34.0
func (sm *SessionManager) Register(ctx context.Context, s *Session) (*Registration, string, error)
Register stores s as a fresh registration, which needs its ID absent or a higher generation than the stored one, and returns its handle and the encoded SSH user identifier. A Register that fails may outlast ctx by up to DefaultConsulTimeout, while the store destroys a lease it created.
func (*SessionManager) Release ¶ added in v0.34.0
func (sm *SessionManager) Release(ctx context.Context, reg *Registration) error
Release removes reg's entry if reg still holds it.
func (*SessionManager) Renew ¶ added in v0.34.0
func (sm *SessionManager) Renew(ctx context.Context, reg *Registration) error
Renew keeps reg's entry alive; see SessionStore.Renew for its errors.
func (*SessionManager) Reregister ¶ added in v0.34.0
func (sm *SessionManager) Reregister(ctx context.Context, reg *Registration) (*Registration, error)
Reregister rebuilds reg after a known loss: the same registration, stored again with a lease of its own. Unlike Register it may replace an entry of reg's own identity; only reg's lease keeper calls it. The handle it returns is Same as reg. Release reg afterwards only if its lease is non-empty and differs from the new handle's: a store without leases keeps one entry for both handles, and releasing reg there would delete the entry just rebuilt.
func (*SessionManager) ResolveSSHUser ¶ added in v0.15.0
func (sm *SessionManager) ResolveSSHUser(sshUser string) (sessionID, nodeAddr string, err error)
ResolveSSHUser resolves an SSH username by decoding it and conditionally validating session existence In embedded mode: only decodes (session may be on another node) In consul mode: decodes and validates (shared store across all nodes)
func (*SessionManager) Shutdown ¶ added in v0.15.0
func (sm *SessionManager) Shutdown(ctx context.Context, nodeAddr string) (err error)
Shutdown deletes this node's sessions and finalizes the store once per call. Consul cleanup finishes before Close. A legacy call cannot be interrupted; cancellation instead lets this caller reach Close while that worker unwinds.
type SessionManagerConfig ¶ added in v0.15.0
type SessionManagerConfig struct {
Mode routing.Mode
Logger *slog.Logger
ConsulURL *url.URL
ConsulTTL time.Duration
}
SessionManagerConfig holds configuration for creating a SessionManager
type SessionManagerOption ¶ added in v0.15.0
type SessionManagerOption func(*SessionManagerConfig)
SessionManagerOption is a functional option for configuring SessionManager
func WithSessionManagerConsulTTL ¶ added in v0.15.0
func WithSessionManagerConsulTTL(ttl time.Duration) SessionManagerOption
WithSessionManagerConsulTTL sets the session TTL for consul mode
func WithSessionManagerConsulURL ¶ added in v0.15.1
func WithSessionManagerConsulURL(consulURL *url.URL) SessionManagerOption
WithSessionManagerConsulURL sets the Consul URL for consul mode
func WithSessionManagerLogger ¶ added in v0.15.0
func WithSessionManagerLogger(logger *slog.Logger) SessionManagerOption
WithSessionManagerLogger sets the logger for the session manager
type SessionStore ¶ added in v0.15.0
type SessionStore interface {
// Register stores s when its ID is absent or s has a higher generation
// than the stored entry. Otherwise it returns an error wrapping
// ErrSuperseded and writes nothing. A Register that fails may outlast ctx
// by up to DefaultConsulTimeout, while it destroys a lease it created.
Register(ctx context.Context, s *Session) (*Registration, error)
// Reregister is the owner's rebuild of reg after a known loss: it stores
// reg's session again under a new lease, as Register does, and may also
// replace an entry of reg's own identity, which Register refuses. A store
// with leases also replaces a value reg's own lease holds, whatever was
// written into it. It orders, retries and cleans up as Register does.
Reregister(ctx context.Context, reg *Registration) (*Registration, error)
// Release removes reg's entry if reg still holds it.
Release(ctx context.Context, reg *Registration) error
// Renew keeps reg's entry alive. An error wrapping ErrLeaseLost means reg
// no longer holds it; any other error leaves that unknown.
Renew(ctx context.Context, reg *Registration) error
// LeaseTTL is how long an unrenewed entry lasts; 0 if it doesn't expire.
LeaseTTL() time.Duration
// Get complete session data
Get(sessionID string) (*Session, error)
// Entry is Get with the lock session that holds the entry, "" in a store
// without leases.
Entry(sessionID string) (StoreEntry, error)
// GetFresh reads sessionID from the store itself, skipping any cache, and
// updates the cache with what it finds, the entry or its absence, as Get's
// read-through does. It gives up once ctx is done.
GetFresh(ctx context.Context, sessionID string) (*Session, error)
// Delete session data, only for an entry this instance holds
Delete(sessionID string) error
// BatchDelete multiple sessions efficiently, likewise
BatchDelete(sessionIDs []string) error
// List all sessions (for cleanup and management)
List() ([]*Session, error)
// Observe has fn called with each view of every entry the store's watch
// delivers; see SessionManager.Observe. A store no other writer shares
// has nothing to watch, and never calls fn.
Observe(fn func(epoch, index uint64, entries map[string]StoreEntry))
// Close cleans up resources and stops background processes
Close() error
}
SessionStore defines the interface for session storage.
Registrations are ordered: a stored entry is replaced only by a higher generation, or by its owner rebuilding it, and a handle's Release and Renew act only on its own entry.
type StoreEntry ¶ added in v0.36.0
StoreEntry is one session as the store's watch delivered it: the value stored for its ID, and the lock session that holds its key, "" if none does.
type UnixProvider ¶
type UnixProvider struct {
// contains filtered or unexported fields
}
func (*UnixProvider) Name ¶
func (p *UnixProvider) Name() string
func (*UnixProvider) Opts ¶
func (p *UnixProvider) Opts() string
func (*UnixProvider) SSHD ¶
func (p *UnixProvider) SSHD() SSHDDialListener
func (*UnixProvider) Session ¶
func (p *UnixProvider) Session() SessionDialListener
func (*UnixProvider) SetOpts ¶
func (p *UnixProvider) SetOpts(opts NetworkOptions) error
type UserCertChecker ¶ added in v0.5.0
type UserCertChecker struct {
// IsUserAuthority reports whether a key may vouch for a certificate's
// AuthRequest. Nil trusts nothing, so a call site that names no authority
// gets no certificate identities: the safe direction to fail in, and the
// one a future call site that forgets this field lands in.
//
// The relay names its own signing keys, because it is the only party that
// mints upterm certificates. A host names the single relay key its host
// key callback accepted.
//
// A relay offers one certificate per signing key, and x/crypto counts a
// rejected public-key query against MaxAuthTries -- 6 by default, which
// charm.land/ssh does not change. So a host pinning one key survives five
// rejected offers and is disconnected on the sixth: the pinned key must be
// among the first six a relay offers. One key, or two through a rotation,
// is always fine. Raising the guest door's MaxAuthTries through a
// ServerConfigCallback is the escape hatch if that ever binds.
IsUserAuthority func(auth ssh.PublicKey) bool
UserKeyFallback func(user string, key ssh.PublicKey) (ssh.PublicKey, error)
}
func (*UserCertChecker) Authenticate ¶ added in v0.5.0
func (c *UserCertChecker) Authenticate(user string, key ssh.PublicKey) (*AuthRequest, ssh.PublicKey, error)
Authenticate tries to pass auth request and public key from a cert. If the public key is not a cert, it calls the UserKeyFallback func. Otherwise it returns an error.
type UserCertSigner ¶ added in v0.5.0
type UserCertSigner struct {
SessionID string
User string
AuthRequest *AuthRequest
}