Documentation
¶
Overview ¶
Package console is backplane's console server (§11): the HTTP the shell talks to directly or through a deployment-owned reverse proxy.
POST /auth/login {token} → session cookie (HttpOnly, SameSite=Strict)
POST /auth/logout ends the session
GET /auth/session the current session, 401 without one
GET /ws ws-proto: backplane's own API (CatalogService,
SessionService, and what WithServices adds) and the
relay of everything else to the services' internal
API on their platform ports
GET /plugins/<service>/<hash>/<path>
console plugin bundles, fetched from a live instance
and cached by content hash
GET / the shell
The console listens on its own address (Settings.Listen) from the start of its node to its stop, under Settings.Prefix (or at "/"). A reverse proxy must preserve this path and support WebSocket upgrades.
Index ¶
- Constants
- Variables
- func SessionID(ctx context.Context) (uuid.UUID, bool)
- type Attempts
- type Console
- type LoginLimits
- type Option
- type PG
- func (p PG) ByToken(ctx context.Context, tokenHash []byte) (Session, error)
- func (p PG) Create(ctx context.Context, tokenHash []byte, s Session) (uuid.UUID, error)
- func (p PG) Delete(ctx context.Context, id uuid.UUID) (bool, error)
- func (p PG) DeleteOthers(ctx context.Context, keep uuid.UUID) (int64, error)
- func (p PG) DeleteStale(ctx context.Context, now, idleSince time.Time) (int64, error)
- func (p PG) Get(ctx context.Context, id uuid.UUID) (Session, error)
- func (p PG) List(ctx context.Context) ([]Session, error)
- func (p PG) Touch(ctx context.Context, id uuid.UUID, at time.Time) error
- type PGAttempts
- type Session
- type Sessions
- type Settings
Constants ¶
const ( // SessionTTL is the absolute lifetime of a session. SessionTTL = 12 * time.Hour // IdleTimeout ends a session without activity (a login, a request with // its cookie, an RPC on its connection). IdleTimeout = time.Hour )
Session lifetime (§11.3).
const ( // SecretHeader carries the installation's internal secret. SecretHeader = "bp-internal-secret" //nolint:gosec // a header name, not a credential // SessionHeader names the console session the call comes from. SessionHeader = "bp-console-session" )
Metadata the relay sets on a forwarded call (§11.1, §17).
const (
// CookieName is the session cookie.
CookieName = "bp_session"
)
const (
// MinAdminTokenLen is the shortest admin token accepted, in bytes.
MinAdminTokenLen = 16
)
const ( // SecretHTTPHeader carries the internal secret to a platform port. SecretHTTPHeader = "Bp-Internal-Secret" //nolint:gosec // a header name, not a credential )
Variables ¶
var ( // ErrNoAdminToken: no admin token is configured. ErrNoAdminToken = errors.New("console: no admin token configured") // ErrShortAdminToken: the admin token is shorter than MinAdminTokenLen. ErrShortAdminToken = fmt.Errorf("console: admin token shorter than %d characters", MinAdminTokenLen) )
Errors of Settings.Validate.
var ErrAttempts = errors.New("console: login attempts unavailable")
ErrAttempts: the login attempts cannot be counted; the login is refused.
var ( // ErrNoSession: no such session. ErrNoSession = errors.New("console: no such session") )
Errors of Sessions.
Functions ¶
Types ¶
type Attempts ¶
type Attempts interface {
// Allow takes one attempt from addr; refused, it is how long to wait.
Allow(ctx context.Context, addr string) (time.Duration, error)
// Failed records a wrong token from anywhere.
Failed(ctx context.Context) error
// Succeeded resets the global backoff.
Succeeded(ctx context.Context) error
}
Attempts counts login attempts for brute force protection (§11.3), shared by every replica: PostgreSQL in the server, memory in tests. When they cannot be counted the login is refused.
type Console ¶
Console is the console server: a component whose start checks the admin token is configured and opens the listener, whose goroutine deletes stale sessions and closes relay connections of gone instances, and whose stop shuts the listener down and closes the open /ws connections.
A Console is shared by pointer: it holds the connections, the relay pool and the bundle cache.
func New ¶
func New( parent deps.Scope, s Settings, sessions Sessions, attempts Attempts, src registry.Source, opts ...Option, ) *Console
New creates the console under parent: sessions keep the sessions, attempts count logins across replicas, src is the installation. Its start fails when s does not pass Validate.
type LoginLimits ¶
type LoginLimits struct {
// Every address has Burst attempts per Window.
Burst int
Window time.Duration
// After Threshold failures (any address, none older than Forget apart)
// every login waits Base, doubling per further failure up to Max; a
// success resets it.
Threshold int
Base, Max time.Duration
Forget time.Duration
}
LoginLimits of shared login attempts.
func DefaultLoginLimits ¶
func DefaultLoginLimits() LoginLimits
DefaultLoginLimits: 5 attempts a minute per address; after 10 failures in a row 1s, doubling up to a minute.
type Option ¶
type Option func(o *options)
Option configures New.
func WithCacheBytes ¶
WithCacheBytes caps the plugin bundle cache (default 64 MiB).
func WithServices ¶
func WithServices(register func(r grpc.ServiceRegistrar)) Option
WithServices registers more of backplane's own API on /ws (another component's gRPC services, e.g. configuration).
func WithSessionTelemetry ¶
WithSessionTelemetry installs log admission behind console session and origin checks, without requiring a public ingest key in the frontend.
func WithShell ¶
WithShell serves the console's frontend from fsys (index.html for every path that is not a file); without it "/" answers a placeholder.
func WithTelemetry ¶
WithTelemetry installs independent OTLP admission without operator auth.
type PG ¶
type PG struct {
// contains filtered or unexported fields
}
PG keeps sessions in PostgreSQL (schema backplane): console_session.
func NewPG ¶
func NewPG(st deps.Dependency[*store.Store]) PG
NewPG is the PostgreSQL Sessions over the store; the store is read once it is provided (from the console's start on).
func (PG) DeleteOthers ¶
DeleteOthers implements Sessions.
func (PG) DeleteStale ¶
DeleteStale implements Sessions.
type PGAttempts ¶
type PGAttempts struct {
// contains filtered or unexported fields
}
PGAttempts counts attempts in the platform's PostgreSQL schema. A database outage refuses logins; there is no per-replica fallback.
func NewPGAttempts ¶
func NewPGAttempts(st deps.Dependency[*store.Store], limits LoginLimits) PGAttempts
type Session ¶
type Session struct {
ID uuid.UUID
CreatedAt time.Time
ExpiresAt time.Time
LastSeenAt time.Time
Address string
UserAgent string
}
Session is one login.
type Sessions ¶
type Sessions interface {
// Create stores a session under the hash of its token; s.ID is ignored
// and the new id returned.
Create(ctx context.Context, tokenHash []byte, s Session) (uuid.UUID, error)
// ByToken finds a session by the hash of its token; ErrNoSession.
ByToken(ctx context.Context, tokenHash []byte) (Session, error)
// Get finds a session by id; ErrNoSession.
Get(ctx context.Context, id uuid.UUID) (Session, error)
// Touch moves last seen forward to at (never back).
Touch(ctx context.Context, id uuid.UUID, at time.Time) error
// List is every session, newest first.
List(ctx context.Context) ([]Session, error)
// Delete removes a session; false when there was none.
Delete(ctx context.Context, id uuid.UUID) (bool, error)
// DeleteOthers removes every session but keep and reports how many.
DeleteOthers(ctx context.Context, keep uuid.UUID) (int64, error)
// DeleteStale removes sessions expired at now or idle since idleSince.
DeleteStale(ctx context.Context, now, idleSince time.Time) (int64, error)
}
Sessions is where the sessions live: PostgreSQL (PG) in the server, memory in tests.
type Settings ¶
type Settings struct {
// Listen is the console's own listener (":8081"); empty: none (the
// Handler is served by someone else, e.g. a test server).
Listen string
// Prefix the console is mounted under ("/backplane"); empty: "/".
Prefix string
// Origins allowed to open /ws and to log in (scheme://host[:port]);
// empty: the request's own host.
Origins []string
// TrustedProxies whose X-Forwarded-For names the client (addresses,
// CIDRs): deployment-owned proxy addresses.
TrustedProxies []string
// InsecureCookie drops Secure from the session cookie and HSTS from the
// responses: plain-HTTP development only.
InsecureCookie bool
// AdminToken is what /auth/login accepts: configuration of the
// deployment, at least MinAdminTokenLen characters.
AdminToken config.Secret
// InternalSecret is presented to the services' platform ports
// (relay and bundles).
InternalSecret config.Secret
}
Settings are the console's part of the server configuration.