Documentation
¶
Index ¶
- Constants
- func SetConfigPath(path string)
- func SetConfigPaths(paths ...string)
- func ValidateAuthSkipPath(path string) error
- type APIKey
- type Auth
- type Authorization
- type CORS
- type ClaimMappings
- type Database
- type Deployments
- type EventHub
- type FileBased
- type FileBasedOrg
- type FileBasedUser
- type FileBasedUsers
- type Gateway
- type HTTPListener
- type HTTPSListener
- type IDP
- type JWT
- type Logging
- type Security
- type Server
- type ServerListeners
- type Timeouts
- type WebSocket
- type Webhook
Constants ¶
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.
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
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
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
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 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 ¶
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.