Skip to content

Commit 808d003

Browse files
authored
Merge branch 'main' into skip-update-check-env-var
2 parents f3dd189 + b1977ec commit 808d003

35 files changed

Lines changed: 1350 additions & 78 deletions

.github/workflows/releaser.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ jobs:
187187
188188
- name: Run GoReleaser
189189
id: run-goreleaser
190-
uses: goreleaser/goreleaser-action@ec59f474b9834571250b370d4735c50f8e2d1e29 # v7
190+
uses: goreleaser/goreleaser-action@1a80836c5c9d9e5755a25cb59ec6f45a3b5f41a8 # v7
191191
with:
192192
distribution: goreleaser
193193
version: "~> v2"

cmd/thv-operator/api/v1beta1/mcpexternalauthconfig_types.go

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -230,11 +230,26 @@ type EmbeddedAuthServerConfig struct {
230230
// +optional
231231
Storage *AuthServerStorageConfig `json:"storage,omitempty"`
232232

233-
// AllowedAudiences is the list of valid resource URIs that tokens can be issued for.
234-
// For an embedded auth server, this can be determined by the servers (MCP or vMCP) it serves.
235-
236-
// ScopesSupported is the list of OAuth 2.0 scopes that this authorization server supports.
237-
// For an embedded auth server, this can be derived from the server's (MCP or vMCP) OIDC configuration.
233+
// BaselineClientScopes is a baseline set of OAuth 2.0 scopes guaranteed to be
234+
// included in every client registration. The embedded auth server unions these
235+
// scopes into the registered set returned by RFC 7591 Dynamic Client
236+
// Registration, so a client that narrows the `scope` field at /oauth/register
237+
// can still request the baseline scopes at /oauth/authorize. All values must
238+
// be present in the upstream-derived scopesSupported set; the auth server
239+
// fails to start if any value is missing.
240+
//
241+
// Security: every client registered via /oauth/register will gain the
242+
// ability to request these scopes at /oauth/authorize, regardless of what
243+
// the client itself requested. Keep the baseline narrow (typically
244+
// "openid" and "offline_access"). Adding a privileged scope here — e.g.
245+
// "admin:read" — would grant it to every DCR-registered client, including
246+
// public clients like Claude Code, Cursor, and VS Code.
247+
// +kubebuilder:validation:MaxItems=10
248+
// +kubebuilder:validation:items:MinLength=1
249+
// +kubebuilder:validation:items:Pattern=`^[\x21\x23-\x5B\x5D-\x7E]+$`
250+
// +listType=atomic
251+
// +optional
252+
BaselineClientScopes []string `json:"baselineClientScopes,omitempty"`
238253
}
239254

240255
// TokenLifespanConfig holds configuration for token lifetimes.

cmd/thv-operator/api/v1beta1/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/thv-operator/pkg/controllerutil/authserver.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,7 @@ func BuildAuthServerRunConfig(
530530
AuthorizationEndpointBaseURL: authConfig.AuthorizationEndpointBaseURL,
531531
AllowedAudiences: allowedAudiences,
532532
ScopesSupported: scopesSupported,
533+
BaselineClientScopes: authConfig.BaselineClientScopes,
533534
}
534535

535536
// Build signing key configuration

deploy/charts/operator-crds/files/crds/toolhive.stacklok.dev_mcpexternalauthconfigs.yaml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,29 @@ spec:
214214
Must be a valid HTTPS URL (or HTTP for localhost) without query, fragment, or trailing slash.
215215
pattern: ^https?://[^\s?#]+[^/\s?#]$
216216
type: string
217+
baselineClientScopes:
218+
description: |-
219+
BaselineClientScopes is a baseline set of OAuth 2.0 scopes guaranteed to be
220+
included in every client registration. The embedded auth server unions these
221+
scopes into the registered set returned by RFC 7591 Dynamic Client
222+
Registration, so a client that narrows the `scope` field at /oauth/register
223+
can still request the baseline scopes at /oauth/authorize. All values must
224+
be present in the upstream-derived scopesSupported set; the auth server
225+
fails to start if any value is missing.
226+
227+
Security: every client registered via /oauth/register will gain the
228+
ability to request these scopes at /oauth/authorize, regardless of what
229+
the client itself requested. Keep the baseline narrow (typically
230+
"openid" and "offline_access"). Adding a privileged scope here — e.g.
231+
"admin:read" — would grant it to every DCR-registered client, including
232+
public clients like Claude Code, Cursor, and VS Code.
233+
items:
234+
minLength: 1
235+
pattern: ^[\x21\x23-\x5B\x5D-\x7E]+$
236+
type: string
237+
maxItems: 10
238+
type: array
239+
x-kubernetes-list-type: atomic
217240
hmacSecretRefs:
218241
description: |-
219242
HMACSecretRefs references Kubernetes Secrets containing symmetric secrets for signing
@@ -1385,6 +1408,29 @@ spec:
13851408
Must be a valid HTTPS URL (or HTTP for localhost) without query, fragment, or trailing slash.
13861409
pattern: ^https?://[^\s?#]+[^/\s?#]$
13871410
type: string
1411+
baselineClientScopes:
1412+
description: |-
1413+
BaselineClientScopes is a baseline set of OAuth 2.0 scopes guaranteed to be
1414+
included in every client registration. The embedded auth server unions these
1415+
scopes into the registered set returned by RFC 7591 Dynamic Client
1416+
Registration, so a client that narrows the `scope` field at /oauth/register
1417+
can still request the baseline scopes at /oauth/authorize. All values must
1418+
be present in the upstream-derived scopesSupported set; the auth server
1419+
fails to start if any value is missing.
1420+
1421+
Security: every client registered via /oauth/register will gain the
1422+
ability to request these scopes at /oauth/authorize, regardless of what
1423+
the client itself requested. Keep the baseline narrow (typically
1424+
"openid" and "offline_access"). Adding a privileged scope here — e.g.
1425+
"admin:read" — would grant it to every DCR-registered client, including
1426+
public clients like Claude Code, Cursor, and VS Code.
1427+
items:
1428+
minLength: 1
1429+
pattern: ^[\x21\x23-\x5B\x5D-\x7E]+$
1430+
type: string
1431+
maxItems: 10
1432+
type: array
1433+
x-kubernetes-list-type: atomic
13881434
hmacSecretRefs:
13891435
description: |-
13901436
HMACSecretRefs references Kubernetes Secrets containing symmetric secrets for signing

deploy/charts/operator-crds/files/crds/toolhive.stacklok.dev_virtualmcpservers.yaml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,29 @@ spec:
8787
Must be a valid HTTPS URL (or HTTP for localhost) without query, fragment, or trailing slash.
8888
pattern: ^https?://[^\s?#]+[^/\s?#]$
8989
type: string
90+
baselineClientScopes:
91+
description: |-
92+
BaselineClientScopes is a baseline set of OAuth 2.0 scopes guaranteed to be
93+
included in every client registration. The embedded auth server unions these
94+
scopes into the registered set returned by RFC 7591 Dynamic Client
95+
Registration, so a client that narrows the `scope` field at /oauth/register
96+
can still request the baseline scopes at /oauth/authorize. All values must
97+
be present in the upstream-derived scopesSupported set; the auth server
98+
fails to start if any value is missing.
99+
100+
Security: every client registered via /oauth/register will gain the
101+
ability to request these scopes at /oauth/authorize, regardless of what
102+
the client itself requested. Keep the baseline narrow (typically
103+
"openid" and "offline_access"). Adding a privileged scope here — e.g.
104+
"admin:read" — would grant it to every DCR-registered client, including
105+
public clients like Claude Code, Cursor, and VS Code.
106+
items:
107+
minLength: 1
108+
pattern: ^[\x21\x23-\x5B\x5D-\x7E]+$
109+
type: string
110+
maxItems: 10
111+
type: array
112+
x-kubernetes-list-type: atomic
90113
hmacSecretRefs:
91114
description: |-
92115
HMACSecretRefs references Kubernetes Secrets containing symmetric secrets for signing
@@ -2723,6 +2746,29 @@ spec:
27232746
Must be a valid HTTPS URL (or HTTP for localhost) without query, fragment, or trailing slash.
27242747
pattern: ^https?://[^\s?#]+[^/\s?#]$
27252748
type: string
2749+
baselineClientScopes:
2750+
description: |-
2751+
BaselineClientScopes is a baseline set of OAuth 2.0 scopes guaranteed to be
2752+
included in every client registration. The embedded auth server unions these
2753+
scopes into the registered set returned by RFC 7591 Dynamic Client
2754+
Registration, so a client that narrows the `scope` field at /oauth/register
2755+
can still request the baseline scopes at /oauth/authorize. All values must
2756+
be present in the upstream-derived scopesSupported set; the auth server
2757+
fails to start if any value is missing.
2758+
2759+
Security: every client registered via /oauth/register will gain the
2760+
ability to request these scopes at /oauth/authorize, regardless of what
2761+
the client itself requested. Keep the baseline narrow (typically
2762+
"openid" and "offline_access"). Adding a privileged scope here — e.g.
2763+
"admin:read" — would grant it to every DCR-registered client, including
2764+
public clients like Claude Code, Cursor, and VS Code.
2765+
items:
2766+
minLength: 1
2767+
pattern: ^[\x21\x23-\x5B\x5D-\x7E]+$
2768+
type: string
2769+
maxItems: 10
2770+
type: array
2771+
x-kubernetes-list-type: atomic
27262772
hmacSecretRefs:
27272773
description: |-
27282774
HMACSecretRefs references Kubernetes Secrets containing symmetric secrets for signing

deploy/charts/operator-crds/templates/toolhive.stacklok.dev_mcpexternalauthconfigs.yaml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,29 @@ spec:
217217
Must be a valid HTTPS URL (or HTTP for localhost) without query, fragment, or trailing slash.
218218
pattern: ^https?://[^\s?#]+[^/\s?#]$
219219
type: string
220+
baselineClientScopes:
221+
description: |-
222+
BaselineClientScopes is a baseline set of OAuth 2.0 scopes guaranteed to be
223+
included in every client registration. The embedded auth server unions these
224+
scopes into the registered set returned by RFC 7591 Dynamic Client
225+
Registration, so a client that narrows the `scope` field at /oauth/register
226+
can still request the baseline scopes at /oauth/authorize. All values must
227+
be present in the upstream-derived scopesSupported set; the auth server
228+
fails to start if any value is missing.
229+
230+
Security: every client registered via /oauth/register will gain the
231+
ability to request these scopes at /oauth/authorize, regardless of what
232+
the client itself requested. Keep the baseline narrow (typically
233+
"openid" and "offline_access"). Adding a privileged scope here — e.g.
234+
"admin:read" — would grant it to every DCR-registered client, including
235+
public clients like Claude Code, Cursor, and VS Code.
236+
items:
237+
minLength: 1
238+
pattern: ^[\x21\x23-\x5B\x5D-\x7E]+$
239+
type: string
240+
maxItems: 10
241+
type: array
242+
x-kubernetes-list-type: atomic
220243
hmacSecretRefs:
221244
description: |-
222245
HMACSecretRefs references Kubernetes Secrets containing symmetric secrets for signing
@@ -1388,6 +1411,29 @@ spec:
13881411
Must be a valid HTTPS URL (or HTTP for localhost) without query, fragment, or trailing slash.
13891412
pattern: ^https?://[^\s?#]+[^/\s?#]$
13901413
type: string
1414+
baselineClientScopes:
1415+
description: |-
1416+
BaselineClientScopes is a baseline set of OAuth 2.0 scopes guaranteed to be
1417+
included in every client registration. The embedded auth server unions these
1418+
scopes into the registered set returned by RFC 7591 Dynamic Client
1419+
Registration, so a client that narrows the `scope` field at /oauth/register
1420+
can still request the baseline scopes at /oauth/authorize. All values must
1421+
be present in the upstream-derived scopesSupported set; the auth server
1422+
fails to start if any value is missing.
1423+
1424+
Security: every client registered via /oauth/register will gain the
1425+
ability to request these scopes at /oauth/authorize, regardless of what
1426+
the client itself requested. Keep the baseline narrow (typically
1427+
"openid" and "offline_access"). Adding a privileged scope here — e.g.
1428+
"admin:read" — would grant it to every DCR-registered client, including
1429+
public clients like Claude Code, Cursor, and VS Code.
1430+
items:
1431+
minLength: 1
1432+
pattern: ^[\x21\x23-\x5B\x5D-\x7E]+$
1433+
type: string
1434+
maxItems: 10
1435+
type: array
1436+
x-kubernetes-list-type: atomic
13911437
hmacSecretRefs:
13921438
description: |-
13931439
HMACSecretRefs references Kubernetes Secrets containing symmetric secrets for signing

deploy/charts/operator-crds/templates/toolhive.stacklok.dev_virtualmcpservers.yaml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,29 @@ spec:
9090
Must be a valid HTTPS URL (or HTTP for localhost) without query, fragment, or trailing slash.
9191
pattern: ^https?://[^\s?#]+[^/\s?#]$
9292
type: string
93+
baselineClientScopes:
94+
description: |-
95+
BaselineClientScopes is a baseline set of OAuth 2.0 scopes guaranteed to be
96+
included in every client registration. The embedded auth server unions these
97+
scopes into the registered set returned by RFC 7591 Dynamic Client
98+
Registration, so a client that narrows the `scope` field at /oauth/register
99+
can still request the baseline scopes at /oauth/authorize. All values must
100+
be present in the upstream-derived scopesSupported set; the auth server
101+
fails to start if any value is missing.
102+
103+
Security: every client registered via /oauth/register will gain the
104+
ability to request these scopes at /oauth/authorize, regardless of what
105+
the client itself requested. Keep the baseline narrow (typically
106+
"openid" and "offline_access"). Adding a privileged scope here — e.g.
107+
"admin:read" — would grant it to every DCR-registered client, including
108+
public clients like Claude Code, Cursor, and VS Code.
109+
items:
110+
minLength: 1
111+
pattern: ^[\x21\x23-\x5B\x5D-\x7E]+$
112+
type: string
113+
maxItems: 10
114+
type: array
115+
x-kubernetes-list-type: atomic
93116
hmacSecretRefs:
94117
description: |-
95118
HMACSecretRefs references Kubernetes Secrets containing symmetric secrets for signing
@@ -2726,6 +2749,29 @@ spec:
27262749
Must be a valid HTTPS URL (or HTTP for localhost) without query, fragment, or trailing slash.
27272750
pattern: ^https?://[^\s?#]+[^/\s?#]$
27282751
type: string
2752+
baselineClientScopes:
2753+
description: |-
2754+
BaselineClientScopes is a baseline set of OAuth 2.0 scopes guaranteed to be
2755+
included in every client registration. The embedded auth server unions these
2756+
scopes into the registered set returned by RFC 7591 Dynamic Client
2757+
Registration, so a client that narrows the `scope` field at /oauth/register
2758+
can still request the baseline scopes at /oauth/authorize. All values must
2759+
be present in the upstream-derived scopesSupported set; the auth server
2760+
fails to start if any value is missing.
2761+
2762+
Security: every client registered via /oauth/register will gain the
2763+
ability to request these scopes at /oauth/authorize, regardless of what
2764+
the client itself requested. Keep the baseline narrow (typically
2765+
"openid" and "offline_access"). Adding a privileged scope here — e.g.
2766+
"admin:read" — would grant it to every DCR-registered client, including
2767+
public clients like Claude Code, Cursor, and VS Code.
2768+
items:
2769+
minLength: 1
2770+
pattern: ^[\x21\x23-\x5B\x5D-\x7E]+$
2771+
type: string
2772+
maxItems: 10
2773+
type: array
2774+
x-kubernetes-list-type: atomic
27292775
hmacSecretRefs:
27302776
description: |-
27312777
HMACSecretRefs references Kubernetes Secrets containing symmetric secrets for signing

0 commit comments

Comments
 (0)