Documentation
¶
Overview ¶
Package config provides configuration management for muster.
This package implements a simple configuration system that loads configuration from a single directory. The default configuration directory is ~/.config/muster, but users can specify a custom directory using the --config-path flag in commands.
Configuration Directory ¶
Configuration is loaded from a single directory containing:
- config.yaml (main configuration file)
- subdirectories for entity definitions (workflows/, capabilities/, mcpservers/)
Default location: ~/.config/muster Custom location: Specified via --config-path flag
Entity Storage System ¶
The Storage system provides generic YAML-based persistence for entity definitions including workflows, capabilities, and mcpservers. This unified storage system allows users to create, modify, and manage entities through both API operations and direct file manipulation.
## Storage Locations
Entities are stored in YAML files in type-specific subdirectories within the configuration directory:
- Default: ~/.config/muster/{entityType}/
- Custom: {customConfigPath}/{entityType}/
Where {entityType} is one of: workflows, capabilities, mcpservers
## Supported Operations
The Storage interface provides CRUD operations:
- Save: Store entity data as YAML file
- Load: Retrieve entity data from file
- Delete: Remove entity file
- List: Get all available entity names
## File Format
All entities are stored as YAML files with .yaml extension. Filenames are automatically sanitized to ensure filesystem compatibility.
## Usage Example
// Create storage instance (uses default ~/.config/muster)
storage := config.NewStorage()
// Create storage instance with custom path
storage := config.NewStorageWithPath("/custom/config/path")
// Save a workflow
workflowYAML := []byte(`name: "my-workflow"
description: "Example workflow"
steps: []`)
err := storage.Save("workflows", "my-workflow", workflowYAML)
// Load the workflow
data, err := storage.Load("workflows", "my-workflow")
// List all workflows
names, err := storage.List("workflows")
// Delete the workflow
err = storage.Delete("workflows", "my-workflow")
Configuration Structure ¶
The configuration file uses YAML format with the following main sections:
aggregator: port: 8090 # Port for the aggregator service (default: 8090) host: "localhost" # Host to bind to (default: localhost) transport: "streamable-http" # Transport to use (default: streamable-http) enabled: true # Whether the aggregator is enabled (default: true) musterPrefix: "x" # Pre-prefix for all tools (default: "x")
Configuration API ¶
The configuration can be accessed and modified at runtime through the Configuration API. The API adapter (ConfigAdapter) is located in the app package rather than here to avoid circular import dependencies, as the adapter needs to import the api package for registration, while the api package imports this package for type definitions.
Usage Examples ¶
// Load configuration from default location
cfg, err := config.LoadConfig(config.GetDefaultConfigPathOrPanic())
if err != nil {
log.Fatal(err)
}
// Access aggregator configuration
fmt.Printf("Aggregator running on %s:%d\n", cfg.Aggregator.Host, cfg.Aggregator.Port)
Index ¶
- Constants
- func GetDefaultConfigPathOrPanic() string
- type AdminConfig
- type AggregatorConfig
- type BrokerSecretRefConfig
- type BrokerTargetConfig
- type BrokerTargetType
- type DexConfig
- type GithubAppSecretKeyRef
- type GithubAppTargetConfig
- type GoogleConfig
- type MCPServerType
- type MusterConfig
- type OAuthCIMDConfig
- type OAuthConfig
- type OAuthMCPClientConfig
- type OAuthServerConfig
- type OAuthStorageConfig
- type Storage
- type TokenExchangeBrokerConfig
- type TrustedIssuerConfig
- type ValkeyConfig
Constants ¶
const ( // DefaultOAuthCallbackPath is the default path for OAuth server callbacks (Cursor -> Muster auth) DefaultOAuthCallbackPath = "/oauth/callback" // DefaultOAuthProxyCallbackPath is the default path for OAuth proxy callbacks (Muster -> Remote server auth) // This MUST be different from DefaultOAuthCallbackPath to avoid route conflicts DefaultOAuthProxyCallbackPath = "/oauth/proxy/callback" // DefaultOAuthCIMDPath is the default path for serving the Client ID Metadata Document (CIMD) DefaultOAuthCIMDPath = "/.well-known/oauth-client.json" // DefaultOAuthCIMDScopes contains the default OAuth scopes for the CIMD. // Operators can customize this via Helm values (muster.oauth.cimdScopes) to add // additional scopes needed by downstream MCP servers (e.g., Google API scopes). // The "groups" scope is included because group claims are required for RBAC // decisions in downstream services like mcp-kubernetes. Provider-level scope // filtering in mcp-oauth handles provider differences (e.g., Google's // filterGoogleScopes strips unsupported scopes like "groups" automatically). DefaultOAuthCIMDScopes = "openid profile email groups offline_access" // DefaultOAuthServerProvider is the default OAuth provider for server protection. DefaultOAuthServerProvider = "dex" // DefaultOAuthStorageType is the default storage type for OAuth tokens. DefaultOAuthStorageType = "memory" )
const ( // MCPTransportStreamableHTTP is the streamable HTTP transport. MCPTransportStreamableHTTP = "streamable-http" // MCPTransportSSE is the Server-Sent Events transport. MCPTransportSSE = "sse" // MCPTransportStdio is the standard I/O transport. MCPTransportStdio = "stdio" )
const DefaultValkeyKeyPrefix = "muster:"
DefaultValkeyKeyPrefix is the default prefix prepended to every Valkey key used by muster's backed stores when the operator does not override it via ValkeyConfig.KeyPrefix. Centralised here so the OAuth client/state stores and the aggregator session/capability stores agree on the namespace.
Variables ¶
This section is empty.
Functions ¶
func GetDefaultConfigPathOrPanic ¶
func GetDefaultConfigPathOrPanic() string
Types ¶
type AdminConfig ¶ added in v0.1.123
type AdminConfig struct {
// Enabled controls whether the admin listener is started. Default: false.
Enabled bool `yaml:"enabled,omitempty"`
// Port is the TCP port for the admin listener (default: 9999).
Port int `yaml:"port,omitempty"`
// BindAddress is the interface to bind to (default: "127.0.0.1").
// Change this at your own risk: the admin surface has no auth.
BindAddress string `yaml:"bindAddress,omitempty"`
}
AdminConfig defines the configuration for the admin web UI.
The admin surface exposes session management (list, inspect, delete) on a dedicated HTTP listener. It does not implement authentication; rely on network-level controls (loopback binding, kubectl port-forward RBAC) to gate access.
type AggregatorConfig ¶
type AggregatorConfig struct {
Port int `yaml:"port,omitempty"` // Port for the aggregator SSE endpoint (default: 8080)
Host string `yaml:"host,omitempty"` // Host to bind to (default: localhost)
Transport string `yaml:"transport,omitempty"` // Transport to use (default: streamable-http)
MusterPrefix string `yaml:"musterPrefix,omitempty"` // Pre-prefix for all tools (default: "x")
// OAuth contains all OAuth-related configuration with explicit mcpClient/server roles.
// - oauth.mcpClient: muster as OAuth client/proxy for authenticating TO remote MCP servers
// - oauth.server: muster as OAuth resource server for protecting ITSELF
OAuth OAuthConfig `yaml:"oauth,omitempty"`
// Admin exposes a read-only web UI for listing and managing sessions on a
// separate HTTP listener. Disabled by default. When enabled, the listener
// binds to AdminBindAddress:AdminPort without authentication, so it is
// only safe when bound to a loopback address or reached via port-forward.
Admin AdminConfig `yaml:"admin,omitempty"`
}
AggregatorConfig defines the configuration for the MCP aggregator service.
type BrokerSecretRefConfig ¶ added in v0.4.0
type BrokerSecretRefConfig struct {
// Name is the secret name. Required.
Name string `yaml:"name"`
// Namespace defaults to the broker's DefaultSecretNamespace (the muster
// namespace) when empty.
Namespace string `yaml:"namespace,omitempty"`
// ClientIDKey defaults to "client-id".
ClientIDKey string `yaml:"clientIdKey,omitempty"`
// ClientSecretKey defaults to "client-secret".
ClientSecretKey string `yaml:"clientSecretKey,omitempty"`
}
BrokerSecretRefConfig references a Kubernetes Secret with OAuth client credentials. Mirrors api.ClientCredentialsSecretRef (kept separate to avoid an import cycle between config and api).
type BrokerTargetConfig ¶ added in v0.4.0
type BrokerTargetConfig struct {
// Type selects the credential provider. Defaults to TargetTypeOIDCExchange
// when empty.
Type BrokerTargetType `yaml:"type,omitempty"`
// DexTokenEndpoint is the downstream Dex token endpoint URL (HTTPS).
// Example: https://dex.cluster-b.example.com/token
DexTokenEndpoint string `yaml:"dexTokenEndpoint"`
// ExpectedIssuer is the expected iss claim of the exchanged token. If
// empty, it is derived from DexTokenEndpoint (strip /token suffix).
ExpectedIssuer string `yaml:"expectedIssuer,omitempty"`
// ConnectorID is the downstream Dex OIDC connector that trusts the
// subject token's issuer.
ConnectorID string `yaml:"connectorId"`
// Scopes is the space-separated scope set requested downstream. Defaults
// to "openid profile email groups". For Kubernetes-bound audiences this
// must include the Dex cross-client scope for the apiserver's client,
// e.g. "audience:server:client_id:dex-k8s-authenticator" — without it
// the exchanged token's aud is the exchange client only, which mcp-*
// servers accept but kube-apiserver rejects.
Scopes string `yaml:"scopes,omitempty"`
// ClientCredentialsSecretRef references the Kubernetes Secret holding the
// downstream exchange client credentials (same secrets the per-MCPServer
// tokenExchange config uses; no duplication).
ClientCredentialsSecretRef *BrokerSecretRefConfig `yaml:"clientCredentialsSecretRef,omitempty"`
// GithubApp contains configuration for the github-app provider type.
// Required when Type is "github-app"; ignored otherwise.
GithubApp *GithubAppTargetConfig `yaml:"githubApp,omitempty"`
}
BrokerTargetConfig describes one downstream target of the token broker.
type BrokerTargetType ¶ added in v0.6.0
type BrokerTargetType string
BrokerTargetType identifies the credential provider for a broker target.
const ( // TargetTypeOIDCExchange selects the downstream Dex/OIDC RFC 8693 exchange // provider. It is the default when BrokerTargetConfig.Type is empty. TargetTypeOIDCExchange BrokerTargetType = "oidc-exchange" // TargetTypeGithubApp selects the GitHub App installation token provider. // The provider builds an RS256 App JWT and exchanges it for a short-lived // installation token scoped to the configured repositories and permissions. TargetTypeGithubApp BrokerTargetType = "github-app" )
type DexConfig ¶
type DexConfig struct {
// IssuerURL is the Dex OIDC issuer URL.
IssuerURL string `yaml:"issuerUrl,omitempty"`
// ClientID is the Dex OAuth client ID.
ClientID string `yaml:"clientId,omitempty"`
// ClientSecret is the Dex OAuth client secret.
// For production, use ClientSecretFile instead to avoid secrets in config files.
ClientSecret string `yaml:"clientSecret,omitempty"`
// ClientSecretFile is the path to a file containing the Dex OAuth client secret.
// This is the recommended way to provide secrets in production deployments.
// The file should contain only the secret value (no newlines at the end).
ClientSecretFile string `yaml:"clientSecretFile,omitempty"`
// ConnectorID is the optional Dex connector ID to bypass connector selection.
ConnectorID string `yaml:"connectorId,omitempty"`
// AllowPrivateIPOIDC allows the Dex issuer URL to resolve to a private or
// loopback IP address during OIDC discovery. Required when Dex is fronted by
// an internal-only load balancer (e.g. Azure internal LB, air-gapped clusters)
// where the public hostname resolves to an RFC 1918 address.
// Emits a CWE-918 startup warning when set.
AllowPrivateIPOIDC bool `yaml:"allowPrivateIPOIDC,omitempty"`
}
DexConfig holds configuration for the Dex OIDC provider.
type GithubAppSecretKeyRef ¶ added in v0.6.0
type GithubAppSecretKeyRef struct {
// Name is the Kubernetes Secret name. Required.
Name string `yaml:"name"`
// Namespace defaults to the broker's DefaultSecretNamespace when empty.
Namespace string `yaml:"namespace,omitempty"`
// Key is the data key within the Secret. Defaults to "private-key".
Key string `yaml:"key,omitempty"`
}
GithubAppSecretKeyRef references a Kubernetes Secret by name, namespace, and key within the secret data map. Used for the GitHub App RSA private key PEM.
type GithubAppTargetConfig ¶ added in v0.6.0
type GithubAppTargetConfig struct {
// AppID is the numeric GitHub App ID, used as the JWT iss claim.
AppID string `yaml:"appId"`
// InstallationID is the numeric installation ID. When empty, it is
// auto-discovered via GET /repos/{Owner}/{Repo}/installation using the App JWT.
// Either InstallationID or both Owner and Repo must be set.
InstallationID string `yaml:"installationId,omitempty"`
// Owner is the GitHub organization or user that installed the App.
// Required for auto-discovery when InstallationID is empty.
Owner string `yaml:"owner,omitempty"`
// Repo is the repository name (without owner) used for auto-discovery.
// Required for auto-discovery when InstallationID is empty.
Repo string `yaml:"repo,omitempty"`
// PrivateKeyRef references the Kubernetes Secret containing the RSA private
// key PEM. Key defaults to "private-key" when empty.
PrivateKeyRef *GithubAppSecretKeyRef `yaml:"privateKeyRef"`
// Repositories limits the installation token to specific repositories.
// When empty, the token covers all repositories the installation can access.
Repositories []string `yaml:"repositories,omitempty"`
// Permissions further restricts the installation token permissions.
// Keys are permission names (e.g. "contents", "issues"); values are
// "read" or "write". When empty, the installation's full permissions apply.
Permissions map[string]string `yaml:"permissions,omitempty"`
// BaseURL overrides the GitHub API base URL. Must use HTTPS. Defaults to
// https://api.github.com. Set for GitHub Enterprise Server or test stubs.
BaseURL string `yaml:"baseUrl,omitempty"`
}
GithubAppTargetConfig configures the github-app credential provider. The provider mints short-lived GitHub App installation tokens by building an RS256 App JWT and exchanging it at the GitHub API.
type GoogleConfig ¶
type GoogleConfig struct {
// ClientID is the Google OAuth client ID.
ClientID string `yaml:"clientId,omitempty"`
// ClientSecret is the Google OAuth client secret.
// For production, use ClientSecretFile instead to avoid secrets in config files.
ClientSecret string `yaml:"clientSecret,omitempty"`
// ClientSecretFile is the path to a file containing the Google OAuth client secret.
// This is the recommended way to provide secrets in production deployments.
ClientSecretFile string `yaml:"clientSecretFile,omitempty"`
}
GoogleConfig holds configuration for the Google OAuth provider.
type MCPServerType ¶
type MCPServerType string
MCPServerType defines the type of MCP server.
const ( MCPServerTypeStdio MCPServerType = "stdio" MCPServerTypeStreamableHTTP MCPServerType = "streamable-http" MCPServerTypeSSE MCPServerType = "sse" )
type MusterConfig ¶
type MusterConfig struct {
Aggregator AggregatorConfig `yaml:"aggregator"`
Namespace string `yaml:"namespace,omitempty"` // Namespace for MCPServer and Workflow discovery
Kubernetes bool `yaml:"kubernetes,omitempty"` // Enable Kubernetes CRD mode (uses CRDs instead of filesystem)
Events bool `yaml:"events,omitempty"` // Enable Kubernetes event emission (alpha, disabled by default)
}
MusterConfig is the top-level configuration structure for muster.
func GetDefaultConfigWithRoles ¶
func GetDefaultConfigWithRoles() MusterConfig
GetDefaultConfigWithRoles returns default configuration
func LoadConfig ¶
func LoadConfig(configPath string) (MusterConfig, error)
LoadConfig loads configuration from a single specified directory. The directory should contain config.yaml and subdirectories for other configuration types.
type OAuthCIMDConfig ¶
type OAuthCIMDConfig struct {
// Path is the path for serving the Client ID Metadata Document (default: "/.well-known/oauth-client.json").
// Muster will serve the CIMD at this path when OAuth MCP client is enabled and PublicURL is set.
Path string `yaml:"path,omitempty"`
// Scopes is the OAuth scopes to advertise in the self-hosted CIMD.
// This determines what API scopes downstream MCP servers can use when muster
// forwards tokens via SSO. Default: "openid profile email offline_access".
// Operators can add additional scopes (e.g., Google API scopes) as needed.
// Format: space-separated list of scope strings.
Scopes string `yaml:"scopes,omitempty"`
}
OAuthCIMDConfig contains Client ID Metadata Document configuration.
type OAuthConfig ¶
type OAuthConfig struct {
// MCPClient configuration for remote MCP server authentication (muster as OAuth proxy).
// When enabled, muster acts as an OAuth client proxy, handling authentication
// flows on behalf of users without exposing tokens to the Muster Agent.
MCPClient OAuthMCPClientConfig `yaml:"mcpClient,omitempty"`
// Server configuration for protecting the Muster Server itself.
// When enabled, muster acts as an OAuth Resource Server, requiring valid
// access tokens from clients (e.g., Muster Agent) to access protected endpoints.
Server OAuthServerConfig `yaml:"server,omitempty"`
}
OAuthConfig consolidates all OAuth-related configuration with explicit mcpClient/server roles. This structure clearly separates the two distinct OAuth roles that muster can play:
- MCPClient: when muster authenticates TO remote MCP servers on behalf of users
- Server: when muster protects ITSELF and requires clients to authenticate
type OAuthMCPClientConfig ¶
type OAuthMCPClientConfig struct {
// Enabled controls whether OAuth MCP client/proxy functionality is active.
// When false, remote MCP servers requiring auth will return errors.
Enabled bool `yaml:"enabled,omitempty"`
// PublicURL is the publicly accessible URL of the Muster Server.
// This is used to construct OAuth callback URLs (e.g., https://muster.example.com).
// Required when OAuth MCP client is enabled.
PublicURL string `yaml:"publicUrl,omitempty"`
// ClientID is the OAuth client identifier.
// This should be the URL of the Client ID Metadata Document (CIMD).
// If not set and PublicURL is set, the ClientID will be auto-derived as
// {PublicURL}/.well-known/oauth-client.json and muster will serve the CIMD itself.
ClientID string `yaml:"clientId,omitempty"`
// CallbackPath is the path for the OAuth proxy callback endpoint (default: "/oauth/proxy/callback").
// This is used when muster authenticates with remote MCP servers.
// NOTE: This MUST be different from the OAuth server callback (/oauth/callback) to avoid conflicts.
CallbackPath string `yaml:"callbackPath,omitempty"`
// CIMD contains Client ID Metadata Document configuration.
// Muster can serve its own CIMD when acting as an OAuth client for MCP servers.
CIMD OAuthCIMDConfig `yaml:"cimd,omitempty"`
// ExtraCAFile mirrors the process-level --extra-ca-file flag for the
// OAuth/token-exchange layer's internal-deployment heuristic. When set,
// the token-exchange HTTP client allows resolution to private IP ranges
// (e.g. in-cluster Dex via .svc.cluster.local).
// Not part of any user-facing config; populated by the serve command.
ExtraCAFile string `yaml:"-"`
}
OAuthMCPClientConfig defines the OAuth client/proxy configuration for remote MCP server authentication. When enabled, the Muster Server acts as an OAuth client proxy, handling authentication flows on behalf of users without exposing tokens to the Muster Agent.
func (*OAuthMCPClientConfig) GetCIMDPath ¶
func (c *OAuthMCPClientConfig) GetCIMDPath() string
GetCIMDPath returns the path for serving the CIMD.
func (*OAuthMCPClientConfig) GetCIMDScopes ¶
func (c *OAuthMCPClientConfig) GetCIMDScopes() string
GetCIMDScopes returns the OAuth scopes to advertise in the CIMD. If not set, returns the default scopes: "openid profile email offline_access".
func (*OAuthMCPClientConfig) GetEffectiveClientID ¶
func (c *OAuthMCPClientConfig) GetEffectiveClientID() string
GetEffectiveClientID returns the effective OAuth client ID. If ClientID is explicitly set, it is returned as-is. If ClientID is empty but PublicURL is set, returns the self-hosted CIMD URL. Otherwise, returns empty string (OAuth proxy requires publicUrl to function).
func (*OAuthMCPClientConfig) GetRedirectURI ¶
func (c *OAuthMCPClientConfig) GetRedirectURI() string
GetRedirectURI returns the full redirect URI for OAuth proxy callbacks. This is where remote MCP server IdPs will redirect after authentication.
func (*OAuthMCPClientConfig) ShouldServeCIMD ¶
func (c *OAuthMCPClientConfig) ShouldServeCIMD() bool
ShouldServeCIMD returns true if muster should serve its own CIMD. This is the case when OAuth MCP client is enabled, PublicURL is set, and ClientID is either empty or matches the auto-derived CIMD URL.
type OAuthServerConfig ¶
type OAuthServerConfig struct {
// Enabled controls whether OAuth server protection is active.
// When true, all MCP endpoints require valid OAuth tokens.
Enabled bool `yaml:"enabled,omitempty"`
// BaseURL is the publicly accessible base URL of the Muster Server.
// This is used as the OAuth issuer URL (e.g., https://muster.example.com).
// Required when OAuth server is enabled.
BaseURL string `yaml:"baseUrl,omitempty"`
// Provider specifies the OAuth provider to use: "dex" or "google".
// Default: "dex"
Provider string `yaml:"provider,omitempty"`
// Dex configuration (used when Provider is "dex")
Dex DexConfig `yaml:"dex,omitempty"`
// Google configuration (used when Provider is "google")
Google GoogleConfig `yaml:"google,omitempty"`
// Storage configuration for OAuth tokens and client registrations.
Storage OAuthStorageConfig `yaml:"storage,omitempty"`
// RegistrationToken is the token required for dynamic client registration.
// Required if AllowPublicClientRegistration is false.
// For production, use RegistrationTokenFile instead to avoid secrets in config files.
RegistrationToken string `yaml:"registrationToken,omitempty"`
// RegistrationTokenFile is the path to a file containing the registration token.
// This is the recommended way to provide secrets in production deployments.
RegistrationTokenFile string `yaml:"registrationTokenFile,omitempty"`
// AllowPublicClientRegistration allows unauthenticated dynamic client registration.
// WARNING: This can lead to DoS attacks. Default: false.
AllowPublicClientRegistration bool `yaml:"allowPublicClientRegistration,omitempty"`
// EncryptionKey is the AES-256 key for encrypting tokens at rest (32 bytes, base64-encoded).
// Required for production deployments.
// For production, use EncryptionKeyFile instead to avoid secrets in config files.
EncryptionKey string `yaml:"encryptionKey,omitempty"`
// EncryptionKeyFile is the path to a file containing the encryption key.
// This is the recommended way to provide secrets in production deployments.
EncryptionKeyFile string `yaml:"encryptionKeyFile,omitempty"`
// TrustedPublicRegistrationSchemes lists URI schemes allowed for unauthenticated
// client registration. Enables Cursor/VSCode without registration tokens.
// Example: ["cursor", "vscode"]
TrustedPublicRegistrationSchemes []string `yaml:"trustedPublicRegistrationSchemes,omitempty"`
// TrustedPublicRegistrationRedirectURIs lists fully-qualified HTTPS redirect URIs
// allowed to register without a RegistrationAccessToken. Matching is exact after
// RFC 3986 normalization. Enables SaaS MCP clients that cannot send a DCR token.
// Example: ["https://claude.ai/api/mcp/auth_callback"]
TrustedPublicRegistrationRedirectURIs []string `yaml:"trustedPublicRegistrationRedirectURIs,omitempty"`
// EnableCIMD enables Client ID Metadata Documents per MCP 2025-11-25 spec.
// Default: true
EnableCIMD bool `yaml:"enableCIMD,omitempty"`
// AllowLocalhostRedirectURIs allows http://localhost and http://127.0.0.1 redirect URIs.
// Required for native apps (like muster agent) per RFC 8252 Section 7.3.
// Default: true (native app support enabled by default)
AllowLocalhostRedirectURIs bool `yaml:"allowLocalhostRedirectURIs,omitempty"`
// SessionDuration is the maximum session duration before re-authentication
// is required. This sets the server-side refresh token TTL.
// Default: 720h (30 days), aligned with Dex's absoluteLifetime.
// Format: Go duration string (e.g., "720h", "30d" is NOT valid, use hours).
SessionDuration string `yaml:"sessionDuration,omitempty"`
// AllowedOrigins is a comma-separated list of allowed CORS origins for
// browser-based MCP clients. Empty disables CORS (default, secure).
AllowedOrigins string `yaml:"allowedOrigins,omitempty"`
// TrustedAudiences lists additional OAuth client IDs (audiences) whose
// JWT ID tokens are accepted directly as bearer tokens, without requiring
// the client to complete muster's own OAuth flow first. This enables
// authenticating muster with tokens generated directly against Dex (e.g.
// by dex-k8s-authenticator or another Dex client), as long as the token's
// `aud` claim matches one of these values and its signature validates
// against the provider's JWKS.
//
// SECURITY: only list client IDs you fully trust. Any JWT signed by the
// configured OIDC provider and carrying one of these audiences is treated
// as a valid muster bearer token.
TrustedAudiences []string `yaml:"trustedAudiences,omitempty"`
// TrustedIssuers registers external OIDC issuers for RFC 8693 token exchange.
// Tokens are accepted as subject_tokens of type id_token, access_token, or jwt.
TrustedIssuers []TrustedIssuerConfig `yaml:"trustedIssuers,omitempty"`
// TrustedProxyCIDRs lists CIDRs from which X-Forwarded-Proto and
// X-Forwarded-Host headers are trusted for DPoP htu URL reconstruction.
// Required when muster runs behind a reverse proxy that terminates TLS.
TrustedProxyCIDRs []string `yaml:"trustedProxyCIDRs,omitempty"`
// EnableJWTMode issues signed RFC 9068 JWTs as access tokens instead of
// opaque random strings. Required when downstream services (e.g. agentgateway)
// need to validate tokens locally without calling the introspection endpoint.
// JWTSigningKeyFile must be set when this is true.
EnableJWTMode bool `yaml:"enableJWTMode,omitempty"`
// JWTSigningKeyFile is the path to a PEM-encoded private key used to sign
// access tokens in JWT mode. Supported formats: EC PRIVATE KEY (P-256, ES256),
// RSA PRIVATE KEY / PRIVATE KEY (PKCS#8, RS256). kid is derived from the
// RFC 7638 JWK thumbprint of the public key. Required when EnableJWTMode is true.
JWTSigningKeyFile string `yaml:"jwtSigningKeyFile,omitempty"`
// ResourceIdentifier is the canonical URI that identifies this muster instance
// as an RFC 8707 resource server. When set, access tokens carry this value in
// their aud claim and tokens bound to a different resource are rejected, preventing
// replay across resource servers sharing the same IdP.
// If empty the library defaults to BaseURL (the issuer URL).
// Example: "https://muster.example.com/mcp"
ResourceIdentifier string `yaml:"resourceIdentifier,omitempty"`
// TokenExchangeBroker exposes muster's RFC 8693 token exchange to external
// confidential clients: a broker client POSTs a token-exchange request with
// an `audience` parameter to /oauth/token and receives a token minted by
// the audience's downstream Dex (not a muster-issued JWT). Subject tokens
// are validated against TrustedIssuers; the per-client allowlist below
// gates which audiences each client may request.
TokenExchangeBroker TokenExchangeBrokerConfig `yaml:"tokenExchangeBroker,omitempty"`
}
OAuthServerConfig defines the OAuth server configuration for protecting the Muster Server. When enabled, the Muster Server acts as an OAuth Resource Server, requiring valid access tokens from clients (e.g., Muster Agent) to access protected endpoints. This implements ADR 005 (OAuth Protection for Muster Server).
type OAuthStorageConfig ¶
type OAuthStorageConfig struct {
// Type is the storage backend type: "memory" or "valkey" (default: "memory").
Type string `yaml:"type,omitempty"`
// Valkey configuration (used when Type is "valkey").
Valkey ValkeyConfig `yaml:"valkey,omitempty"`
}
OAuthStorageConfig holds configuration for OAuth token storage backend.
type Storage ¶
type Storage struct {
// contains filtered or unexported fields
}
Storage provides generic storage functionality for dynamic entities using a single configuration directory approach
func NewStorageWithPath ¶
NewStorageWithPath creates a new Storage instance with a custom config path
type TokenExchangeBrokerConfig ¶ added in v0.4.0
type TokenExchangeBrokerConfig struct {
// ClientAudiences maps an authenticated confidential broker client ID to
// the audiences it may request. Requests for audiences outside the
// client's list are rejected with invalid_target. Maps to mcp-oauth's
// Config.TokenExchangeClientAudiences.
ClientAudiences map[string][]string `yaml:"clientAudiences,omitempty"`
// Targets maps an RFC 8693 audience name (e.g. a management cluster name)
// to the downstream credential provider target.
Targets map[string]BrokerTargetConfig `yaml:"targets,omitempty"`
// WorkloadAudiences maps a workload subject (the sub claim of a validated
// SA token, e.g. system:serviceaccount:<ns>:<name>; globs supported) to
// the audiences it may request. Enables workload-authenticated token
// exchange (no confidential-client credentials required). Maps to
// mcp-oauth's Config.WorkloadAudiences; enforcement is performed upstream
// by mcp-oauth before the provider is invoked.
WorkloadAudiences map[string][]string `yaml:"workloadAudiences,omitempty"`
// AllowPrivateIP allows downstream token endpoints to resolve to private
// or loopback IP addresses. WARNING: reduces SSRF protection; only enable
// for internal/VPN deployments where the target Dex is reachable via a
// private address.
AllowPrivateIP bool `yaml:"allowPrivateIP,omitempty"`
// DefaultSecretNamespace is the namespace used for target credential
// secret refs that do not set an explicit namespace. Populated from the
// muster namespace by the serve command; not user-facing config.
DefaultSecretNamespace string `yaml:"-"`
}
TokenExchangeBrokerConfig configures brokered RFC 8693 token exchange (muster as a shared token broker for external clients).
func (TokenExchangeBrokerConfig) Enabled ¶ added in v0.4.0
func (c TokenExchangeBrokerConfig) Enabled() bool
Enabled reports whether brokered token exchange is configured.
type TrustedIssuerConfig ¶ added in v0.1.210
type TrustedIssuerConfig struct {
// Issuer is the expected iss claim value.
Issuer string `yaml:"issuer,omitempty"`
// JwksURL is the JWKS endpoint. Independent of Issuer.
JwksURL string `yaml:"jwksUrl,omitempty"`
// AllowedAudiences lists accepted aud values. Empty accepts any audience.
AllowedAudiences []string `yaml:"allowedAudiences,omitempty"`
// AllowedScopes caps scopes for tokens from this issuer. Nil means no restriction.
AllowedScopes []string `yaml:"allowedScopes,omitempty"`
// AllowedClaims requires each named claim to match its pattern. Keys are JWT
// claim names; values are exact strings or globs ('*' spans any chars incl. '/',
// '?' one char). Absent or non-string claims are rejected. Empty means no
// restriction. Use to express K8s SA trust via sub, e.g.
// "system:serviceaccount:<namespace>:*".
AllowedClaims map[string]string `yaml:"allowedClaims,omitempty"`
// AllowPrivateIPJWKS allows the JwksURL to resolve to a private or loopback
// address. Required for in-cluster Kubernetes SA trust where the JWKS endpoint
// is https://kubernetes.default.svc/openid/v1/jwks. Emits a startup warning
// when set (mcp-oauth dev-override flag). Default: false.
AllowPrivateIPJWKS bool `yaml:"allowPrivateIPJWKS,omitempty"`
// AcceptedTypHeaders lists the JWT typ header values accepted for Bearer
// tokens from this issuer. Empty keeps the RFC 9068 default ("at+jwt").
// Kubernetes ServiceAccount tokens carry no typ header; use [""] to
// accept them.
AcceptedTypHeaders []string `yaml:"acceptedTypHeaders,omitempty"`
}
TrustedIssuerConfig mirrors server.TrustedIssuer.
type ValkeyConfig ¶
type ValkeyConfig struct {
// URL is the Valkey server address (e.g., "valkey.namespace.svc:6379").
URL string `yaml:"url,omitempty"`
// Password is the optional password for Valkey authentication.
// For production, use PasswordFile instead to avoid secrets in config files.
Password string `yaml:"password,omitempty"`
// PasswordFile is the path to a file containing the Valkey password.
// This is the recommended way to provide secrets in production deployments.
PasswordFile string `yaml:"passwordFile,omitempty"`
// TLSEnabled enables TLS for Valkey connections.
TLSEnabled bool `yaml:"tlsEnabled,omitempty"`
// TLSServerName overrides the server name used for TLS certificate verification.
// Use this when the Valkey server certificate CN/SAN differs from the connection address.
TLSServerName string `yaml:"tlsServerName,omitempty"`
// KeyPrefix is the prefix for all Valkey keys (default: "muster:").
KeyPrefix string `yaml:"keyPrefix,omitempty"`
// DB is the Valkey database number (default: 0).
DB int `yaml:"db,omitempty"`
}
ValkeyConfig holds configuration for Valkey storage backend.