config

package
v0.14.0 Latest Latest
Warning

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

Go to latest
Published: Jul 30, 2026 License: Apache-2.0 Imports: 20 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// AuthModeInternalToken verifies asymmetrically-signed JWTs (RS256) minted by
	// another trusted platform component holding the matching RSA private key.
	// Verification uses the RSA public key in auth.jwt.public_key_file; symmetric
	// (HMAC) and unsigned ("none") tokens are rejected.
	AuthModeInternalToken = "internal_token"
	// AuthModeFile is AuthModeInternalToken plus local username/password login: the
	// login endpoint authenticates users from auth.file and issues RS256 JWTs signed
	// with the RSA private key in auth.jwt.private_key_file, verified with the matching
	// auth.jwt.public_key_file.
	AuthModeFile = "file"
	// AuthModeIDP validates tokens against an external IDP's JWKS (auth.idp).
	AuthModeIDP = "idp"
)

Authentication modes selectable via auth.mode. Exactly one mode is active; modeling the choice as a single discriminator (rather than per-mode enabled flags) makes conflicting configurations inexpressible.

View Source
const (
	// AuthzModeScope authorizes using the JWT scope claim directly.
	AuthzModeScope = "scope"
	// AuthzModeRole authorizes by expanding the token's roles claim into
	// platform scopes via the auth.authorization.role_to_scope_mapping file.
	AuthzModeRole = "role"
)

Authorization modes selectable via auth.authorization.mode.

Variables

This section is empty.

Functions

func SetConfigPath

func SetConfigPath(path string)

SetConfigPath configures a single config.toml path. Retained for backward compatibility; SetConfigPaths is the repeatable form. Must be called before the first GetConfig() if a config file is used.

func SetConfigPaths added in v0.14.0

func SetConfigPaths(paths ...string)

SetConfigPaths configures one or more config.toml paths, merged in order with last-wins precedence. Must be called before the first GetConfig() if config files are used.

func ValidateAuthSkipPath added in v0.14.0

func ValidateAuthSkipPath(path string) error

ValidateAuthSkipPath rejects a skip-path entry that would widen the auth bypass beyond the narrow, specific prefix a skip path is meant to be. Skip-path matching is a segment-boundary prefix match, so "" or "/" would disable authentication and scope enforcement for every route on the server (GO-AUTH-004/GO-AUTH-011) — that must fail startup, not silently pass every request through. It is applied to both config-sourced entries and the prefixes plugins contribute, so neither source can drift from the other.

Types

type APIKey

type APIKey struct {
	HashingAlgorithms []string `koanf:"hashing_algorithms"`
}

APIKey holds API key-specific configuration.

type Auth

type Auth struct {
	// Mode selects the active authentication mode: "internal_token", "file", or "idp".
	Mode string `koanf:"mode"`
	// Authorization holds every authorization setting — whether it is enforced,
	// how (scope or role), and the role-to-scope mapping file. It is deliberately
	// its own section rather than living under [auth.idp]: authorization applies
	// in every auth mode, because a token minted by an enterprise IDP carries the
	// same roles claim whether the platform verifies it via JWKS or with a local
	// public key.
	Authorization Authorization `koanf:"authorization"`
	// SkipPaths are the path prefixes that bypass authentication and scope
	// enforcement — health/metrics probes, the login endpoint, and the internal
	// routes authenticated by a gateway token instead of a user JWT. It is not
	// operator-configurable (koanf:"-"): the list is a property of the product's
	// own routing, and a wrong entry here is an auth bypass, so it comes from
	// DefaultConfig plus the prefixes plugins declare. Operators turn
	// authorization on and off with auth.authorization.enabled instead.
	SkipPaths []string `koanf:"-"`
	IDP       IDP      `koanf:"idp"`
	// JWT is shared by two modes — "internal_token" mode only verifies
	// tokens minted elsewhere with the public key, "file" mode both signs (with
	// the private key) and verifies (with the public key) using the RSA key pair.
	JWT  JWT       `koanf:"jwt"`
	File FileBased `koanf:"file"`
	// ClaimMappings names the JWT claims that carry each identity field. It is
	// shared by all three auth modes: "idp" reads incoming claims by these
	// names, "file" mode's login endpoint signs tokens using these names, and
	// "internal_token" mode reads tokens minted elsewhere by these names too
	// — one mapping, so issuance and validation can never drift apart. Every
	// field accepts either a flat top-level claim name ("org_id") or a
	// dot-separated path into a nested claim ("realm_access.org_id") — see
	// resolveClaimPath in internal/middleware/auth.go.
	ClaimMappings ClaimMappings `koanf:"claim_mappings"`
}

Auth groups all authentication-related configuration.

type Authorization added in v0.14.0

type Authorization struct {
	// Enabled enforces per-endpoint OAuth2 scopes on validated tokens.
	// Disable only to temporarily bypass authorization during development.
	Enabled bool `koanf:"enabled"`
	// Mode selects how authorization is enforced: "scope" (default) or "role".
	Mode string `koanf:"mode"`
	// RoleToScopeMapping is the path to a YAML file mapping IDP roles to platform
	// scopes. Required in "role" mode (validateAuthorizationConfig rejects an
	// empty path there); unused in "scope" mode.
	RoleToScopeMapping string `koanf:"role_to_scope_mapping"`
}

Authorization groups all authorization configuration. It applies in every auth mode — authentication (how a token is verified) and authorization (what a verified token may do) are configured independently, mirroring the separation Kubernetes draws between its authentication and authorization configs and Envoy draws between JWT providers and rules.

type CORS

type CORS struct {
	// AllowedOrigins lists the exact origins permitted to make credentialed
	// cross-origin requests. Must never be ["*"] — wildcard
	// origins cannot be combined with credentialed requests.
	AllowedOrigins []string `koanf:"allowed_origins"`
}

CORS holds cross-origin resource sharing configuration.

type ClaimMappings added in v0.13.0

type ClaimMappings struct {
	Organization string `koanf:"organization"`
	OrgName      string `koanf:"org_name"`
	OrgHandle    string `koanf:"org_handle"`
	UserID       string `koanf:"user_id"`
	Username     string `koanf:"username"`
	Email        string `koanf:"email"`
	Scope        string `koanf:"scope"`
	Roles        string `koanf:"roles"`
}

ClaimMappings holds JWT claim name mappings, shared across all auth modes.

type Database

type Database struct {
	// Driver supports: sqlite3, postgres/postgresql/pgx, sqlserver/mssql.
	Driver string `koanf:"driver"`
	// Path is the file path for SQLite databases.
	Path     string `koanf:"path"`
	Host     string `koanf:"host"`
	Port     int    `koanf:"port"`
	Name     string `koanf:"name"`
	User     string `koanf:"user"`
	Password string `koanf:"password"`
	SSLMode  string `koanf:"ssl_mode"`
	// SSLRootCert is the CA certificate file path used to verify the server's
	// certificate. Required when SSLMode is "verify-ca" or "verify-full".
	SSLRootCert string `koanf:"ssl_root_cert"`
	// SSLCert and SSLKey are the client certificate/key pair used for mutual
	// TLS. Optional; both must be set together or not at all.
	SSLCert         string `koanf:"ssl_cert"`
	SSLKey          string `koanf:"ssl_key"`
	MaxOpenConns    int    `koanf:"max_open_conns"`
	MaxIdleConns    int    `koanf:"max_idle_conns"`
	ConnMaxLifetime int    `koanf:"conn_max_lifetime"`
}

Database holds database-specific configuration.

type Deployments

type Deployments struct {
	MaxPerAPIGateway          int  `koanf:"max_per_api_gateway"`
	TransitionalStatusEnabled bool `koanf:"transitional_status_enabled"`
	TimeoutEnabled            bool `koanf:"timeout_enabled"`
	TimeoutInterval           int  `koanf:"timeout_interval"`
	TimeoutDuration           int  `koanf:"timeout_duration"`
}

Deployments holds deployment-specific configuration.

type EventHub

type EventHub struct {
	PollInterval    time.Duration `koanf:"poll_interval"`
	CleanupInterval time.Duration `koanf:"cleanup_interval"`
	RetentionPeriod time.Duration `koanf:"retention_period"`
}

EventHub holds EventHub-specific configuration for multi-replica HA event delivery.

type FileBased

type FileBased struct {
	Organization FileBasedOrg   `koanf:"organization"`
	Users        FileBasedUsers `koanf:"users"`
}

FileBased holds configuration for local username/password authentication. Active when Auth.Mode is AuthModeFile.

type FileBasedOrg

type FileBasedOrg struct {
	// ID is the organization handle (URL-safe slug), e.g. "default".
	ID string `koanf:"id"`

	// DisplayName is the human-readable name of the organization.
	DisplayName string `koanf:"display_name"`

	// Region is the deployment region for the organization.
	Region string `koanf:"region"`

	// UUID is the platform organization UUID. File-based auth has no external
	// IDP, so this value is stored as idp_organization_ref_uuid and emitted as
	// the `organization` claim in issued tokens.
	UUID string `koanf:"uuid"`
}

FileBasedOrg holds the single organization used in file-based auth mode.

type FileBasedUser

type FileBasedUser struct {
	Username     string `json:"username"     koanf:"username"`
	PasswordHash string `json:"password_hash" koanf:"password_hash"`
	// Roles names one or more of the roles in the
	// auth.authorization.role_to_scope_mapping file and is the user's entire
	// grant: the login endpoint expands them into the scope claim of the token it
	// issues, unioning what each role grants — most-permissive wins, the same way
	// a token carrying several roles is expanded in role authorization mode. It is
	// the only way to grant a file-mode user, so a user's privileges are expressed
	// exactly the way an IDP expresses them — as roles — and changing what a role
	// grants is a single edit to the mapping file rather than a per-user scope
	// string to keep in sync.
	Roles []string `json:"roles" koanf:"roles"`
}

FileBasedUser represents a built-in user for file-based auth mode.

type FileBasedUsers

type FileBasedUsers []FileBasedUser

FileBasedUsers is a slice of FileBasedUser that can be decoded from a JSON string (env var) or from a TOML array of tables ([[auth.file.users]]).

type Gateway

type Gateway struct {
	EnableVersionVerification           bool `koanf:"enable_version_verification"`
	EnableFunctionalityTypeVerification bool `koanf:"enable_functionality_type_verification"`
}

Gateway holds gateway-related configuration.

type HTTPListener added in v0.12.0

type HTTPListener struct {
	Enabled bool `koanf:"enabled"`
	Port    int  `koanf:"port"`
}

HTTPListener configures the plain-HTTP listener. Enable it only when a trusted upstream (ingress, service-mesh sidecar) terminates TLS, or for internal cluster traffic; never expose it directly to untrusted networks.

type HTTPSListener added in v0.12.0

type HTTPSListener struct {
	Enabled  bool   `koanf:"enabled"`
	Port     int    `koanf:"port"`
	CertFile string `koanf:"cert_file"`
	KeyFile  string `koanf:"key_file"`
}

HTTPSListener configures the TLS listener. CertFile and KeyFile must point at a certificate pair when Enabled is true; there is no self-signed fallback.

type IDP

type IDP struct {
	Name     string   `koanf:"name"`
	JWKSUrl  string   `koanf:"jwks_url"`
	Issuer   []string `koanf:"issuer"`
	Audience []string `koanf:"audience"`
}

IDP holds configuration for JWKS-based identity providers. Active when Auth.Mode is AuthModeIDP.

type JWT

type JWT struct {
	// PublicKeyFile is the path to a mounted PEM-encoded RSA public key file,
	// used to verify token signatures. Required in both "internal_token" and
	// "file" modes. The key is read from disk at the point of use rather than
	// being interpolated into config at load time, so the PEM content is never
	// held in the config struct.
	PublicKeyFile string `koanf:"public_key_file"`
	// PrivateKeyFile is the path to a mounted PEM-encoded RSA private key file,
	// used to sign tokens. Required only in "file" mode, whose login endpoint
	// mints tokens; unused (and not required) in verify-only "internal_token"
	// mode. Read from disk at the point of use, never cached as content.
	PrivateKeyFile string        `koanf:"private_key_file"`
	Issuer         string        `koanf:"issuer"`
	TokenTTL       time.Duration `koanf:"token_ttl"`
}

JWT holds configuration for local asymmetric (RS256) JWT authentication. Active when Auth.Mode is AuthModeInternalToken (verify-only; tokens minted by another platform component) or AuthModeFile (file mode also issues these tokens). Signature validation is always on and strictly asymmetric — symmetric (HMAC) and unsigned ("none") algorithms are rejected.

TODO(pqc): migrate — RS256 is quantum-vulnerable. Move to an ML-DSA (FIPS 204) signature once a Go JWT library exposes it. See post-quantum-cryptography.md.

func (*JWT) LoadPrivateKey added in v0.13.0

func (j *JWT) LoadPrivateKey() (*rsa.PrivateKey, error)

LoadPrivateKey reads and parses the PEM-encoded RSA private key from PrivateKeyFile. The file is read fresh on every call rather than cached, so PrivateKeyFile is a mounted-file path, never inlined PEM content.

func (*JWT) LoadPublicKey added in v0.13.0

func (j *JWT) LoadPublicKey() (*rsa.PublicKey, error)

LoadPublicKey reads and parses the PEM-encoded RSA public key from PublicKeyFile. The file is read fresh on every call rather than cached, so PublicKeyFile is a mounted-file path, never inlined PEM content.

type Logging added in v0.13.0

type Logging struct {
	Level  string `koanf:"level"`
	Format string `koanf:"format"`
}

Logging holds logging configuration.

type Security added in v0.13.0

type Security struct {
	// EncryptionKey is the single 32-byte key used for ALL at-rest encryption
	// (secrets, subscription tokens, WebSub HMAC secrets).
	EncryptionKey string `koanf:"encryption_key"`
	APIKey        APIKey `koanf:"api_key"`
}

Security holds cryptographic/secret-handling configuration.

type Server

type Server struct {
	Logging Logging `koanf:"logging"`

	DBSchemaPath               string `koanf:"db_schema_path"`
	OpenAPISpecPath            string `koanf:"openapi_spec_path"`
	LLMTemplateDefinitionsPath string `koanf:"llm_template_definitions_path"`
	OpenAPISpecMaxFetchBytes   int64  `koanf:"openapi_spec_max_fetch_bytes"`

	Database    Database        `koanf:"database"`
	Auth        Auth            `koanf:"auth"`
	Deployments Deployments     `koanf:"deployments"`
	Listeners   ServerListeners `koanf:"server"`
	Security    Security        `koanf:"security"`
	Gateway     Gateway         `koanf:"gateway"`
	EventHub    EventHub        `koanf:"event_hub"`
	Webhook     Webhook         `koanf:"webhook"`
}

Server holds the configuration parameters for the application.

func GetConfig

func GetConfig() *Server

GetConfig returns the singleton config instance, loading it on first call.

func LoadConfig

func LoadConfig(configPaths ...string) (*Server, error)

LoadConfig loads configuration with priority: config files > defaults.

configPaths is repeatable: files are merged in the order given with last-wins precedence (a key set in a later file overrides the same key from an earlier file). Merge semantics follow koanf — nested tables (maps) deep-merge, while list/array values are replaced wholesale, not appended. A field may be overridden across files with a different representation — e.g. a numeric value in the base and an {{ env }} token (a string) in an overlay — and still resolve, because types are only checked after interpolation by the weakly-typed unmarshal.

Zero paths is permitted (the embeddable library API and callers supplying an already-built config via the platform façade rely on this) — with no files, only the {{ env }}-resolved defaults apply. The `platform-api` binary itself requires at least one -config file (enforced in cmd/main.go), so it never silently boots on defaults. Any path that is given must exist and parse.

type ServerListeners added in v0.13.0

type ServerListeners struct {
	HTTP      HTTPListener  `koanf:"http"`
	HTTPS     HTTPSListener `koanf:"https"`
	Timeouts  Timeouts      `koanf:"timeouts"`
	CORS      CORS          `koanf:"cors"`
	WebSocket WebSocket     `koanf:"websocket"`
}

ServerListeners models the [server] section: the two independent HTTP listeners (each enabled independently and bound to its own port, so a deployment can serve plain HTTP internally, HTTPS externally, or both at once to migrate clients between them without downtime), plus the cross-cutting settings — timeouts, CORS, WebSocket — that apply to whichever listener(s) are serving requests.

type Timeouts added in v0.12.0

type Timeouts struct {
	// ReadHeader bounds how long a client may take to send request headers.
	ReadHeader time.Duration `koanf:"read_header"`
	// Read bounds the whole request read, including bodies such as uploaded API
	// definitions. Must be >= ReadHeader when both are set.
	Read time.Duration `koanf:"read"`
	// Write bounds handler execution plus the response write. Keep it generous:
	// some handlers proxy slow upstreams (LLM completions, deployments).
	Write time.Duration `koanf:"write"`
	// Idle bounds how long a keep-alive connection may sit unused between
	// requests.
	Idle time.Duration `koanf:"idle"`
}

Timeouts bounds the lifetime of a connection on both listeners, so a slow or idle peer cannot hold one open indefinitely (Slowloris). The values apply to the plain-HTTP and HTTPS listeners alike, since both serve the same handler.

A zero value disables the corresponding timeout, matching net/http semantics. Disabling Read or ReadHeader removes the Slowloris protection — only do so behind a proxy that already enforces its own bounds.

WebSocket routes are unaffected: gorilla/websocket clears the hijacked connection's deadlines during the upgrade, so long-lived sockets outlive these.

type WebSocket

type WebSocket struct {
	MaxConnections     int  `koanf:"max_connections"`
	ConnectionTimeout  int  `koanf:"connection_timeout"`
	RateLimitPerMin    int  `koanf:"rate_limit_per_min"`
	MetricsLogEnabled  bool `koanf:"metrics_log_enabled"`
	MetricsLogInterval int  `koanf:"metrics_log_interval"`
}

WebSocket holds WebSocket-specific configuration.

type Webhook

type Webhook struct {
	// Enabled controls whether the webhook endpoint is registered.
	Enabled bool `koanf:"enabled"`
	// Secret is the shared secret with the API Portal. It serves two purposes: verifying
	// the HMAC-SHA256 request signature, and deriving (via HKDF-SHA3-256) the AES key that decrypts
	// encrypted payload fields such as an API key secret.
	Secret string `koanf:"secret"`
	// SignatureTolerance bounds how old a signed request may be (replay protection).
	SignatureTolerance time.Duration `koanf:"signature_tolerance"`
	// MaxBodySize caps the request body size in bytes.
	MaxBodySize int64 `koanf:"max_body_size"`
	// SignatureHeader is the header carrying the "t=...,v1=..." signature.
	SignatureHeader string `koanf:"signature_header"`
}

Webhook holds configuration for the control-plane webhook receiver. The API Portal delivers signed events (API key / subscription changes) to this endpoint. See docs-local/platform-api-webhook.md.

Jump to

Keyboard shortcuts

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