state: replace zcache with bounded LRU for auth cache
Replace zcache with golang-lru/v2/expirable for both the state auth cache and the OIDC state cache. Add tuning.register_cache_max_entries (default 1024) to cap the number of pending registration entries. Introduce types.RegistrationData to replace caching a full *Node; only the fields the registration callback path reads are retained. Remove the dead HSDatabase.regCache field. Drop zgo.at/zcache/v2 from go.mod.
This commit is contained in:
parent
3587225a88
commit
0d4f2293ff
21 changed files with 343 additions and 258 deletions
|
|
@ -221,40 +221,65 @@ func (r AuthID) Validate() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// AuthRequest represent a pending authentication request from a user or a node.
|
||||
// If it is a registration request, the node field will be populate with the node that is trying to register.
|
||||
// When the authentication process is finished, the node that has been authenticated will be sent through the Finished channel.
|
||||
// The closed field is used to ensure that the Finished channel is only closed once, and that no more nodes are sent through it after it has been closed.
|
||||
// AuthRequest represents a pending authentication request from a user or a
|
||||
// node. It carries the minimum data needed to either complete a node
|
||||
// registration (regData populated) or signal the verdict of an interactive
|
||||
// auth flow (no payload). Verdict delivery is via the finished channel; the
|
||||
// closed flag guards FinishAuth against double-close.
|
||||
//
|
||||
// AuthRequest is always handled by pointer so the channel and atomic flag
|
||||
// have a single canonical instance even when stored in caches that
|
||||
// internally copy values.
|
||||
type AuthRequest struct {
|
||||
node *Node
|
||||
// regData is populated for node-registration flows (interactive web
|
||||
// or OIDC). It carries only the minimal subset of registration data
|
||||
// the auth callback needs to promote this request into a real node;
|
||||
// see RegistrationData for the rationale behind keeping the payload
|
||||
// small.
|
||||
//
|
||||
// nil for non-registration flows (e.g. SSH check). Use
|
||||
// RegistrationData() to read it safely.
|
||||
regData *RegistrationData
|
||||
|
||||
finished chan AuthVerdict
|
||||
closed *atomic.Bool
|
||||
}
|
||||
|
||||
func NewAuthRequest() AuthRequest {
|
||||
return AuthRequest{
|
||||
// NewAuthRequest creates a pending auth request with no payload, suitable
|
||||
// for non-registration flows that only need a verdict channel.
|
||||
func NewAuthRequest() *AuthRequest {
|
||||
return &AuthRequest{
|
||||
finished: make(chan AuthVerdict, 1),
|
||||
closed: &atomic.Bool{},
|
||||
}
|
||||
}
|
||||
|
||||
func NewRegisterAuthRequest(node Node) AuthRequest {
|
||||
return AuthRequest{
|
||||
node: &node,
|
||||
// NewRegisterAuthRequest creates a pending auth request carrying the
|
||||
// minimal RegistrationData for a node-registration flow. The data is
|
||||
// stored by pointer; callers must not mutate it after handing it off.
|
||||
func NewRegisterAuthRequest(data *RegistrationData) *AuthRequest {
|
||||
return &AuthRequest{
|
||||
regData: data,
|
||||
finished: make(chan AuthVerdict, 1),
|
||||
closed: &atomic.Bool{},
|
||||
}
|
||||
}
|
||||
|
||||
// Node returns the node that is trying to register.
|
||||
// It will panic if the AuthRequest is not a registration request.
|
||||
// Can _only_ be used in the registration path.
|
||||
func (rn *AuthRequest) Node() NodeView {
|
||||
if rn.node == nil {
|
||||
panic("Node can only be used in registration requests")
|
||||
// RegistrationData returns the cached registration payload. It panics if
|
||||
// called on an AuthRequest that was not created via
|
||||
// NewRegisterAuthRequest, mirroring the previous Node() contract.
|
||||
func (rn *AuthRequest) RegistrationData() *RegistrationData {
|
||||
if rn.regData == nil {
|
||||
panic("RegistrationData can only be used in registration requests")
|
||||
}
|
||||
|
||||
return rn.node.View()
|
||||
return rn.regData
|
||||
}
|
||||
|
||||
// IsRegistration reports whether this auth request carries registration
|
||||
// data (i.e. it was created via NewRegisterAuthRequest).
|
||||
func (rn *AuthRequest) IsRegistration() bool {
|
||||
return rn.regData != nil
|
||||
}
|
||||
|
||||
func (rn *AuthRequest) FinishAuth(verdict AuthVerdict) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue