config

package
v0.25.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 15, 2026 License: AGPL-3.0 Imports: 20 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// DefaultOIDCScopes is the scope set requested from the issuer.
	DefaultOIDCScopes = "openid email profile"
	// DefaultOIDCGroupsClaim is the ID-token claim read for directory group
	// membership when DBB_OIDC_GROUPS_CLAIM is unset.
	DefaultOIDCGroupsClaim = "groups"
	// DefaultOIDCDisplayName is the login-button label when the operator
	// does not set one.
	DefaultOIDCDisplayName = "SSO"
)

OIDC provider defaults.

View Source
const (
	// DefaultApprovalSlackDelay is how long a hold waits before escalating.
	DefaultApprovalSlackDelay = "30s"
	// ApprovalSlackSQLMaxLen bounds the SQL text copied into Slack.
	ApprovalSlackSQLMaxLen = 500
)

Default approval-hold settings.

View Source
const (
	DefaultDumpMaxSize   = 10 * 1024 * 1024 // 10MB
	DefaultDumpRetention = "24h"
)

Default dump settings.

View Source
const (
	// MSSQLTLSMaxVersion12 pins the encapsulated handshake to TLS 1.2.
	MSSQLTLSMaxVersion12 = "1.2"
	// MSSQLTLSMaxVersion13 allows TLS 1.3 on the client leg.
	MSSQLTLSMaxVersion13 = "1.3"
	// MSSQLDefaultTLSMaxVersion is what an unset variable means.
	//
	// It is 1.2 on purpose, and not for lack of ambition: under TLS 1.2 both
	// peers end their handshake on a *read*, so the framed→raw switch that TDS
	// encapsulation forces lands on the same byte for both. Under 1.3 the
	// client ends on a *write* and drivers differ on whether that last flight
	// is still encapsulated. dbbat handles both (see internal/proxy/mssql),
	// but only go-mssqldb has been verified end to end, so an existing
	// deployment must not change behavior merely by upgrading.
	MSSQLDefaultTLSMaxVersion = MSSQLTLSMaxVersion12
)

SQL Server client-leg TLS version ceilings, as accepted in DBB_MSSQL_TLS_MAX_VERSION.

View Source
const (
	DefaultMaxResultRows  = 100000
	DefaultMaxResultBytes = 100 * 1024 * 1024 // 100MB
)

Default query storage limits.

View Source
const (
	DefaultRateLimitEnabled = true
	DefaultRateLimitRPM     = 60
	DefaultRateLimitRPMAnon = 10
	DefaultRateLimitBurst   = 10
)

Default rate limiting settings.

View Source
const (
	DefaultHashMemoryMB = 64
	DefaultHashTime     = 1
	DefaultHashThreads  = 4
)

Default hash settings (matching current argon2id defaults).

View Source
const (
	DefaultAuthCacheEnabled    = true
	DefaultAuthCacheTTLSeconds = 300 // 5 minutes
	DefaultAuthCacheMaxSize    = 10000
)

Default auth cache settings.

View Source
const DefaultBaseURL = "/app"

DefaultBaseURL is the default base URL path for the frontend.

View Source
const DefaultDemoTargetDB = "demo:demo@localhost/demo"

DefaultDemoTargetDB is the default value for DemoTargetDB.

View Source
const DefaultLogLevel = "info"

DefaultLogLevel is the default log level.

View Source
const DefaultOAuthRole = "connector"

DefaultOAuthRole is the role an auto-provisioned OAuth user starts with when DBB_AUTH_DEFAULT_ROLE is unset. It mirrors store.RoleConnector, which config cannot import (store imports config); TestConfigKnownRolesMatchStore pins the two together.

View Source
const DefaultQueryStorageRetention = "0"

DefaultQueryStorageRetention keeps query history forever. Retention is opt-in: see QueryStorageConfig.Retention.

View Source
const FallbackInstanceID = "dbbat"

FallbackInstanceID is used when no DBB_INSTANCE_ID is set and the hostname cannot be read. It is deliberately a constant rather than a random value: it is what attributes a connection row to a recognizable owner, and a value that changed on every start would leave a trail of ids nobody can interpret.

It is also the one way replicas can end up sharing an id without anyone asking for it — every replica that cannot read its hostname lands here. That is no longer dangerous: the reconcile keys on the per-run id the store mints at startup, which cannot be shared, so replicas sharing this value still cannot close each other's connections. It stays undesirable — several processes then answer to one identity in the logs, the UI and the reclaim's counts — and reaching it at all takes a broken container; see resolveInstanceID.

Variables

View Source
var (
	ErrDSNRequired    = errors.New("DBB_DSN environment variable is required")
	ErrKeyRequired    = errors.New("either DBB_KEY or DBB_KEYFILE must be set")
	ErrInvalidKeySize = errors.New("encryption key must be 32 bytes")

	// ErrDumpUploadNeedsDir is returned when an upload target is configured
	// without a local spool. Captures are always written to disk first and
	// uploaded once complete (S3 objects cannot be appended to), so an upload
	// URL with no DBB_DUMP_DIR would silently capture nothing.
	ErrDumpUploadNeedsDir = errors.New("DBB_DUMP_UPLOAD_URL requires DBB_DUMP_DIR")

	// ErrOIDCClientCredentialsRequired is returned when an OIDC issuer is
	// configured without client credentials. Failing at startup beats
	// offering a login button that can only ever end in an error page.
	ErrOIDCClientCredentialsRequired = errors.New(
		"DBB_OIDC_ISSUER requires DBB_OIDC_CLIENT_ID and DBB_OIDC_CLIENT_SECRET")

	// ErrOIDCRoleMappingInvalid is returned when DBB_OIDC_ROLE_MAPPING cannot
	// be parsed. A mapping is an authorization rule: a typo must stop the
	// process, never silently resolve to "no rule" and hand everyone the
	// default role.
	ErrOIDCRoleMappingInvalid = errors.New("DBB_OIDC_ROLE_MAPPING is malformed")

	// ErrAuthDefaultRoleInvalid is returned when DBB_AUTH_DEFAULT_ROLE (or its
	// legacy alias DBB_SLACK_AUTH_DEFAULT_ROLE) names a role that does not
	// exist. Same reasoning as the role mapping: a default role is an
	// authorization decision, and one that fails closed at startup is far
	// better than one that quietly provisions users into a role nothing knows.
	ErrAuthDefaultRoleInvalid = errors.New("DBB_AUTH_DEFAULT_ROLE is not a known role")

	// ErrAuthProviderUnknown is returned when a per-provider auto-provisioning
	// override names a login provider that does not exist. Ignoring it would
	// fail *open*: an operator writing DBB_AUTH_AUTO_CREATE_USERS_OKTA to gate
	// their issuer would get no override, no error, and auto-provisioning still
	// on for everyone.
	ErrAuthProviderUnknown = errors.New("unknown OAuth provider in a per-provider auto-provisioning override")
)

Configuration errors.

View Source
var ErrMSSQLTLSMaxVersionInvalid = errors.New(
	`invalid DBB_MSSQL_TLS_MAX_VERSION: want "1.2" or "1.3"`)

ErrMSSQLTLSMaxVersionInvalid is returned when DBB_MSSQL_TLS_MAX_VERSION holds something other than "1.2" or "1.3". It fails the process at startup rather than silently falling back, because a deployment that asked for a TLS floor and quietly got a different one is exactly the sort of thing nobody notices.

View Source
var KnownOAuthProviders = []string{"slack", "oidc"}

KnownOAuthProviders is the set of login-provider keys a per-provider auto-provisioning override may name. Same duplication as KnownRoles and for the same reason: internal/auth/slack and internal/auth/oidc both import config, so config cannot name their provider constants. TestConfigKnownOAuthProvidersMatchProviders in internal/api pins the lists together — a provider added on one side without the other would make its override a startup failure.

View Source
var KnownRoles = []string{"admin", "viewer", "connector"}

KnownRoles is the set of role names a role mapping may name. It duplicates store.RoleAdmin/RoleViewer/RoleConnector on purpose: store imports config, so config cannot import store. TestConfigKnownRolesMatchStore in internal/api pins the two lists together.

Functions

func DefaultKeyFilePath

func DefaultKeyFilePath() (string, error)

DefaultKeyFilePath returns the path to the default key file (~/.dbbat/key).

func ParseLogLevel added in v0.1.0

func ParseLogLevel(level string) slog.Level

ParseLogLevel parses a log level string and returns the corresponding slog.Level. Supported values (case-insensitive): debug, info, warn, warning, error. Returns slog.LevelInfo for invalid values.

Types

type ApprovalConfig added in v0.20.0

type ApprovalConfig struct {
	// Enabled turns the approval gate on. When false, approval patterns on
	// grants are inert: nothing is ever held.
	Enabled bool `koanf:"enabled"`
	// SlackDelay is how long a hold must remain pending before a Slack
	// notification fires. Zero disables Slack escalation entirely. There is
	// no presence detection: if an admin was watching, they had this long to
	// act, and resolving the hold cancels the pending notification.
	SlackDelay string `koanf:"slack_delay"`
	// SlackSQL includes the (truncated) SQL text in the Slack message.
	// Default on. Slack is a lower trust boundary than the dbbat UI and this
	// feature pipes production query text into it, so it is switchable off.
	SlackSQL bool `koanf:"slack_sql"`
}

ApprovalConfig configures pattern-triggered approval holds — the four-eyes control that suspends a matching statement mid-flight until a second human approves it.

Enabled defaults to **false**. This feature blocks a live database connection on a human being; it ships off and gets turned on deliberately, per deployment.

func (ApprovalConfig) SlackDelayDuration added in v0.20.0

func (c ApprovalConfig) SlackDelayDuration() time.Duration

SlackDelayDuration parses SlackDelay, falling back to the default on a malformed value (a typo must not silently disable escalation). A zero or negative value disables escalation, which is an explicit opt-out.

type AuthCacheConfig added in v0.0.1

type AuthCacheConfig struct {
	// Enabled enables/disables the authentication cache.
	Enabled bool `koanf:"enabled"`

	// TTLSeconds is the time-to-live for cache entries in seconds.
	TTLSeconds int `koanf:"ttl_seconds"`

	// MaxSize is the maximum number of cache entries.
	MaxSize int `koanf:"max_size"`
}

AuthCacheConfig holds configuration for authentication caching.

type Config

type Config struct {
	// Proxy listen address.
	ListenPG string `koanf:"listen_pg"`

	// Oracle proxy listen address (empty = disabled).
	ListenOracle string `koanf:"listen_ora"`

	// MySQL proxy listen address (empty = disabled).
	ListenMySQL string `koanf:"listen_mysql"`

	// MongoDB proxy listen address (empty = disabled).
	ListenMongo string `koanf:"listen_mongo"`

	// SQL Server (TDS) proxy listen address (empty = disabled).
	ListenMSSQL string `koanf:"listen_mssql"`

	// REST API listen address.
	ListenAPI string `koanf:"listen_api"`

	// PostgreSQL DSN for DBBat storage.
	DSN string `koanf:"dsn"`

	// Base64-encoded encryption key (alternative to KeyFile).
	Key string `koanf:"key"`

	// Path to file containing encryption key (alternative to Key).
	KeyFile string `koanf:"keyfile"`

	// ConfigFile path (not loaded from config, set via CLI).
	ConfigFile string `koanf:"-"`

	// Encryption key for database credentials (32 bytes).
	// Populated from Key or KeyFile after loading.
	EncryptionKey []byte `koanf:"-"`

	// RunMode controls whether test data is provisioned on startup.
	RunMode RunMode `koanf:"run_mode"`

	// InstanceID identifies this dbbat process among the replicas sharing the
	// same store. It is stamped on every connection row, alongside the run id
	// the store mints at startup, so the reconcile of crash-orphaned
	// connections can tell a dead run's rows from a live one's. Defaults to the
	// hostname, which is the pod name under Kubernetes. Empty is not a valid
	// runtime value — Load fills it in.
	InstanceID string `koanf:"instance_id"`

	// DemoTargetDB specifies the only allowed database target in demo mode.
	// Format: "user:password@host/dbname" (e.g., "demo:demo@localhost/demo")
	// Only applies when RunMode is "demo". If empty, defaults to "demo:demo@localhost/demo".
	DemoTargetDB string `koanf:"demo_target_db"`

	// QueryStorage holds query result storage configuration.
	QueryStorage QueryStorageConfig `koanf:"query_storage"`

	// RateLimit holds rate limiting configuration.
	RateLimit RateLimitConfig `koanf:"rate_limit"`

	// Hash holds password hashing configuration.
	Hash HashConfig `koanf:"hash"`

	// AuthCache holds authentication cache configuration.
	AuthCache AuthCacheConfig `koanf:"auth_cache"`

	// BaseURL is the base URL path for the frontend app (default: "/app").
	BaseURL string `koanf:"base_url"`

	// Redirects contains dev redirect rules parsed from DBB_REDIRECTS env var.
	// Not loaded from config file, parsed from environment only.
	Redirects []RedirectRule `koanf:"-"`

	// LogLevel controls the logging verbosity (debug, info, warn, error).
	// Default is "info".
	LogLevel string `koanf:"log_level"`

	// SlackAuth holds Slack OAuth configuration.
	SlackAuth SlackAuthConfig `koanf:"slack_auth"`

	// Auth holds the auto-provisioning settings shared by every OAuth/OIDC
	// login provider.
	Auth OAuthUsersConfig `koanf:"auth"`

	// OIDCAuth holds the generic OpenID Connect login provider.
	OIDCAuth OIDCAuthConfig `koanf:"oidc"`

	// SlackNotify holds outbound Slack notification configuration for
	// grant request events.
	SlackNotify SlackNotifyConfig `koanf:"slack_notify"`

	// PublicURL is the externally reachable base URL for this dbbat
	// instance. Used to build deep-links in Slack notifications. Required
	// only if SlackNotify is enabled.
	PublicURL string `koanf:"public_url"`

	// Dump holds session packet dump configuration.
	Dump DumpConfig `koanf:"dump"`

	// MySQL holds MySQL proxy specific configuration.
	MySQL MySQLConfig `koanf:"mysql"`

	// Mongo holds MongoDB proxy specific configuration.
	Mongo MongoConfig `koanf:"mongo"`

	// MSSQL holds SQL Server proxy specific configuration.
	MSSQL MSSQLConfig `koanf:"mssql"`

	// PG holds PostgreSQL proxy specific configuration.
	PG PGConfig `koanf:"pg"`

	// Approval holds pattern-triggered approval-hold configuration.
	Approval ApprovalConfig `koanf:"approval"`

	// MCP holds the Model Context Protocol endpoint configuration.
	MCP MCPConfig `koanf:"mcp"`
}

Config holds the application configuration.

func Load

func Load(opts LoadOptions, cliOverrides ...func(*Config)) (*Config, error)

Load reads configuration from environment variables and optional config file. Priority order: CLI overrides > Environment variables > Config file > Defaults

func (*Config) GetDemoTarget

func (c *Config) GetDemoTarget() *DemoTarget

GetDemoTarget parses and returns the demo target configuration. Returns nil if not in demo mode.

func (*Config) GetHashParams added in v0.0.1

func (c *Config) GetHashParams() ResolvedHashParams

GetHashParams returns the resolved hash parameters.

func (*Config) IsDemoMode

func (c *Config) IsDemoMode() bool

IsDemoMode returns true if running in demo mode.

func (*Config) ValidateDemoTarget

func (c *Config) ValidateDemoTarget(username, password, host, database string) string

ValidateDemoTarget checks if the given credentials match the demo target. Returns an error message if validation fails, or empty string if valid.

type DemoTarget

type DemoTarget struct {
	Username string
	Password string
	Host     string
	Server   string
}

DemoTarget holds the parsed demo target database credentials.

func ParseDemoTargetDB

func ParseDemoTargetDB(s string) *DemoTarget

ParseDemoTargetDB parses a demo target string in format "user:pass@host/dbname".

type DumpConfig added in v0.5.0

type DumpConfig struct {
	// Dir is the directory for dump files. Empty = disabled.
	Dir string `koanf:"dir"`

	// MaxSize is the maximum dump file size per session in bytes.
	MaxSize int64 `koanf:"max_size"`

	// Retention is the auto-delete duration for old dumps (e.g., "24h").
	//
	// It applies to the local spool only. When UploadURL is set, remote
	// retention is the bucket's own lifecycle policy — dbbat never expires
	// objects it uploaded, and never LISTs the bucket to look for them.
	Retention string `koanf:"retention"`

	// UploadURL is the blob-storage bucket finished captures are uploaded to
	// on session close, e.g. "s3://my-bucket/dbbat-captures". Empty — the
	// default — keeps captures on local disk only, which is the historical
	// behavior.
	//
	// The scheme selects the driver (gocloud.dev/blob): "s3://" for S3 and
	// S3-compatible stores, "file://" for a local directory (useful in tests
	// and for a mounted volume). Any path after the bucket is used as a key
	// prefix. Requires Dir: captures are always spooled locally first and
	// uploaded once complete.
	UploadURL string `koanf:"upload_url"`
}

DumpConfig holds configuration for session packet dumps.

type HashConfig added in v0.0.1

type HashConfig struct {
	// Preset is a named configuration preset (default, low, minimal).
	Preset string `koanf:"preset"`

	// MemoryMB is the memory parameter in megabytes (1-1024).
	MemoryMB int `koanf:"memory_mb"`

	// Time is the time/iterations parameter (1-10).
	Time int `koanf:"time"`

	// Threads is the parallelism parameter (1-16).
	Threads int `koanf:"threads"`
}

HashConfig holds password hashing configuration.

type LoadOptions

type LoadOptions struct {
	// ConfigFile is the path to a config file (YAML, JSON, or TOML).
	ConfigFile string
}

LoadOptions configures how configuration is loaded.

type MCPConfig added in v0.24.0

type MCPConfig struct {
	// Enabled registers POST/GET/DELETE /api/v1/mcp. When false the routes do
	// not exist at all — a disabled feature should not answer, not even 403.
	Enabled bool `koanf:"enabled"`
}

MCPConfig configures the Model Context Protocol endpoint that lets AI agents query databases through dbbat.

Enabled defaults to **true**, deliberately unlike ApprovalConfig. The endpoint is API-key gated, and every statement it runs is executed by dialing dbbat's own proxy listener as the key's owner — so it grants an agent nothing the key holder could not already do with psql, and it adds no enforcement path of its own. Turning it off is for deployments that want the route surface gone entirely, not a safety default.

type MSSQLConfig added in v0.23.0

type MSSQLConfig struct {
	// TLS holds TLS server-termination settings for the proxy. TDS is the odd
	// one out: the handshake is encapsulated inside PRELOGIN-typed TDS packets
	// rather than starting on a clean byte boundary, and a client connecting
	// with Encrypt=no still runs one — TLS then covers the LOGIN7 packet only.
	// When Disable is true the proxy answers ENCRYPT_NOT_SUP and the listener
	// stays plaintext, which also refuses clients that require encryption.
	TLS TLSConfig `koanf:"tls"`

	// TLSMaxVersion caps the client-leg handshake. Empty (the default) means
	// TLS 1.2 — see MSSQLDefaultTLSMaxVersion for why that is not simply "the
	// newest thing crypto/tls supports". "1.3" opts in.
	//
	// It lives here rather than on the shared TLSConfig because it is a TDS
	// encapsulation concern: the other four proxies upgrade on a clean byte
	// boundary and have nothing to decide.
	TLSMaxVersion string `koanf:"tls_max_version"`
}

MSSQLConfig holds configuration specific to the SQL Server (TDS) proxy.

func (MSSQLConfig) ResolveTLSMaxVersion added in v0.23.0

func (c MSSQLConfig) ResolveTLSMaxVersion() (uint16, error)

ResolveTLSMaxVersion validates TLSMaxVersion and returns the crypto/tls constant it names. An empty value resolves to MSSQLDefaultTLSMaxVersion.

type MongoConfig added in v0.16.0

type MongoConfig struct {
	// TLS holds TLS server-termination settings for the proxy. Mongo TLS is
	// implicit-from-byte-0 (no STARTTLS dance): when certs are configured (or
	// auto-generated) the proxy terminates TLS, and SASL PLAIN auth is only
	// accepted over TLS. When Disable is true the listener stays plaintext.
	TLS TLSConfig `koanf:"tls"`
}

MongoConfig holds configuration specific to the MongoDB proxy.

type MySQLConfig added in v0.7.0

type MySQLConfig struct {
	// TLS holds TLS server-termination settings for the proxy. When enabled,
	// the proxy advertises CLIENT_SSL and accepts SSL Request packets from
	// clients, terminating the TLS session at the proxy. Required for clean
	// caching_sha2_password full-auth (cleartext password over TLS).
	TLS TLSConfig `koanf:"tls"`
}

MySQLConfig holds configuration specific to the MySQL proxy.

type OAuthProviderUsersConfig added in v0.24.0

type OAuthProviderUsersConfig struct {
	// AutoCreateUsers is a pointer because "unset" and "false" must be
	// different answers. Auto-provisioning defaults to *on*, so a plain bool
	// would make an unset override indistinguishable from an explicit
	// "false" — and the whole point of the override is letting one provider
	// say false while the instance says true.
	AutoCreateUsers *bool `koanf:"auto_create_users"`
	// DefaultRole overrides the role this provider's auto-provisioned accounts
	// start with. Empty means "no override", so a provider cannot opt back
	// into the built-in default against an instance-wide setting — spelling the
	// instance-wide role out is the way to say that, and it is unambiguous.
	DefaultRole string `koanf:"default_role"`
}

OAuthProviderUsersConfig is one provider's override of the instance-wide auto-provisioning settings. Every field is optional: what is not set here falls back to the instance-wide value, which itself falls back to the default.

type OAuthUsersConfig added in v0.24.0

type OAuthUsersConfig struct {
	// AutoCreateUsers lets an unknown but verified identity provision itself a
	// local account on first login. Defaults to true.
	AutoCreateUsers bool `koanf:"auto_create_users"`
	// DefaultRole is the role such an account starts with, and the floor a
	// group role mapping can never dig below. Empty means DefaultOAuthRole.
	DefaultRole string `koanf:"default_role"`
	// Providers overrides both settings for one login provider, keyed by the
	// provider's registered name ("slack", "oidc"). Written as
	// DBB_AUTH_AUTO_CREATE_USERS_<PROVIDER> / DBB_AUTH_DEFAULT_ROLE_<PROVIDER>,
	// or as auth.providers.<name>.* in a config file. A key nobody registered
	// is a startup failure (see Validate).
	Providers map[string]OAuthProviderUsersConfig `koanf:"providers"`
}

OAuthUsersConfig holds the auto-provisioning settings that apply to **every** OAuth/OIDC login provider — Slack, the generic OIDC issuer, and whatever comes next.

They used to live on SlackAuthConfig, which meant an operator who had never touched Slack still had to set DBB_SLACK_AUTH_AUTO_CREATE_USERS=false to stop their OIDC issuer from minting accounts. The canonical names are now DBB_AUTH_AUTO_CREATE_USERS and DBB_AUTH_DEFAULT_ROLE; the DBB_SLACK_AUTH_* ones keep working as aliases (applyAuthProvisioningAliases). One knob for every provider is right for the common case and wrong for a deployment running two providers at different trust levels — a tightly-gated Entra tenant where auto-provisioning is exactly what you want, next to a Slack workspace full of contractors that should only admit accounts an admin created by hand. Providers holds that per-provider override; the two accessors below are the only way either setting is read.

func (OAuthUsersConfig) AutoCreateUsersFor added in v0.24.0

func (c OAuthUsersConfig) AutoCreateUsersFor(providerName string) bool

AutoCreateUsersFor reports whether providerName may auto-provision accounts: its own override if it set one, otherwise the instance-wide value.

func (OAuthUsersConfig) Role added in v0.24.0

func (c OAuthUsersConfig) Role() string

Role returns the configured default role verbatim, falling back to DefaultOAuthRole when unset.

Deliberately no normalization: Validate refuses anything that is not spelled exactly like a known role, so in a process that booted this is either "" or one of KnownRoles, and there is nothing left to normalize. See Validate for why normalizing here would be actively unsafe.

func (OAuthUsersConfig) RoleFor added in v0.24.0

func (c OAuthUsersConfig) RoleFor(providerName string) string

RoleFor returns the default role providerName's auto-provisioned accounts start with — its override, then the instance-wide value, then DefaultOAuthRole.

Same non-normalization as Role: Validate refuses anything a normalizer would have had to fix, per-provider values included.

func (OAuthUsersConfig) Validate added in v0.24.0

func (c OAuthUsersConfig) Validate() error

Validate refuses a default role that is not a real role. A typo here would otherwise provision every auto-created user into a role that grants nothing and that no permission check has ever heard of — failing at startup is the far cheaper outcome, and it is the same rule ParseRoleMapping applies to the role names in a group mapping.

The match is exact, and a near-miss like "Admin" or " admin " is an error rather than something quietly folded to "admin". That looks pedantic and is not: before these settings moved off SlackAuthConfig the default role was read raw and never validated, so DBB_SLACK_AUTH_DEFAULT_ROLE=Admin matched no role and granted precisely nothing. Normalizing it now would turn a dormant typo into a genuine admin default for every auto-provisioned user of that deployment — a privilege escalation delivered by an upgrade, with nothing in the release notes to warn anyone. Refusing to start says it out loud instead, and the fix is one character. A per-provider override goes through exactly the same check — a typo is a typo whichever name carried it, and an override that fails to apply is the more dangerous half of the pair, since it silently leaves the looser instance-wide policy in force.

type OIDCAuthConfig added in v0.24.0

type OIDCAuthConfig struct {
	// Issuer is the OIDC issuer URL (e.g. "https://accounts.google.com").
	// Setting it is what enables the provider.
	Issuer string `koanf:"issuer"`
	// ClientID and ClientSecret identify this dbbat instance to the issuer.
	ClientID     string `koanf:"client_id"`
	ClientSecret string `koanf:"client_secret"`
	// Scopes is the space- or comma-separated scope list requested at
	// authorization time. "openid" is always added.
	Scopes string `koanf:"scopes"`
	// DisplayName is the login-button label (e.g. "Acme SSO").
	DisplayName string `koanf:"display_name"`
	// EmailDomains is an optional comma-separated allowlist. When set, a
	// login is rejected unless the *verified* email claim's domain is
	// listed — the generic equivalent of Slack's workspace gating.
	EmailDomains string `koanf:"email_domains"`
	// GroupsClaim names the ID-token claim carrying the user's directory
	// group membership. Empty means "groups", which is what Okta, Keycloak
	// and Entra all use by default.
	GroupsClaim string `koanf:"groups_claim"`
	// RoleMapping binds dbbat roles to directory groups, e.g.
	// "admin=db-admins,viewer=analysts". Empty disables the mapping
	// entirely, leaving role assignment manual.
	RoleMapping string `koanf:"role_mapping"`
}

OIDCAuthConfig holds the generic OpenID Connect login provider — the one that lets an organization sign in with Google Workspace, Okta, Microsoft Entra, Keycloak or anything else speaking OIDC discovery. Distinct from SlackAuthConfig: both can be enabled at once, and the login page shows a button per enabled provider.

func (OIDCAuthConfig) EmailDomainList added in v0.24.0

func (c OIDCAuthConfig) EmailDomainList() []string

EmailDomainList splits EmailDomains on whitespace and commas.

func (OIDCAuthConfig) Enabled added in v0.24.0

func (c OIDCAuthConfig) Enabled() bool

Enabled returns true when an issuer is configured. Client id and secret are validated at startup once Enabled is true, so a half-configured provider fails loudly instead of silently offering a broken login button.

func (OIDCAuthConfig) GroupsClaimName added in v0.24.0

func (c OIDCAuthConfig) GroupsClaimName() string

GroupsClaimName returns the configured groups claim, defaulting to "groups".

func (OIDCAuthConfig) ParseRoleMapping added in v0.24.0

func (c OIDCAuthConfig) ParseRoleMapping() (map[string][]string, error)

ParseRoleMapping turns "admin=db-admins,viewer=analysts" into {"admin": ["db-admins"], "viewer": ["analysts"]}.

Pairs are separated by commas only — never by whitespace — because directory groups are routinely named "Domain Admins". The role is the part before the first "=", lower-cased and validated against KnownRoles; everything after it is the group value, kept verbatim (Entra sends group **object ids**, not display names, and matching is exact, case included). Repeating a role unions its groups: "admin=db-admins,admin=sre" grants admin to either.

An empty map means "no mapping configured"; an error means the operator typed something that cannot be an authorization rule.

func (OIDCAuthConfig) RoleMappingEnabled added in v0.24.0

func (c OIDCAuthConfig) RoleMappingEnabled() bool

RoleMappingEnabled reports whether a group-to-role mapping is configured. Without one, nothing in the login path ever touches a user's roles.

func (OIDCAuthConfig) ScopeList added in v0.24.0

func (c OIDCAuthConfig) ScopeList() []string

ScopeList splits Scopes on whitespace and commas.

type PGConfig added in v0.8.0

type PGConfig struct {
	// TLS holds TLS server-termination settings for the proxy. When enabled,
	// the proxy responds 'S' to SSLRequest and terminates TLS at the proxy.
	// Without this, clients with sslmode=prefer silently fall back to
	// plaintext and credentials travel over the wire in the clear.
	TLS TLSConfig `koanf:"tls"`
}

PGConfig holds configuration specific to the PostgreSQL proxy.

type QueryStorageConfig

type QueryStorageConfig struct {
	// MaxResultRows is the maximum number of rows to store per query.
	MaxResultRows int `koanf:"max_result_rows"`

	// MaxResultBytes is the maximum total bytes to store per query.
	MaxResultBytes int64 `koanf:"max_result_bytes"`

	// StoreResults enables/disables result storage globally.
	StoreResults bool `koanf:"store_results"`

	// Retention is how long query history (and the captured result rows
	// hanging off it) is kept, as a Go duration (e.g. "720h").
	//
	// Empty or "0" means keep forever, and that is the default: dbbat is an
	// audit tool, so an upgrade must never silently start deleting history.
	// Operators opt in — "720h" (30 days) is a reasonable starting point.
	Retention string `koanf:"retention"`
}

QueryStorageConfig holds configuration for query result storage.

func (QueryStorageConfig) RetentionDuration added in v0.20.0

func (c QueryStorageConfig) RetentionDuration() time.Duration

RetentionDuration parses Retention into a duration. A zero or negative result means "disabled — keep forever", and no sweep is scheduled.

A malformed value also disables the sweep rather than falling back to some built-in period: this sweep permanently deletes audit data, so a typo must never be interpreted as "delete more". The caller warns about it (see RetentionMisconfigured).

func (QueryStorageConfig) RetentionMisconfigured added in v0.20.0

func (c QueryStorageConfig) RetentionMisconfigured() bool

RetentionMisconfigured reports that Retention was set to something that is neither empty nor a usable positive duration — i.e. retention silently ends up disabled and the operator probably did not mean that.

type RateLimitConfig

type RateLimitConfig struct {
	// Enabled enables/disables rate limiting.
	Enabled bool `koanf:"enabled"`

	// RequestsPerMinute is the rate limit for authenticated users.
	RequestsPerMinute int `koanf:"requests_per_minute"`

	// RequestsPerMinuteAnon is the rate limit for unauthenticated requests (by IP).
	RequestsPerMinuteAnon int `koanf:"requests_per_minute_anon"`

	// Burst allows short bursts above the rate limit.
	Burst int `koanf:"burst"`
}

RateLimitConfig holds configuration for API rate limiting.

type RedirectRule

type RedirectRule struct {
	// PathPrefix is the path prefix to match (e.g., "/app").
	PathPrefix string
	// TargetHost is the target host to proxy to (e.g., "localhost:5173").
	TargetHost string
	// TargetPath is the path on the target (e.g., "/").
	TargetPath string
}

RedirectRule represents a path-based redirect for development proxying.

type ResolvedHashParams added in v0.0.1

type ResolvedHashParams struct {
	MemoryKB uint32
	Time     uint32
	Threads  uint8
}

ResolvedHashParams returns the hash parameters after applying presets. Individual settings override preset values.

type RunMode

type RunMode string

RunMode represents the application run mode.

const (
	// RunModeDefault is the default production mode.
	RunModeDefault RunMode = ""
	// RunModeTest provisions test data on startup.
	RunModeTest RunMode = "test"
	// RunModeDemo provisions demo data on startup with additional protections.
	RunModeDemo RunMode = "demo"
)

type SlackAuthConfig added in v0.4.0

type SlackAuthConfig struct {
	ClientID     string `koanf:"client_id"`
	ClientSecret string `koanf:"client_secret"`
	TeamID       string `koanf:"team_id"`
}

SlackAuthConfig holds Slack OAuth configuration.

Auto-provisioning used to live here (`auto_create_users`, `default_role`) even though every OAuth provider read it; it now lives on OAuthUsersConfig. The old env/file keys are still accepted as aliases — see applyAuthProvisioningAliases.

func (SlackAuthConfig) Enabled added in v0.4.0

func (c SlackAuthConfig) Enabled() bool

Enabled returns true if Slack OAuth is configured with both client ID and secret.

type SlackNotifyConfig added in v0.10.0

type SlackNotifyConfig struct {
	// BotToken is the Slack bot user OAuth token (xoxb-...). Empty
	// disables notifications.
	BotToken string `koanf:"bot_token"`
	// Channel is the Slack channel id or name (e.g. "#dbbat") where
	// notifications are posted. Defaults to "#dbbat".
	Channel string `koanf:"channel"`
	// SigningSecret is the Slack app signing secret used to verify inbound
	// interaction callbacks (Approve/Deny button clicks). Empty disables
	// interactivity: messages carry no buttons and the inbound endpoint is
	// not registered — outbound notifications still work.
	SigningSecret string `koanf:"signing_secret"`
	// AppToken is the Slack app-level token (xapp-...) with the
	// connections:write scope. When set together with a bot token, dbbat
	// opens an outbound Socket Mode connection and receives Approve/Deny
	// interactions over it instead of the inbound HTTP endpoint — for
	// deployments that can't accept inbound Slack traffic. Empty = no Socket
	// Mode.
	AppToken string `koanf:"app_token"`
}

SlackNotifyConfig configures outbound Slack notifications for grant request events. Distinct from SlackAuthConfig (login OIDC) so deployments can enable one without the other.

func (SlackNotifyConfig) Enabled added in v0.10.0

func (c SlackNotifyConfig) Enabled() bool

Enabled returns true when a bot token is set. Channel is enforced at startup when Enabled is true; this method only gates whether the notifier should run at all.

func (SlackNotifyConfig) Interactive added in v0.14.0

func (c SlackNotifyConfig) Interactive() bool

Interactive returns true when Approve/Deny buttons should be rendered and an inbound interaction transport should be served. A bot token (to carry the buttons on notification messages) plus at least one inbound transport — a signing secret (the HTTP endpoint) or an app-level token (Socket Mode) — is required. A signing secret or app token without a bot token is a misconfiguration caught at startup.

func (SlackNotifyConfig) SocketMode added in v0.14.0

func (c SlackNotifyConfig) SocketMode() bool

SocketMode returns true when dbbat should open an outbound Slack Socket Mode connection: both an app-level token and a bot token are set. An app token without a bot token is a misconfiguration caught at startup.

type TLSConfig added in v0.7.0

type TLSConfig struct {
	// CertFile is the path to a PEM-encoded server certificate.
	CertFile string `koanf:"cert_file"`

	// KeyFile is the path to a PEM-encoded server private key.
	KeyFile string `koanf:"key_file"`

	// Disable turns off TLS termination entirely. When true, SSL Request
	// packets from clients are refused and connections stay plaintext.
	Disable bool `koanf:"disable"`
}

TLSConfig holds TLS server-side termination settings.

When CertFile and KeyFile are both empty (and Disable is false), the proxy auto-generates a self-signed certificate at startup. This is suitable for development; production deployments should provide a real certificate.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL