diff --git a/.github/upstream-projects.yaml b/.github/upstream-projects.yaml index 7182c2b6..dfae225b 100644 --- a/.github/upstream-projects.yaml +++ b/.github/upstream-projects.yaml @@ -44,7 +44,7 @@ projects: - id: toolhive repo: stacklok/toolhive - version: v0.45.0 + version: v0.46.0 # toolhive is a monorepo covering the CLI, the Kubernetes # operator, and the vMCP gateway. It also introduces cross- # cutting features that land in concepts/, integrations/, diff --git a/docs/toolhive/guides-k8s/embedded-auth-server-k8s.mdx b/docs/toolhive/guides-k8s/embedded-auth-server-k8s.mdx index 04c72a30..5a0cddd9 100644 --- a/docs/toolhive/guides-k8s/embedded-auth-server-k8s.mdx +++ b/docs/toolhive/guides-k8s/embedded-auth-server-k8s.mdx @@ -439,10 +439,17 @@ The embedded AS enforces the following rules on fetched CIMD documents: - The `client_id` field inside the document must exactly match the URL it was fetched from. - `redirect_uris` must be present and pass strict validation. -- Symmetric shared-secret `token_endpoint_auth_method` values are forbidden. -- `grant_types` must include `authorization_code` and be a subset of - `[authorization_code, refresh_token]`. -- `response_types` must be a subset of `[code]`. +- `token_endpoint_auth_method` must be `none` or omitted. When it names any + other value (for example, `private_key_jwt`), the document must also publish a + `token_endpoint_auth_methods_supported` list containing `none` (per OpenID + Connect RP Metadata Choices 1.0), and the server negotiates down to `none`. + Symmetric shared-secret methods (`client_secret_post`, `client_secret_basic`, + `client_secret_jwt`) are always rejected, even alongside a supported-methods + list. +- `grant_types` must include `authorization_code`. Unsupported entries in + `grant_types` and `response_types` are filtered out rather than rejected; the + document is only rejected when the filtered intersection lacks the + `authorization_code` grant or the `code` response type. - Declared scopes must be a subset of the AS's configured `scopes_supported` list (when set). @@ -656,6 +663,62 @@ For OAuth 2.0 servers that return identity in the token response itself, see ::: +### Trust a private CA for the upstream provider + +If the upstream identity provider serves its endpoints with a certificate signed +by an internal CA (for example, an in-cluster Keycloak or a corporate ADFS +behind private PKI), the embedded authorization server can't complete discovery, +token, user-info, or DCR requests to it until it trusts that CA. Set +`caBundleRef` on the upstream's `oidcConfig` or `oauth2Config` to point at a +ConfigMap containing the PEM-encoded CA bundle. The operator projects it +read-only into the proxy pod and the auth server adds it to the system trust +roots for connections to this upstream only. The bundle augments the system +roots; it doesn't restrict trust to this CA or disable public roots. + +First, create a ConfigMap with the CA certificate. The ConfigMap must live in +the same namespace as the `MCPExternalAuthConfig`: + +```bash +kubectl create configmap upstream-private-ca \ + --from-file=ca.crt=/path/to/upstream-ca.crt \ + -n toolhive-system +``` + +Then reference it from the upstream provider's `oidcConfig`: + +```yaml title="MCPExternalAuthConfig: OIDC upstream with a private CA" +spec: + type: embeddedAuthServer + embeddedAuthServer: + issuer: 'https://mcp.example.com' + upstreamProviders: + - name: corporate-idp + type: oidc + oidcConfig: + issuerUrl: 'https://idp.internal.example.com' + clientId: 'toolhive-client' + # highlight-start + caBundleRef: + configMapRef: + name: upstream-private-ca + key: ca.crt + # highlight-end +``` + +Use the same pattern under `oauth2Config` when the upstream is a pure OAuth 2.0 +provider. Set `key` to the ConfigMap key holding the bundle, commonly `ca.crt`. +The operator watches the ConfigMap and rolls the proxy pod when the bundle +changes or the reference is removed, so rotating the CA doesn't require a manual +restart. When the bundle content is invalid PEM, the operator surfaces a +terminal condition on the resource that references this `MCPExternalAuthConfig` +(for example, the `MCPServer` or `VirtualMCPServer`) rather than retrying +reconciliation. + +`caBundleRef` on the upstream provider is independent of `caBundleRef` on the +`MCPOIDCConfig` that validates incoming JWTs (see +[Use a custom CA certificate for the OIDC issuer](./auth-k8s.mdx#use-a-custom-ca-certificate-for-the-oidc-issuer)): +the two references configure trust for different network hops. + ### Use dynamic client registration with an upstream provider Some OAuth 2.0 providers register clients dynamically instead of requiring you @@ -1075,11 +1138,14 @@ consumer's mirrored condition clears on the next reconcile. - The `client_id` field inside the fetched document must exactly match the URL used to fetch it. -- Documents must not declare `token_endpoint_auth_method` values that use a - symmetric shared secret (`client_secret_post`, `client_secret_basic`, - `client_secret_jwt`). -- `grant_types` must include `authorization_code`. `response_types` must only - contain `code`. +- `token_endpoint_auth_method` must be `none` or omitted. When it names any + other value (for example, `private_key_jwt`), the document must also publish a + `token_endpoint_auth_methods_supported` list containing `none` so the server + can negotiate down to `none`. Symmetric shared-secret methods + (`client_secret_post`, `client_secret_basic`, `client_secret_jwt`) are always + rejected with `invalid_client`. +- After unsupported entries are filtered out, `grant_types` must still include + `authorization_code` and `response_types` must still include `code`. - `redirect_uris` must be present and valid. diff --git a/docs/toolhive/guides-vmcp/embedded-auth-server-vmcp.mdx b/docs/toolhive/guides-vmcp/embedded-auth-server-vmcp.mdx index 1a27d490..8d5135c3 100644 --- a/docs/toolhive/guides-vmcp/embedded-auth-server-vmcp.mdx +++ b/docs/toolhive/guides-vmcp/embedded-auth-server-vmcp.mdx @@ -183,6 +183,10 @@ and [token exchange](#exchange-a-stored-upstream-token-token-exchange) outgoing strategies reference to map backends to providers. For details on configuring OIDC vs OAuth 2.0 upstream providers, see [Using an OAuth 2.0 upstream provider](../guides-k8s/embedded-auth-server-k8s.mdx#using-an-oauth-20-upstream-provider). +When an upstream serves its endpoints with a certificate signed by an internal +CA, set `caBundleRef` on the upstream's `oidcConfig` or `oauth2Config` to point +at a ConfigMap containing the PEM bundle; see +[Trust a private CA for the upstream provider](../guides-k8s/embedded-auth-server-k8s.mdx#trust-a-private-ca-for-the-upstream-provider). The [complete example](#complete-example) below shows full provider configurations. @@ -987,11 +991,14 @@ supports CIMD but still uses DCR: - The `client_id` field in the fetched document must exactly match the URL used to fetch it. -- The document must not declare a symmetric shared-secret - `token_endpoint_auth_method`, including `client_secret_post`, - `client_secret_basic`, or `client_secret_jwt`. -- If declared, `grant_types` must include `authorization_code`, and - `response_types` must include `code`. +- `token_endpoint_auth_method` must be `none` or omitted. When it names any + other value (for example, `private_key_jwt`), the document must also publish a + `token_endpoint_auth_methods_supported` list containing `none` so the server + can negotiate down to `none`. Symmetric shared-secret methods + (`client_secret_post`, `client_secret_basic`, `client_secret_jwt`) are always + rejected. +- After unsupported entries are filtered, `grant_types` must include + `authorization_code` and `response_types` must include `code`. - `redirect_uris` must be present and valid. diff --git a/docs/toolhive/reference/cli/thv_ai-plugin_upgrade.md b/docs/toolhive/reference/cli/thv_ai-plugin_upgrade.md index 9de7e92f..af0ff7d3 100644 --- a/docs/toolhive/reference/cli/thv_ai-plugin_upgrade.md +++ b/docs/toolhive/reference/cli/thv_ai-plugin_upgrade.md @@ -41,6 +41,7 @@ thv ai-plugin upgrade [plugin-name...] [flags] ``` --allow-ref-change Permit the artifact to move to a different repository during upgrade + --allow-signer-change Permit upgrading to an artifact signed by a different identity; the new identity replaces the recorded one --clients string Comma-separated target client apps (e.g. claude-code,opencode), or "all" for every available client --fail-on-changes Report what would change without installing anything; a CI freshness gate --format string Output format (json, text) (default "text") diff --git a/static/api-specs/toolhive-api.yaml b/static/api-specs/toolhive-api.yaml index 37854572..6cb036d1 100644 --- a/static/api-specs/toolhive-api.yaml +++ b/static/api-specs/toolhive-api.yaml @@ -1,161 +1,6 @@ components: schemas: - auth.TokenValidatorConfig: - description: |- - DEPRECATED: Middleware configuration. - OIDCConfig contains OIDC configuration - properties: - allowPrivateIP: - description: AllowPrivateIP allows JWKS/OIDC endpoints on private IP addresses - type: boolean - audience: - description: Audience is the expected audience for the token - type: string - authTokenFile: - description: AuthTokenFile is the path to file containing bearer token for - authentication - type: string - cacertPath: - description: CACertPath is the path to the CA certificate bundle for HTTPS - requests - type: string - clientID: - description: ClientID is the OIDC client ID - type: string - clientSecret: - description: ClientSecret is the optional OIDC client secret for introspection - type: string - insecureAllowHTTP: - description: |- - InsecureAllowHTTP allows HTTP (non-HTTPS) OIDC issuers for development/testing - WARNING: This is insecure and should NEVER be used in production - type: boolean - introspectionURL: - description: IntrospectionURL is the optional introspection endpoint for - validating tokens - type: string - issuer: - description: Issuer is the OIDC issuer URL (e.g., https://accounts.google.com) - type: string - jwksurl: - description: JWKSURL is the URL to fetch the JWKS from - type: string - resourceURL: - description: ResourceURL is the explicit resource URL for OAuth discovery - (RFC 9728) - type: string - scopes: - description: |- - Scopes is the list of OAuth scopes to advertise in the well-known endpoint (RFC 9728) - If empty, defaults to ["openid"] - items: - type: string - type: array - type: object - core.Workload: - properties: - created_at: - description: CreatedAt is the timestamp when the workload was created. - type: string - group: - description: Group is the name of the group this workload belongs to, if - any. - type: string - labels: - additionalProperties: - type: string - description: Labels are the container labels (excluding standard ToolHive - labels) - type: object - name: - description: |- - Name is the name of the workload. - It is used as a unique identifier. - type: string - package: - description: Package specifies the Workload Package used to create this - Workload. - type: string - port: - description: |- - Port is the port on which the workload is exposed. - This is embedded in the URL. - type: integer - proxy_mode: - description: |- - ProxyMode is the proxy mode that clients should use to connect. - For stdio transports, this will be the proxy mode (sse or streamable-http). - For direct transports (sse/streamable-http), this will be the same as TransportType. - type: string - remote: - description: Remote indicates whether this is a remote workload (true) or - a container workload (false). - type: boolean - started_at: - description: StartedAt is when the container was last started (changes on - restart) - type: string - status: - description: Status is the current status of the workload. - enum: - - running - - stopped - - error - - starting - - stopping - - unhealthy - - removing - - unknown - - unauthenticated - - auth_retrying - - policy_stopped - type: string - status_context: - description: |- - StatusContext provides additional context about the workload's status. - The exact meaning is determined by the status and the underlying runtime. - type: string - tools: - description: ToolsFilter is the filter on tools applied to the workload. - items: - type: string - type: array - uniqueItems: false - transport_type: - description: TransportType is the type of transport used for this workload. - enum: - - stdio - - sse - - streamable-http - - inspector - type: string - url: - description: URL is the URL of the workload exposed by the ToolHive proxy. - type: string - type: object - github_com_stacklok_toolhive_cmd_thv-operator_api_v1beta1.RateLimitConfig: - description: |- - RateLimitConfig contains the CRD rate limiting configuration. - When set, rate limiting middleware is added to the proxy middleware chain. - properties: - perUser: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_ratelimit_types.RateLimitBucket' - shared: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_ratelimit_types.RateLimitBucket' - tools: - description: |- - Tools defines per-tool rate limit overrides. - Each entry applies additional rate limits to calls targeting a specific tool name. - A request must pass both the server-level limit and the per-tool limit. - +listType=map - +listMapKey=name - +optional - items: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_ratelimit_types.ToolRateLimitConfig' - type: array - uniqueItems: false - type: object - github_com_stacklok_toolhive_pkg_audit.Config: + audit.Config: description: |- DEPRECATED: Middleware configuration. AuditConfig contains the audit logging configuration @@ -232,95 +77,59 @@ components: +optional type: integer type: object - github_com_stacklok_toolhive_pkg_auth_awssts.Config: - description: AWSStsConfig contains AWS STS token exchange configuration for - accessing AWS services + auth.TokenValidatorConfig: + description: |- + DEPRECATED: Middleware configuration. + OIDCConfig contains OIDC configuration properties: - fallback_role_arn: - description: FallbackRoleArn is the IAM role ARN to assume when no role - mapping matches. - type: string - region: - description: Region is the AWS region for STS and SigV4 signing. - type: string - role_claim: - description: 'RoleClaim is the JWT claim to use for role mapping (default: - "groups").' + allowPrivateIP: + description: AllowPrivateIP allows JWKS/OIDC endpoints on private IP addresses + type: boolean + audience: + description: Audience is the expected audience for the token type: string - role_mappings: - description: RoleMappings maps JWT claim values to IAM roles with priority. - items: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_auth_awssts.RoleMapping' - type: array - uniqueItems: false - service: - description: 'Service is the AWS service name for SigV4 signing (default: - "aws-mcp").' + authTokenFile: + description: AuthTokenFile is the path to file containing bearer token for + authentication type: string - session_duration: - description: 'SessionDuration is the duration in seconds for assumed role - credentials (default: 3600).' - type: integer - session_name_claim: - description: 'SessionNameClaim is the JWT claim to use for role session - name (default: "sub").' + cacertPath: + description: CACertPath is the path to the CA certificate bundle for HTTPS + requests type: string - subject_provider_name: - description: |- - SubjectProviderName identifies which upstream provider's access token to use - for STS AssumeRoleWithWebIdentity. Used by vMCP only. When empty, the bearer - token from the incoming HTTP request is used. + clientID: + description: ClientID is the OIDC client ID type: string - type: object - github_com_stacklok_toolhive_pkg_auth_awssts.RoleMapping: - properties: - claim: - description: |- - Claim is the simple claim value to match (e.g., group name). - Internally compiles to a CEL expression: "" in claims[""] - Mutually exclusive with Matcher. + clientSecret: + description: ClientSecret is the optional OIDC client secret for introspection type: string - matcher: + insecureAllowHTTP: description: |- - Matcher is a CEL expression for complex matching against JWT claims. - The expression has access to a "claims" variable containing all JWT claims. - Examples: - - "admins" in claims["groups"] - - claims["sub"] == "user123" && !("act" in claims) - Mutually exclusive with Claim. + InsecureAllowHTTP allows HTTP (non-HTTPS) OIDC issuers for development/testing + WARNING: This is insecure and should NEVER be used in production + type: boolean + introspectionURL: + description: IntrospectionURL is the optional introspection endpoint for + validating tokens type: string - priority: - description: |- - Priority determines selection order (lower number = higher priority). - When multiple mappings match, the one with the lowest priority is selected. - When nil (omitted), the mapping has the lowest possible priority, and - configuration order acts as tie-breaker via stable sort. - type: integer - role_arn: - description: RoleArn is the IAM role ARN to assume when this mapping matches. + issuer: + description: Issuer is the OIDC issuer URL (e.g., https://accounts.google.com) type: string - type: object - github_com_stacklok_toolhive_pkg_auth_upstreamswap.Config: - description: |- - UpstreamSwapConfig contains configuration for upstream token swap middleware. - When set along with EmbeddedAuthServerConfig, this middleware exchanges ToolHive JWTs - for upstream IdP tokens before forwarding requests to the MCP server. - properties: - custom_header_name: - description: CustomHeaderName is the header name when HeaderStrategy is - "custom". + jwksurl: + description: JWKSURL is the URL to fetch the JWKS from type: string - header_strategy: - description: 'HeaderStrategy determines how to inject the token: "replace" - (default) or "custom".' + resourceURL: + description: ResourceURL is the explicit resource URL for OAuth discovery + (RFC 9728) type: string - provider_name: + scopes: description: |- - ProviderName identifies which upstream provider's tokens to retrieve for injection. - This is required and must match a configured upstream provider name. - type: string + Scopes is the list of OAuth scopes to advertise in the well-known endpoint (RFC 9728) + If empty, defaults to ["openid"] + items: + type: string + type: array type: object - github_com_stacklok_toolhive_pkg_authserver.CIMDRunConfig: + authserver.CIMDRunConfig: description: |- CIMD controls client_id metadata document support. When enabled, the embedded authorization server accepts HTTPS URLs as client_id values @@ -343,7 +152,7 @@ components: description: Enabled activates CIMD client lookup when true. type: boolean type: object - github_com_stacklok_toolhive_pkg_authserver.DCRUpstreamConfig: + authserver.DCRUpstreamConfig: description: |- DCRConfig enables RFC 7591 Dynamic Client Registration against the upstream authorization server. When set, the client credentials are @@ -407,7 +216,7 @@ components: server trusts. type: string type: object - github_com_stacklok_toolhive_pkg_authserver.DelegateClientRunConfig: + authserver.DelegateClientRunConfig: properties: audiences: description: |- @@ -444,7 +253,7 @@ components: type: array uniqueItems: false type: object - github_com_stacklok_toolhive_pkg_authserver.IdentityFromTokenRunConfig: + authserver.IdentityFromTokenRunConfig: description: |- IdentityFromToken extracts user identity (subject, name, email) directly from the OAuth2 token-endpoint response body using gjson dot-notation paths. When set, the @@ -464,7 +273,7 @@ components: Required when IdentityFromToken is set. type: string type: object - github_com_stacklok_toolhive_pkg_authserver.OAuth2UpstreamRunConfig: + authserver.OAuth2UpstreamRunConfig: description: |- OAuth2Config contains OAuth 2.0-specific configuration. Required when Type is "oauth2", must be nil when Type is "oidc". @@ -493,6 +302,10 @@ components: description: AuthorizationEndpoint is the URL for the OAuth authorization endpoint. type: string + ca_file_path: + description: CAFilePath is the path to a PEM CA bundle added to the system + roots. + type: string client_id: description: |- ClientID is the OAuth 2.0 client identifier registered with the upstream IDP. @@ -510,9 +323,9 @@ components: Mutually exclusive with ClientSecretEnvVar. Optional for public clients using PKCE. type: string dcr_config: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.DCRUpstreamConfig' + $ref: '#/components/schemas/authserver.DCRUpstreamConfig' identity_from_token: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.IdentityFromTokenRunConfig' + $ref: '#/components/schemas/authserver.IdentityFromTokenRunConfig' insecure_allow_http: description: |- InsecureAllowHTTP permits plain-HTTP authorization and token endpoint URLs @@ -535,11 +348,11 @@ components: description: TokenEndpoint is the URL for the OAuth token endpoint. type: string token_response_mapping: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.TokenResponseMappingRunConfig' + $ref: '#/components/schemas/authserver.TokenResponseMappingRunConfig' userinfo: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.UserInfoRunConfig' + $ref: '#/components/schemas/authserver.UserInfoRunConfig' type: object - github_com_stacklok_toolhive_pkg_authserver.OIDCUpstreamRunConfig: + authserver.OIDCUpstreamRunConfig: description: |- OIDCConfig contains OIDC-specific configuration. Required when Type is "oidc", must be nil when Type is "oauth2". @@ -560,6 +373,10 @@ components: HTTP-scheme restrictions are unchanged — HTTPS is still required for non-localhost hosts. Defaults to false. type: boolean + ca_file_path: + description: CAFilePath is the path to a PEM CA bundle added to the system + roots. + type: string client_id: description: ClientID is the OAuth 2.0 client identifier registered with the upstream IDP. @@ -609,9 +426,9 @@ components: stable per user (e.g. Entra/Azure AD's "oid"). See upstream.OIDCConfig. type: string userinfo_override: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.UserInfoRunConfig' + $ref: '#/components/schemas/authserver.UserInfoRunConfig' type: object - github_com_stacklok_toolhive_pkg_authserver.RunConfig: + authserver.RunConfig: description: |- EmbeddedAuthServerConfig contains configuration for the embedded OAuth2/OIDC authorization server. When set, the proxy runner will start an embedded auth server that delegates to upstream IDPs. @@ -679,7 +496,7 @@ components: type: array uniqueItems: false cimd: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.CIMDRunConfig' + $ref: '#/components/schemas/authserver.CIMDRunConfig' delegate_clients: description: |- DelegateClients declares confidential OAuth clients to register at @@ -695,7 +512,7 @@ components: See DelegateClientRunConfig for the per-client field reference. items: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.DelegateClientRunConfig' + $ref: '#/components/schemas/authserver.DelegateClientRunConfig' type: array uniqueItems: false delegation_token_lifespan: @@ -800,11 +617,11 @@ components: type: array uniqueItems: false signing_key_config: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.SigningKeyRunConfig' + $ref: '#/components/schemas/authserver.SigningKeyRunConfig' storage: $ref: '#/components/schemas/storage.RunConfig' token_lifespans: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.TokenLifespanRunConfig' + $ref: '#/components/schemas/authserver.TokenLifespanRunConfig' trusted_issuers: description: |- TrustedIssuers lists external OIDC issuers whose tokens are accepted as @@ -819,7 +636,7 @@ components: subject namespace qualification, required client binding) that aren't visible from the config shape alone. items: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_authserver_server_tokenexchange.TrustedIssuer' + $ref: '#/components/schemas/tokenexchange.TrustedIssuer' type: array uniqueItems: false upstreams: @@ -828,11 +645,11 @@ components: At least one upstream is required - the server delegates authentication to these providers. Multiple upstreams are supported for sequential authorization chains. items: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.UpstreamRunConfig' + $ref: '#/components/schemas/authserver.UpstreamRunConfig' type: array uniqueItems: false type: object - github_com_stacklok_toolhive_pkg_authserver.SigningKeyRunConfig: + authserver.SigningKeyRunConfig: description: |- SigningKeyConfig configures the signing key provider for JWT operations. If nil or empty, an ephemeral signing key will be auto-generated (development only). @@ -858,7 +675,7 @@ components: This key is used for signing new tokens. type: string type: object - github_com_stacklok_toolhive_pkg_authserver.TokenLifespanRunConfig: + authserver.TokenLifespanRunConfig: description: |- TokenLifespans configures the duration that various tokens are valid. If nil, defaults are applied (access: 1h, refresh: 7d, authCode: 10m). @@ -879,7 +696,7 @@ components: If empty, defaults to 7 days (168h). type: string type: object - github_com_stacklok_toolhive_pkg_authserver.TokenResponseMappingRunConfig: + authserver.TokenResponseMappingRunConfig: description: |- TokenResponseMapping configures custom field extraction from non-standard token responses. When set, the token exchange bypasses golang.org/x/oauth2 and extracts fields using @@ -902,16 +719,7 @@ components: "scope". type: string type: object - github_com_stacklok_toolhive_pkg_authserver.UpstreamProviderType: - description: 'Type specifies the provider type: "oidc" or "oauth2".' - enum: - - oidc - - oauth2 - type: string - x-enum-varnames: - - UpstreamProviderTypeOIDC - - UpstreamProviderTypeOAuth2 - github_com_stacklok_toolhive_pkg_authserver.UpstreamRunConfig: + authserver.UpstreamRunConfig: properties: name: description: |- @@ -920,13 +728,14 @@ components: If empty when only one upstream is configured, defaults to "default". type: string oauth2_config: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.OAuth2UpstreamRunConfig' + $ref: '#/components/schemas/authserver.OAuth2UpstreamRunConfig' oidc_config: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.OIDCUpstreamRunConfig' + $ref: '#/components/schemas/authserver.OIDCUpstreamRunConfig' type: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.UpstreamProviderType' + description: 'Type specifies the provider type: "oidc" or "oauth2".' + type: string type: object - github_com_stacklok_toolhive_pkg_authserver.UserInfoFieldMappingRunConfig: + authserver.UserInfoFieldMappingRunConfig: description: |- FieldMapping contains custom field mapping configuration for non-standard providers. If nil, standard OIDC field names are used ("sub", "name", "email"). @@ -959,7 +768,7 @@ components: type: array uniqueItems: false type: object - github_com_stacklok_toolhive_pkg_authserver.UserInfoRunConfig: + authserver.UserInfoRunConfig: description: |- UserInfo contains configuration for fetching user information. Optional: when nil, the upstream OAuth2 provider derives a deterministic @@ -978,148 +787,181 @@ components: description: EndpointURL is the URL of the userinfo endpoint. type: string field_mapping: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.UserInfoFieldMappingRunConfig' + $ref: '#/components/schemas/authserver.UserInfoFieldMappingRunConfig' http_method: description: |- HTTPMethod is the HTTP method to use for the userinfo request. If not specified, defaults to GET. type: string type: object - github_com_stacklok_toolhive_pkg_authserver_server_tokenexchange.JWTBearerGrantPolicy: - description: |- - JWTBearerGrant optionally enables the plain RFC 7523 JWT-bearer grant. - It accepts assertions from this issuer without client authentication and - limits their maximum age, subjects, and RFC 8707 resources. It is - independent from RFC 8693 delegation policy. + core.Workload: properties: - accepted_audiences: - description: |- - AcceptedAudiences is the set of "this AS" identity strings an - assertion's "aud" claim must intersect — e.g. to support migrating - this server's issuer/token-endpoint URL, or exposing it under more - than one valid name. Each value uniquely identifies this - authorization server for this grant; it is NOT a resource/API - identifier — a bare resource audience is deliberately not accepted - here, that would let any RFC 8707 resource-scoped token satisfy the - grant instead of only tokens minted for this AS. Defaults to - [tokenEndpoint] when empty, preserving prior exact-match behavior. - items: - type: string - type: array - uniqueItems: false - max_assertion_age: + created_at: + description: CreatedAt is the timestamp when the workload was created. type: string - subject_bindings: - items: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_authserver_server_tokenexchange.JWTBearerSubjectBinding' - type: array - uniqueItems: false - type: object - github_com_stacklok_toolhive_pkg_authserver_server_tokenexchange.JWTBearerSubjectBinding: - properties: - allowed_resources: - items: - type: string - type: array - uniqueItems: false - subject: + group: + description: Group is the name of the group this workload belongs to, if + any. type: string - type: object - github_com_stacklok_toolhive_pkg_authserver_server_tokenexchange.TrustedIssuer: - properties: - actor_claim: + labels: + additionalProperties: + type: string + description: Labels are the container labels (excluding standard ToolHive + labels) + type: object + name: description: |- - ActorClaim names the claim identifying the client that requested the - subject token from THIS EXTERNAL ISSUER (used by AllowedActors below). - Values are in the external issuer's namespace, NOT ToolHive client - IDs. Defaults to "azp"; use "appid" for Microsoft Entra v1, "cid" for - Okta. The special value "client_id" reads ValidatedClaims.ClientID - instead of Extra (assignClaim routes it to that field) — it is still - the external token's client_id claim, not a ToolHive one. + Name is the name of the workload. + It is used as a unique identifier. type: string - actor_matcher: - description: |- - ActorMatcher is an admin-authored CEL expression evaluated against the - complete signature-verified JWT claims map as "claims". A true result - authorizes delegation alongside AllowedActors; a syntax or type error - fails configuration validation. An expression that compiles but does - not return bool is NOT caught at that point, though — it compiles - successfully and is only rejected the first time it is evaluated - against a real token, denying that token (and every one after it, since - the expression will never return bool). Any other runtime evaluation - error denies the token the same way. + package: + description: Package specifies the Workload Package used to create this + Workload. type: string - allow_may_act: + port: description: |- - AllowMayAct permits this external issuer's may_act claim to authorize - delegation. It defaults to false; external issuers must be opted in - explicitly because may_act bypasses AllowedActors and ActorMatcher. It - does not affect self-issued subject tokens. When enabled, - AllowedDelegateClients must name specific ToolHive clients rather than - use the wildcard. - type: boolean - allow_private_ips: + Port is the port on which the workload is exposed. + This is embedded in the URL. + type: integer + proxy_mode: description: |- - AllowPrivateIPs permits OIDC discovery and JWKS fetches for THIS - issuer to resolve to a private or loopback address. Use only when the - issuer is hosted inside the same cluster and has no public endpoint. + ProxyMode is the proxy mode that clients should use to connect. + For stdio transports, this will be the proxy mode (sse or streamable-http). + For direct transports (sse/streamable-http), this will be the same as TransportType. + type: string + remote: + description: Remote indicates whether this is a remote workload (true) or + a container workload (false). type: boolean - allowed_actors: + started_at: + description: StartedAt is when the container was last started (changes on + restart) + type: string + status: + description: Status is the current status of the workload. + enum: + - running + - stopped + - error + - starting + - stopping + - unhealthy + - removing + - unknown + - unauthenticated + - auth_retrying + - policy_stopped + type: string + status_context: description: |- - AllowedActors is the allowlist of ActorClaim values authorized to - exchange a subject token from this issuer when it carries no - "may_act" claim. ActorMatcher can additionally authorize a token by - matching its complete verified claims map; either signal is sufficient. - When both are empty, only may_act-bearing tokens are accepted, and only - if AllowMayAct is also true for this issuer. By itself names no - ToolHive client — see AllowedDelegateClients and - docs/arch/17-token-exchange-delegation.md ("Accepted limitations" #1). + StatusContext provides additional context about the workload's status. + The exact meaning is determined by the status and the underlying runtime. + type: string + tools: + description: ToolsFilter is the filter on tools applied to the workload. items: type: string type: array uniqueItems: false - allowed_delegate_clients: - description: |- - AllowedDelegateClients restricts which ToolHive client IDs may - exchange a subject token from this issuer, for BOTH consent paths. - Required (validateTrustedIssuer rejects empty/absent); "*" permits - any confidential client holding the grant. See - docs/arch/17-token-exchange-delegation.md ("Accepted limitations" #1). + transport_type: + description: TransportType is the type of transport used for this workload. + enum: + - stdio + - sse + - streamable-http + - inspector + type: string + url: + description: URL is the URL of the workload exposed by the ToolHive proxy. + type: string + type: object + github_com_stacklok_toolhive_pkg_auth_awssts.Config: + description: AWSStsConfig contains AWS STS token exchange configuration for + accessing AWS services + properties: + fallback_role_arn: + description: FallbackRoleArn is the IAM role ARN to assume when no role + mapping matches. + type: string + region: + description: Region is the AWS region for STS and SigV4 signing. + type: string + role_claim: + description: 'RoleClaim is the JWT claim to use for role mapping (default: + "groups").' + type: string + role_mappings: + description: RoleMappings maps JWT claim values to IAM roles with priority. items: - type: string + $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_auth_awssts.RoleMapping' type: array uniqueItems: false - expected_audience: + service: + description: 'Service is the AWS service name for SigV4 signing (default: + "aws-mcp").' + type: string + session_duration: + description: 'SessionDuration is the duration in seconds for assumed role + credentials (default: 3600).' + type: integer + session_name_claim: + description: 'SessionNameClaim is the JWT claim to use for role session + name (default: "sub").' + type: string + subject_provider_name: description: |- - ExpectedAudience is the expected "aud" claim value that must appear - in an RFC 8693 subject token's audience list (a resource/API identifier, - not a client ID — required for delegation unless JWTBearerGrant is - configured; see looksLikeResourceIdentifier). RFC 7523 assertions use - the token endpoint as their audience instead. - See docs/arch/17-token-exchange-delegation.md ("ID/access-token - discrimination") for why and its limits. + SubjectProviderName identifies which upstream provider's access token to use + for STS AssumeRoleWithWebIdentity. Used by vMCP only. When empty, the bearer + token from the incoming HTTP request is used. + type: string + type: object + github_com_stacklok_toolhive_pkg_auth_awssts.RoleMapping: + properties: + claim: + description: |- + Claim is the simple claim value to match (e.g., group name). + Internally compiles to a CEL expression: "" in claims[""] + Mutually exclusive with Matcher. type: string - insecure_allow_http: + matcher: description: |- - InsecureAllowHTTP permits plain-HTTP OIDC discovery and JWKS fetches - for THIS issuer only. Development and testing only — never set in - production. Does not relax the private-IP guard; see AllowPrivateIPs. - Deliberately per-issuer: this server's own InsecureAllowHTTP must not - silently permit plaintext discovery for every trusted external issuer - too — a network attacker who can intercept that traffic could - substitute a JWKS and forge subject tokens for that issuer's - namespace. - type: boolean - issuer_url: - description: IssuerURL is the expected "iss" claim value (exact match). + Matcher is a CEL expression for complex matching against JWT claims. + The expression has access to a "claims" variable containing all JWT claims. + Examples: + - "admins" in claims["groups"] + - claims["sub"] == "user123" && !("act" in claims) + Mutually exclusive with Claim. type: string - jwks_url: + priority: description: |- - JWKSURL is the URL to fetch the issuer's JSON Web Key Set from. - If empty, it is resolved via OIDC discovery at {IssuerURL}/.well-known/openid-configuration. + Priority determines selection order (lower number = higher priority). + When multiple mappings match, the one with the lowest priority is selected. + When nil (omitted), the mapping has the lowest possible priority, and + configuration order acts as tie-breaker via stable sort. + type: integer + role_arn: + description: RoleArn is the IAM role ARN to assume when this mapping matches. + type: string + type: object + github_com_stacklok_toolhive_pkg_auth_upstreamswap.Config: + description: |- + UpstreamSwapConfig contains configuration for upstream token swap middleware. + When set along with EmbeddedAuthServerConfig, this middleware exchanges ToolHive JWTs + for upstream IdP tokens before forwarding requests to the MCP server. + properties: + custom_header_name: + description: CustomHeaderName is the header name when HeaderStrategy is + "custom". + type: string + header_strategy: + description: 'HeaderStrategy determines how to inject the token: "replace" + (default) or "custom".' + type: string + provider_name: + description: |- + ProviderName identifies which upstream provider's tokens to retrieve for injection. + This is required and must match a configured upstream provider name. type: string - jwt_bearer_grant: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_authserver_server_tokenexchange.JWTBearerGrantPolicy' type: object github_com_stacklok_toolhive_pkg_authz.Config: description: |- @@ -1555,35 +1397,6 @@ components: type: array uniqueItems: false type: object - github_com_stacklok_toolhive_pkg_ratelimit_types.RateLimitBucket: - description: |- - PerUser token bucket configuration for this tool. - +optional - properties: - maxTokens: - description: |- - MaxTokens is the maximum number of tokens (bucket capacity). - This is also the burst size: the maximum number of requests that can be served - instantaneously before the bucket is depleted. - +kubebuilder:validation:Required - +kubebuilder:validation:Minimum=1 - type: integer - refillPeriod: - $ref: '#/components/schemas/v1.Duration' - type: object - github_com_stacklok_toolhive_pkg_ratelimit_types.ToolRateLimitConfig: - properties: - name: - description: |- - Name is the MCP tool name this limit applies to. - +kubebuilder:validation:Required - +kubebuilder:validation:MinLength=1 - type: string - perUser: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_ratelimit_types.RateLimitBucket' - shared: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_ratelimit_types.RateLimitBucket' - type: object github_com_stacklok_toolhive_pkg_registry.OAuthPublicConfig: description: |- AuthConfig contains the non-secret OAuth configuration when auth is configured. @@ -1667,7 +1480,7 @@ components: type: array uniqueItems: false audit_config: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_audit.Config' + $ref: '#/components/schemas/audit.Config' audit_config_path: description: |- DEPRECATED: Middleware configuration. @@ -1703,7 +1516,7 @@ components: description: Debug indicates whether debug mode is enabled type: boolean embedded_auth_server_config: - $ref: '#/components/schemas/github_com_stacklok_toolhive_pkg_authserver.RunConfig' + $ref: '#/components/schemas/authserver.RunConfig' endpoint_prefix: description: |- EndpointPrefix is an explicit prefix to prepend to SSE endpoint URLs. @@ -1799,7 +1612,7 @@ components: type: array uniqueItems: false rate_limit_config: - $ref: '#/components/schemas/github_com_stacklok_toolhive_cmd_thv-operator_api_v1beta1.RateLimitConfig' + $ref: '#/components/schemas/v1beta1.RateLimitConfig' rate_limit_namespace: description: RateLimitNamespace is the Kubernetes namespace for Redis key derivation. @@ -3835,6 +3648,11 @@ components: allow_ref_change: description: AllowRefChange permits resolvedReference changes during upgrade type: boolean + allow_signer_change: + description: |- + AllowSignerChange permits upgrading to an artifact signed by a + different identity than the recorded one + type: boolean clients: description: |- Clients lists target client identifiers. Empty means every @@ -5016,6 +4834,142 @@ components: description: TokenURL is the OAuth 2.0 token endpoint URL type: string type: object + tokenexchange.JWTBearerGrantPolicy: + description: |- + JWTBearerGrant optionally enables the plain RFC 7523 JWT-bearer grant. + It accepts assertions from this issuer without client authentication and + limits their maximum age, subjects, and RFC 8707 resources. It is + independent from RFC 8693 delegation policy. + properties: + accepted_audiences: + description: |- + AcceptedAudiences is the set of "this AS" identity strings an + assertion's "aud" claim must intersect — e.g. to support migrating + this server's issuer/token-endpoint URL, or exposing it under more + than one valid name. Each value uniquely identifies this + authorization server for this grant; it is NOT a resource/API + identifier — a bare resource audience is deliberately not accepted + here, that would let any RFC 8707 resource-scoped token satisfy the + grant instead of only tokens minted for this AS. Defaults to + [tokenEndpoint] when empty, preserving prior exact-match behavior. + items: + type: string + type: array + uniqueItems: false + max_assertion_age: + type: string + subject_bindings: + items: + $ref: '#/components/schemas/tokenexchange.JWTBearerSubjectBinding' + type: array + uniqueItems: false + type: object + tokenexchange.JWTBearerSubjectBinding: + properties: + allowed_resources: + items: + type: string + type: array + uniqueItems: false + subject: + type: string + type: object + tokenexchange.TrustedIssuer: + properties: + actor_claim: + description: |- + ActorClaim names the claim identifying the client that requested the + subject token from THIS EXTERNAL ISSUER (used by AllowedActors below). + Values are in the external issuer's namespace, NOT ToolHive client + IDs. Defaults to "azp"; use "appid" for Microsoft Entra v1, "cid" for + Okta. The special value "client_id" reads ValidatedClaims.ClientID + instead of Extra (assignClaim routes it to that field) — it is still + the external token's client_id claim, not a ToolHive one. + type: string + actor_matcher: + description: |- + ActorMatcher is an admin-authored CEL expression evaluated against the + complete signature-verified JWT claims map as "claims". A true result + authorizes delegation alongside AllowedActors; a syntax or type error + fails configuration validation. An expression that compiles but does + not return bool is NOT caught at that point, though — it compiles + successfully and is only rejected the first time it is evaluated + against a real token, denying that token (and every one after it, since + the expression will never return bool). Any other runtime evaluation + error denies the token the same way. + type: string + allow_may_act: + description: |- + AllowMayAct permits this external issuer's may_act claim to authorize + delegation. It defaults to false; external issuers must be opted in + explicitly because may_act bypasses AllowedActors and ActorMatcher. It + does not affect self-issued subject tokens. When enabled, + AllowedDelegateClients must name specific ToolHive clients rather than + use the wildcard. + type: boolean + allow_private_ips: + description: |- + AllowPrivateIPs permits OIDC discovery and JWKS fetches for THIS + issuer to resolve to a private or loopback address. Use only when the + issuer is hosted inside the same cluster and has no public endpoint. + type: boolean + allowed_actors: + description: |- + AllowedActors is the allowlist of ActorClaim values authorized to + exchange a subject token from this issuer when it carries no + "may_act" claim. ActorMatcher can additionally authorize a token by + matching its complete verified claims map; either signal is sufficient. + When both are empty, only may_act-bearing tokens are accepted, and only + if AllowMayAct is also true for this issuer. By itself names no + ToolHive client — see AllowedDelegateClients and + docs/arch/17-token-exchange-delegation.md ("Accepted limitations" #1). + items: + type: string + type: array + uniqueItems: false + allowed_delegate_clients: + description: |- + AllowedDelegateClients restricts which ToolHive client IDs may + exchange a subject token from this issuer, for BOTH consent paths. + Required (validateTrustedIssuer rejects empty/absent); "*" permits + any confidential client holding the grant. See + docs/arch/17-token-exchange-delegation.md ("Accepted limitations" #1). + items: + type: string + type: array + uniqueItems: false + expected_audience: + description: |- + ExpectedAudience is the expected "aud" claim value that must appear + in an RFC 8693 subject token's audience list (a resource/API identifier, + not a client ID — required for delegation unless JWTBearerGrant is + configured; see looksLikeResourceIdentifier). RFC 7523 assertions use + the token endpoint as their audience instead. + See docs/arch/17-token-exchange-delegation.md ("ID/access-token + discrimination") for why and its limits. + type: string + insecure_allow_http: + description: |- + InsecureAllowHTTP permits plain-HTTP OIDC discovery and JWKS fetches + for THIS issuer only. Development and testing only — never set in + production. Does not relax the private-IP guard; see AllowPrivateIPs. + Deliberately per-issuer: this server's own InsecureAllowHTTP must not + silently permit plaintext discovery for every trusted external issuer + too — a network attacker who can intercept that traffic could + substitute a JWKS and forge subject tokens for that issuer's + namespace. + type: boolean + issuer_url: + description: IssuerURL is the expected "iss" claim value (exact match). + type: string + jwks_url: + description: |- + JWKSURL is the URL to fetch the issuer's JSON Web Key Set from. + If empty, it is resolved via OIDC discovery at {IssuerURL}/.well-known/openid-configuration. + type: string + jwt_bearer_grant: + $ref: '#/components/schemas/tokenexchange.JWTBearerGrantPolicy' + type: object types.MiddlewareConfig: properties: parameters: @@ -5027,6 +4981,35 @@ components: description: Type is a string representing the middleware type. type: string type: object + types.RateLimitBucket: + description: |- + PerUser token bucket configuration for this tool. + +optional + properties: + maxTokens: + description: |- + MaxTokens is the maximum number of tokens (bucket capacity). + This is also the burst size: the maximum number of requests that can be served + instantaneously before the bucket is depleted. + +kubebuilder:validation:Required + +kubebuilder:validation:Minimum=1 + type: integer + refillPeriod: + $ref: '#/components/schemas/v1.Duration' + type: object + types.ToolRateLimitConfig: + properties: + name: + description: |- + Name is the MCP tool name this limit applies to. + +kubebuilder:validation:Required + +kubebuilder:validation:MinLength=1 + type: string + perUser: + $ref: '#/components/schemas/types.RateLimitBucket' + shared: + $ref: '#/components/schemas/types.RateLimitBucket' + type: object v0.ServerJSON: properties: $schema: @@ -5093,6 +5076,28 @@ components: Format: Go duration string (e.g., "1m0s", "30s", "1h0m0s"). +kubebuilder:validation:Required type: object + v1beta1.RateLimitConfig: + description: |- + RateLimitConfig contains the CRD rate limiting configuration. + When set, rate limiting middleware is added to the proxy middleware chain. + properties: + perUser: + $ref: '#/components/schemas/types.RateLimitBucket' + shared: + $ref: '#/components/schemas/types.RateLimitBucket' + tools: + description: |- + Tools defines per-tool rate limit overrides. + Each entry applies additional rate limits to calls targeting a specific tool name. + A request must pass both the server-level limit and the per-tool limit. + +listType=map + +listMapKey=name + +optional + items: + $ref: '#/components/schemas/types.ToolRateLimitConfig' + type: array + uniqueItems: false + type: object externalDocs: description: "" url: "" diff --git a/static/api-specs/toolhive-crds/mcpexternalauthconfigs.schema.json b/static/api-specs/toolhive-crds/mcpexternalauthconfigs.schema.json index eb434ae8..442f9648 100644 --- a/static/api-specs/toolhive-crds/mcpexternalauthconfigs.schema.json +++ b/static/api-specs/toolhive-crds/mcpexternalauthconfigs.schema.json @@ -774,6 +774,35 @@ "pattern": "^https?://.*$", "type": "string" }, + "caBundleRef": { + "description": "CABundleRef references a ConfigMap containing a CA bundle added to the\nsystem roots when connecting to this upstream; it does not restrict trust\nto this bundle or disable public-root trust. The selected key is projected\nas ca.crt.", + "properties": { + "configMapRef": { + "description": "ConfigMapRef references a ConfigMap containing the CA certificate bundle.\nThe ConfigMap key is required by the API. If omitted in a stored object, it\ndefaults to \"ca.crt\" for backwards compatibility.", + "properties": { + "key": { + "description": "The key to select.", + "type": "string" + }, + "name": { + "default": "", + "description": "Name of the referent.\nThis field is effectively required, but due to backwards compatibility is\nallowed to be empty. Instances of this type with an empty value here are\nalmost certainly wrong.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + }, + "optional": { + "description": "Specify whether the ConfigMap or its key must be defined", + "type": "boolean" + } + }, + "required": [ + "key" + ], + "type": "object", + "x-kubernetes-map-type": "atomic" + } + }, + "type": "object" + }, "clientId": { "description": "ClientID is the OAuth 2.0 client identifier registered with the upstream IDP.\nMutually exclusive with DCRConfig: when DCRConfig is set, ClientID is obtained\nat runtime via RFC 7591 Dynamic Client Registration and must be left empty.", "type": "string" @@ -1009,6 +1038,39 @@ "maxProperties": 16, "type": "object" }, + "allowPrivateIPs": { + "description": "AllowPrivateIPs permits the upstream provider's HTTP client to connect to\nprivate IP ranges (RFC-1918, link-local). Use only when the upstream is\nhosted inside the same cluster and has no public endpoint.", + "type": "boolean" + }, + "caBundleRef": { + "description": "CABundleRef references a ConfigMap containing a CA bundle added to the\nsystem roots when connecting to this upstream; it does not restrict trust\nto this bundle or disable public-root trust. The selected key is projected\nas ca.crt.", + "properties": { + "configMapRef": { + "description": "ConfigMapRef references a ConfigMap containing the CA certificate bundle.\nThe ConfigMap key is required by the API. If omitted in a stored object, it\ndefaults to \"ca.crt\" for backwards compatibility.", + "properties": { + "key": { + "description": "The key to select.", + "type": "string" + }, + "name": { + "default": "", + "description": "Name of the referent.\nThis field is effectively required, but due to backwards compatibility is\nallowed to be empty. Instances of this type with an empty value here are\nalmost certainly wrong.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + }, + "optional": { + "description": "Specify whether the ConfigMap or its key must be defined", + "type": "boolean" + } + }, + "required": [ + "key" + ], + "type": "object", + "x-kubernetes-map-type": "atomic" + } + }, + "type": "object" + }, "clientId": { "description": "ClientID is the OAuth 2.0 client identifier registered with the upstream IdP.", "type": "string" diff --git a/static/api-specs/toolhive-crds/mcpoidcconfigs.schema.json b/static/api-specs/toolhive-crds/mcpoidcconfigs.schema.json index aa5f8afe..db3e5c22 100644 --- a/static/api-specs/toolhive-crds/mcpoidcconfigs.schema.json +++ b/static/api-specs/toolhive-crds/mcpoidcconfigs.schema.json @@ -21,7 +21,7 @@ "description": "CABundleRef references a ConfigMap containing the CA certificate bundle.\nWhen specified, ToolHive auto-mounts the ConfigMap and auto-computes ThvCABundlePath.", "properties": { "configMapRef": { - "description": "ConfigMapRef references a ConfigMap containing the CA certificate bundle.\nIf Key is not specified, it defaults to \"ca.crt\".", + "description": "ConfigMapRef references a ConfigMap containing the CA certificate bundle.\nThe ConfigMap key is required by the API. If omitted in a stored object, it\ndefaults to \"ca.crt\" for backwards compatibility.", "properties": { "key": { "description": "The key to select.", diff --git a/static/api-specs/toolhive-crds/mcpserverentries.schema.json b/static/api-specs/toolhive-crds/mcpserverentries.schema.json index 76f00949..2cdec0e1 100644 --- a/static/api-specs/toolhive-crds/mcpserverentries.schema.json +++ b/static/api-specs/toolhive-crds/mcpserverentries.schema.json @@ -23,7 +23,7 @@ "description": "CABundleRef references a ConfigMap containing CA certificates for TLS verification\nwhen connecting to the remote MCP server.", "properties": { "configMapRef": { - "description": "ConfigMapRef references a ConfigMap containing the CA certificate bundle.\nIf Key is not specified, it defaults to \"ca.crt\".", + "description": "ConfigMapRef references a ConfigMap containing the CA certificate bundle.\nThe ConfigMap key is required by the API. If omitted in a stored object, it\ndefaults to \"ca.crt\" for backwards compatibility.", "properties": { "key": { "description": "The key to select.", diff --git a/static/api-specs/toolhive-crds/mcptelemetryconfigs.schema.json b/static/api-specs/toolhive-crds/mcptelemetryconfigs.schema.json index dd62ecc5..25cda8de 100644 --- a/static/api-specs/toolhive-crds/mcptelemetryconfigs.schema.json +++ b/static/api-specs/toolhive-crds/mcptelemetryconfigs.schema.json @@ -21,7 +21,7 @@ "description": "CABundleRef references a ConfigMap containing a CA certificate bundle for the OTLP endpoint.\nWhen specified, the operator mounts the ConfigMap into the proxyrunner pod and configures\nthe OTLP exporters to trust the custom CA. This is useful when the OTLP collector uses\nTLS with certificates signed by an internal or private CA.", "properties": { "configMapRef": { - "description": "ConfigMapRef references a ConfigMap containing the CA certificate bundle.\nIf Key is not specified, it defaults to \"ca.crt\".", + "description": "ConfigMapRef references a ConfigMap containing the CA certificate bundle.\nThe ConfigMap key is required by the API. If omitted in a stored object, it\ndefaults to \"ca.crt\" for backwards compatibility.", "properties": { "key": { "description": "The key to select.", diff --git a/static/api-specs/toolhive-crds/virtualmcpservers.schema.json b/static/api-specs/toolhive-crds/virtualmcpservers.schema.json index 9318f0da..58f6a28d 100644 --- a/static/api-specs/toolhive-crds/virtualmcpservers.schema.json +++ b/static/api-specs/toolhive-crds/virtualmcpservers.schema.json @@ -665,6 +665,35 @@ "pattern": "^https?://.*$", "type": "string" }, + "caBundleRef": { + "description": "CABundleRef references a ConfigMap containing a CA bundle added to the\nsystem roots when connecting to this upstream; it does not restrict trust\nto this bundle or disable public-root trust. The selected key is projected\nas ca.crt.", + "properties": { + "configMapRef": { + "description": "ConfigMapRef references a ConfigMap containing the CA certificate bundle.\nThe ConfigMap key is required by the API. If omitted in a stored object, it\ndefaults to \"ca.crt\" for backwards compatibility.", + "properties": { + "key": { + "description": "The key to select.", + "type": "string" + }, + "name": { + "default": "", + "description": "Name of the referent.\nThis field is effectively required, but due to backwards compatibility is\nallowed to be empty. Instances of this type with an empty value here are\nalmost certainly wrong.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + }, + "optional": { + "description": "Specify whether the ConfigMap or its key must be defined", + "type": "boolean" + } + }, + "required": [ + "key" + ], + "type": "object", + "x-kubernetes-map-type": "atomic" + } + }, + "type": "object" + }, "clientId": { "description": "ClientID is the OAuth 2.0 client identifier registered with the upstream IDP.\nMutually exclusive with DCRConfig: when DCRConfig is set, ClientID is obtained\nat runtime via RFC 7591 Dynamic Client Registration and must be left empty.", "type": "string" @@ -900,6 +929,39 @@ "maxProperties": 16, "type": "object" }, + "allowPrivateIPs": { + "description": "AllowPrivateIPs permits the upstream provider's HTTP client to connect to\nprivate IP ranges (RFC-1918, link-local). Use only when the upstream is\nhosted inside the same cluster and has no public endpoint.", + "type": "boolean" + }, + "caBundleRef": { + "description": "CABundleRef references a ConfigMap containing a CA bundle added to the\nsystem roots when connecting to this upstream; it does not restrict trust\nto this bundle or disable public-root trust. The selected key is projected\nas ca.crt.", + "properties": { + "configMapRef": { + "description": "ConfigMapRef references a ConfigMap containing the CA certificate bundle.\nThe ConfigMap key is required by the API. If omitted in a stored object, it\ndefaults to \"ca.crt\" for backwards compatibility.", + "properties": { + "key": { + "description": "The key to select.", + "type": "string" + }, + "name": { + "default": "", + "description": "Name of the referent.\nThis field is effectively required, but due to backwards compatibility is\nallowed to be empty. Instances of this type with an empty value here are\nalmost certainly wrong.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + }, + "optional": { + "description": "Specify whether the ConfigMap or its key must be defined", + "type": "boolean" + } + }, + "required": [ + "key" + ], + "type": "object", + "x-kubernetes-map-type": "atomic" + } + }, + "type": "object" + }, "clientId": { "description": "ClientID is the OAuth 2.0 client identifier registered with the upstream IdP.", "type": "string"