Documentation
¶
Overview ¶
Package access is Eta's optional browser-session login. It is off by default: an Eta instance with no password configured behaves exactly as before, matching the LAN/Tailscale trust boundary the rest of the product assumes. Setting a password gates the desktop UI and this machine's API behind a login, for the case where the LAN itself is not fully trusted (a shared network, a guest VLAN, a NAS closet someone else can plug into).
The password never reaches the server. The browser derives a PBKDF2 verifier client-side and the server only ever sees that verifier, so a disk read or a request log can't leak the password itself. See web/app.ts's auth section for the client half, and Manager.Login for the challenge/response the two sides share.
Index ¶
- Constants
- Variables
- func DefaultPath() (string, error)
- func DeriveVerifier(password string, salt []byte) []byte
- func ParsePasswordHash(encoded string) (*passwordRecord, error)
- func Save(path string, cfg Config) error
- type Config
- type Manager
- func (m *Manager) Authenticated(r *http.Request) bool
- func (m *Manager) Configure(encoded string) error
- func (m *Manager) Enabled() bool
- func (m *Manager) EncodedVerifier() string
- func (m *Manager) Login(challenge, proof, remoteAddr string) (string, error)
- func (m *Manager) StatusAndChallenge() (enabled bool, salt, challenge string, err error)
- func (m *Manager) UpdatePassword(encoded string, authorized bool) (token string, revokeLiveConnections bool, err error)
- func (m *Manager) ValidSession(token string) bool
Constants ¶
const ( PasswordHashVersion = "v1" PasswordHashAlgorithm = "pbkdf2-sha256" PasswordHashIterations = 600_000 SessionTTL = 365 * 24 * time.Hour SessionCookie = "eta_access_session" )
Variables ¶
var ( ErrRateLimited = errors.New("too many failed password attempts; try again shortly") )
Functions ¶
func DefaultPath ¶
DefaultPath returns the per-user config path, alongside identity.json and state.json.
func DeriveVerifier ¶
DeriveVerifier runs the same PBKDF2-HMAC-SHA256 the browser runs. No production code path calls it: a peer's password is derived in the browser too (see web/app.ts's derivePeerVerifier, and handlePeerAuthStatus in main.go, which exists so the browser can fetch a peer's salt without contacting that peer directly). A password does not pass through this server in plaintext for its own login or for a peer's. Kept as an exported function because tests need a Go-side way to construct a valid verifier without a browser to derive one.
func ParsePasswordHash ¶
ParsePasswordHash accepts the only verifier format this package writes. The browser derives the verifier; the server stores it without ever receiving the raw password. The salt and iteration count are public KDF parameters; the verifier is the secret and is never returned by an API.
Types ¶
type Config ¶
type Config struct {
PasswordHash string `json:"password_hash,omitempty"`
}
Config is the on-disk shape. PasswordHash is the encoded verifier record (see ParsePasswordHash), never the raw password.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager holds one instance's access password state: the configured verifier, in-flight login challenges, live sessions, and a per-client failed-attempt backoff. All in memory — a restart resets sessions and backoff state, matching the no-account, no-database design; only the password verifier itself persists, via Config.
func NewManager ¶
func NewManager() *Manager
func (*Manager) EncodedVerifier ¶
EncodedVerifier returns the on-disk form of the configured password verifier (the format ParsePasswordHash accepts), or "" when no password is configured. Used by the SSH setup path to forward the same access control to a freshly installed remote eta.
func (*Manager) StatusAndChallenge ¶
StatusAndChallenge returns public KDF parameters and a single-use login challenge from one locked snapshot, so a concurrent password change cannot pair an old salt with a challenge for the new verifier.
func (*Manager) UpdatePassword ¶
func (m *Manager) UpdatePassword(encoded string, authorized bool) (token string, revokeLiveConnections bool, err error)
UpdatePassword atomically prevents an unauthenticated caller from replacing a password that became enabled between middleware evaluation and this handler running. A new verifier invalidates all prior sessions.
func (*Manager) ValidSession ¶
ValidSession checks a bare session token, for callers that carry it somewhere other than this server's own cookie jar — a peer's proxied request forwards the token it was issued, not a browser cookie read from this request.