Documentation
¶
Overview ¶
Package comqttauth manages comqtt broker authentication and authorization state from the dashboard. Each Backend implementation reads and writes the same on-disk/on-wire shape comqtt's corresponding plugin/auth/* runtime hooks already consume, so a change made through the dashboard is visible to the running broker on its next lookup without any synchronization layer or process restart.
Backends supported in v0.3.0:
- file: auth.Ledger YAML file (built-in comqtt hook)
- redis: plugin/auth/redis HSET/HGETALL key shape
- mysql: plugin/auth/mysql configurable auth/acl tables
- postgres: plugin/auth/postgresql configurable auth/acl tables
The dashboard's Auth and ACL pages consume Backend through a single interface. The active backend is selected by the cmd-binary based on cfg.Auth.Datasource and constructed via factory.New().
This package does not manage the dashboard's own operator credentials (admin/viewer roles) - those live in dashboard/auth and are unrelated to MQTT-broker auth.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrConflict = errors.New("comqttauth: conflict")
ErrConflict is returned when a write would create a duplicate of a unique record (e.g. a second user with the same username).
var ErrNotFound = errors.New("comqttauth: not found")
ErrNotFound is returned when a requested record does not exist.
var ErrUnsupported = errors.New("comqttauth: operation not supported by this backend")
ErrUnsupported is returned by Backend methods when the operation is not supported by the active backend (e.g. user CRUD against an http-delegated auth backend, or wildcard-subject ACL queries against a key-value store that only indexes by exact subject).
Functions ¶
This section is empty.
Types ¶
type ACLRule ¶
type ACLRule struct {
ID string `json:"id"`
Subject string `json:"subject"`
Topic string `json:"topic"`
Access Access `json:"access"`
}
ACLRule is the wire shape for one row in the ACL table. ID is backend- assigned and opaque to callers (a row id for SQL backends, the topic filter for redis, or the slice index for the file backend).
type Access ¶
type Access uint8
Access matches comqtt's auth.Access constants. The dashboard exposes the four values directly in ACL editing forms; backends store them as the same byte values.
type AuthMode ¶
type AuthMode uint8
AuthMode selects what the lookup key is for auth and ACL records. It mirrors comqtt's auth.Access constants where it is overloaded as a mode indicator (0=anon, 1=username, 2=clientid).
type AuthTable ¶
AuthTable mirrors plugin/auth/{mysql,postgresql}.AuthTable so the dashboard reads and writes the same physical table the broker reads.
type Backend ¶
type Backend interface {
// Kind returns a short stable name for the backend ("file", "redis",
// "mysql", "postgres"). Used in admin UI badges and structured logging.
Kind() string
// Mode returns how user records are keyed (username or clientid). The UI
// labels Subject columns accordingly.
Mode() AuthMode
// HashType returns the password hash algorithm this backend writes. The UI
// labels password fields with this so operators know what they are
// configuring.
HashType() HashType
// Users returns all user records. Returns an empty slice (not nil) when
// no users exist.
Users(ctx context.Context) ([]User, error)
// GetUser returns the user with the given subject, or ErrNotFound.
GetUser(ctx context.Context, subject string) (*User, error)
// PutUser upserts a user record. plaintextPassword is hashed per
// HashType() before write. Pass empty plaintextPassword to leave the
// stored password unchanged on update; ErrNotFound on update of a missing
// subject; the implementation distinguishes create vs update by existence
// of the record.
PutUser(ctx context.Context, u User, plaintextPassword string) error
// DeleteUser removes the user with the given subject. Returns ErrNotFound
// when no record matched.
DeleteUser(ctx context.Context, subject string) error
// Rules returns ACL rules for the given subject, or all rules when
// subject is empty. Returns an empty slice when no rules match.
Rules(ctx context.Context, subject string) ([]ACLRule, error)
// PutRule inserts or updates an ACL rule. If r.ID is empty, the
// implementation creates a new record and returns its assigned id.
// Otherwise the existing record with that id is replaced; ErrNotFound if
// the id does not exist.
PutRule(ctx context.Context, r ACLRule) (string, error)
// DeleteRule removes the ACL rule with the given id. ErrNotFound if no
// record matched.
DeleteRule(ctx context.Context, id string) error
// Close releases any underlying connections. Idempotent.
Close() error
}
Backend is the unified interface the dashboard's Auth and ACL pages call. Each plugin/auth/* in comqtt has a corresponding implementation under this package's sub-trees.
All Context-taking methods are expected to honor cancellation and obey any deadline set by callers (typically a 3s default applied by the handler layer to keep dashboard responsiveness predictable).
func New ¶
New constructs the Backend for cfg.Kind. Returns an error if the per-Kind sub-config is missing or if Kind is unknown.
Chunks 2-5 of v0.3.0 fill in the per-backend constructors. Until then, each constructor returns a stub that responds to interface calls with ErrUnsupported so the surrounding dashboard handler scaffold can be wired independently.
type Config ¶
type Config struct {
Kind string
// Mode is the lookup key used by user records.
// ACLMode is the lookup key used by ACL records. Comqtt allows these to
// differ (e.g. auth-by-username, ACL-by-clientid) so we keep them
// independent.
Mode AuthMode
ACLMode AuthMode
// HashType is the algorithm used for password storage. HashKey is the
// shared secret consumed by HMAC-* variants and ignored otherwise.
HashType HashType
HashKey string
// Per-backend specifics. The factory consults the field matching Kind
// and returns an error if it is nil.
File *FileConfig
Redis *RedisConfig
SQL *SQLConfig
}
Config is the disjoint-union of per-backend configurations. Exactly one of File/Redis/SQL is consulted, picked by Kind. Mode, ACLMode, HashType, and HashKey apply across all backends.
Kind is the canonical lowercase backend name: "file" | "redis" | "mysql" | "postgres". Pass-through from the broker's --auth-ds flag.
type FileConfig ¶
type FileConfig struct {
// Path is the YAML file. Must be writable by the dashboard process; the
// file backend writes via atomic rename so a partial flush never makes
// the broker see half a config.
Path string
}
FileConfig points at a YAML ledger file matching the shape consumed by comqtt's built-in mqtt/hooks/auth.Hook running in LedgerMode.
type HashType ¶
type HashType uint8
HashType identifies which hashing algorithm a backend uses for stored passwords. Values match comqtt's plugin/auth.HashType so a dashboard configured with the same hash as the broker writes hashes the broker can verify.
type RedisConfig ¶
type RedisConfig struct {
Addr string
Username string
Password string
DB int
// AuthKeyPrefix defaults to "comqtt:auth" when empty (matching
// plugin/auth/redis.defaultAuthkeyPrefix).
AuthKeyPrefix string
// ACLKeyPrefix defaults to "comqtt:acl" when empty.
ACLKeyPrefix string
}
RedisConfig matches the lookup shape of comqtt's plugin/auth/redis: a HASH at AuthKeyPrefix (default "comqtt:auth") and per-subject HASH at ACLKeyPrefix:<subject>.
type SQLConfig ¶
SQLConfig is shared between MySQL and Postgres backends; Driver selects. Driver is one of "mysql" | "postgres". DSN is the database/sql connection string the chosen driver expects.
type User ¶
type User struct {
// Subject is the lookup key for this record: a username when the backend
// is configured AuthMode=Username, or a clientID when AuthMode=ClientID.
Subject string `json:"subject"`
// Allow is whether the user may connect. False denies authentication
// without removing the record (useful for temporary lockouts).
Allow bool `json:"allow"`
}
User is the wire shape returned by Backend.Users / Backend.GetUser. Passwords are never read back through this struct; PutUser takes the plaintext separately.