Documentation
¶
Overview ¶
Package authclient is the Go client for the yarilo-auth master protocol. It opens a single mTLS TCP connection to the master listener (the second socket yarilo-auth exposes — see internal/auth/protocol/master.go), drains the handshake, and provides typed methods for the wire commands the protocol surfaces today:
- Client.Userdb — password-less user lookup (USER)
- Client.IterateUsers — enumerate every known user (LIST)
- Client.PassdbLookup — placeholder; returns ErrNotImplemented until Phase AUTH-2 ships Passdb.LookupCredentials
One Client owns one TCP conn. Commands within a Client serialise behind a mutex — multiple goroutines may call methods concurrently and the wire-side ordering is enforced internally. Callers that need higher throughput open additional Clients; this package does not ship a pool today.
Consumers wire authclient at startup with the configured master address and the internal mTLS material. The current production consumer is yarilo-backend-api (Phase AUTH-1 follow-up); future consumers — yarilo-admin's userdb subcommand, the standalone smoketest — will Dial the same address.
Index ¶
- Variables
- type Client
- func (c *Client) CacheFlush(ctx context.Context, masks []string) (uint32, error)
- func (c *Client) Close() error
- func (c *Client) IssueSession(ctx context.Context, username, sid, ip string) (string, error)
- func (c *Client) IterateUsers(ctx context.Context) ([]string, error)
- func (c *Client) PassdbLookup(ctx context.Context, username string) (*protocol.UserInfo, error)
- func (c *Client) Userdb(ctx context.Context, username string) (*protocol.UserInfo, error)
Constants ¶
This section is empty.
Variables ¶
var ErrClosed = errors.New("authclient: client closed")
ErrClosed signals that a Client has had Close called or its connection terminated; subsequent calls return this so callers can re-Dial deterministically rather than hanging on the dead reader.
var ErrNotImplemented = errors.New("authclient: PASS not implemented (Phase AUTH-2)")
ErrNotImplemented is returned by Client.PassdbLookup until Phase AUTH-2 ships Passdb.LookupCredentials and the master-protocol PASS handler stops returning the corresponding `FAIL reason=PASS not implemented` line. Callers can use errors.Is to gate fall-through behaviour cleanly.
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client speaks the yarilo-auth master protocol over a single TCP (optionally mTLS-wrapped) connection. Methods are safe to call from multiple goroutines: a mutex enforces one in-flight request at a time on the underlying conn, mirroring the server-side per-connection serial-processing guarantee.
Construct with Dial / DialContext. Always call Client.Close on shutdown so the FIN propagates promptly to the server side and the goroutine watching that conn there returns.
func Dial ¶
Dial opens a connection to the yarilo-auth master listener at addr and consumes the protocol handshake. When tlsCfg is non-nil the connection is wrapped in TLS — yarilo's standard deployment supplies an mTLS config built from the internal CA + the consumer's client cert.
The handshake's VERSION line is validated: only major version 1 is accepted today. Future major bumps surface as a typed error so callers can fail fast rather than speak stale dialect.
func DialContext ¶
DialContext is Dial with a context-aware dial. The context bounds the TCP + TLS handshake; once the handshake is consumed the context has no further effect on the returned Client.
func (*Client) CacheFlush ¶
CacheFlush invokes the master-protocol CACHE-FLUSH verb. Empty masks slice triggers a full flush; otherwise each mask is sent as an additional tab-separated argument and yarilo-auth evicts every entry whose stored username matches any mask (glob syntax: `*` = any run, `?` = one char).
Returns the count of evicted entries reported by the server. Used by `yarilo-admin auth cache flush [mask…]`.
func (*Client) Close ¶
Close releases the underlying connection. Idempotent — calling Close twice returns nil the second time. After Close every other method on this Client returns ErrClosed.
func (*Client) IssueSession ¶ added in v1.57.0
IssueSession sends a SESSION command to the master listener and returns the one-time token bound to username. The token is scoped to the "lmtp" service and must be consumed by a VERIFY call on the client listener within the token TTL.
sid is the anvil session ID already registered for this delivery; ip is the originating MTA address (both are recorded in the audit log but do not affect token validity).
func (*Client) IterateUsers ¶
IterateUsers runs a LIST and collects every streamed username until the server emits the DONE marker. Backends that do not support enumeration return a FAIL line; this method surfaces that as a typed error (compare its message against the wire reason if needed).
func (*Client) PassdbLookup ¶
PassdbLookup runs a PASS lookup. The master-protocol handler for PASS returns `FAIL reason=PASS not implemented` until Phase AUTH-2 ships Passdb.LookupCredentials; this method therefore always returns ErrNotImplemented. The full method exists in PR 3 so consumers can ship the typed call surface unchanged when AUTH-2 flips the implementation on.
func (*Client) Userdb ¶
Userdb runs a USER lookup for username. Returns:
- (ui, nil) — backend hit; ui populated from the wire fields
- (nil, nil) — backend miss (master responded NOTFOUND)
- (nil, err) — wire / parse / backend error
Mirrors the protocol.Userdb contract so callers chaining Client.Userdb with other Userdb implementations see the same "not found is nil/nil" semantics.