Skip to content

Commit 08f60ec

Browse files
authored
Use X-Forwarded-* headers to construct endpoint URL (#2051)
Fix #2012
1 parent 9299e30 commit 08f60ec

File tree

25 files changed

+254
-52
lines changed

25 files changed

+254
-52
lines changed

cmd/thv-operator/api/v1alpha1/mcpserver_types.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,13 @@ type MCPServerSpec struct {
119119
// Telemetry defines observability configuration for the MCP server
120120
// +optional
121121
Telemetry *TelemetryConfig `json:"telemetry,omitempty"`
122+
123+
// TrustProxyHeaders indicates whether to trust X-Forwarded-* headers from reverse proxies
124+
// When enabled, the proxy will use X-Forwarded-Proto, X-Forwarded-Host, X-Forwarded-Port,
125+
// and X-Forwarded-Prefix headers to construct endpoint URLs
126+
// +kubebuilder:default=false
127+
// +optional
128+
TrustProxyHeaders bool `json:"trustProxyHeaders,omitempty"`
122129
}
123130

124131
// ResourceOverrides defines overrides for annotations and labels on created resources

cmd/thv-operator/controllers/mcpserver_controller.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,10 @@ func (r *MCPServerReconciler) deploymentForMCPServer(ctx context.Context, m *mcp
807807
if m.Spec.ProxyMode != "" {
808808
args = append(args, fmt.Sprintf("--proxy-mode=%s", m.Spec.ProxyMode))
809809
}
810+
// Add trust proxy headers flag if enabled
811+
if m.Spec.TrustProxyHeaders {
812+
args = append(args, "--trust-proxy-headers")
813+
}
810814
}
811815

812816
// Add pod template patch and permission profile only if not using ConfigMap

cmd/thv-operator/controllers/mcpserver_runconfig.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ func (r *MCPServerReconciler) createRunConfigFromMCPServer(m *mcpv1alpha1.MCPSer
263263
runner.WithTransportAndPorts(m.Spec.Transport, port, int(m.Spec.TargetPort)),
264264
runner.WithProxyMode(transporttypes.ProxyMode(proxyMode)),
265265
runner.WithHost(proxyHost),
266+
runner.WithTrustProxyHeaders(m.Spec.TrustProxyHeaders),
266267
runner.WithToolsFilter(toolsFilter),
267268
runner.WithEnvVars(envVars),
268269
runner.WithVolumes(volumes),

cmd/thv-proxyrunner/app/execution.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ func runWithFlagsBasedConfig(
4343
runner.WithHost(validatedHost),
4444
runner.WithTargetHost(transport.LocalhostIPv4),
4545
runner.WithProxyMode(types.ProxyMode(runFlags.runProxyMode)),
46+
runner.WithTrustProxyHeaders(runFlags.runTrustProxyHeaders),
4647
runner.WithVolumes(runFlags.runVolumes),
4748
runner.WithSecrets(runFlags.runSecrets),
4849
runner.WithAuthzConfigPath(runFlags.runAuthzConfig),

cmd/thv-proxyrunner/app/run.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ type proxyRunFlags struct {
8787
// Network isolation flag
8888
runIsolateNetwork bool
8989

90+
// Trust proxy headers flag
91+
runTrustProxyHeaders bool
92+
9093
// Tools filter
9194
runToolsFilter []string
9295

@@ -217,6 +220,8 @@ func addRunFlags(runCmd *cobra.Command, runFlags *proxyRunFlags) {
217220
"Enable Prometheus-style /metrics endpoint on the main transport port")
218221
runCmd.Flags().BoolVar(&runFlags.runIsolateNetwork, "isolate-network", false,
219222
"Isolate the container network from the host (default: false)")
223+
runCmd.Flags().BoolVar(&runFlags.runTrustProxyHeaders, "trust-proxy-headers", false,
224+
"Trust X-Forwarded-* headers from reverse proxies (X-Forwarded-Proto, X-Forwarded-Host, X-Forwarded-Port, X-Forwarded-Prefix)")
220225
runCmd.Flags().StringArrayVar(
221226
&runFlags.runToolsFilter,
222227
"tools",

cmd/thv/app/run_flags.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ type RunFlags struct {
8282
// Network isolation
8383
IsolateNetwork bool
8484

85+
// Proxy headers
86+
TrustProxyHeaders bool
87+
8588
// Labels
8689
Labels []string
8790

@@ -195,6 +198,8 @@ func AddRunFlags(cmd *cobra.Command, config *RunFlags) {
195198

196199
cmd.Flags().BoolVar(&config.IsolateNetwork, "isolate-network", false,
197200
"Isolate the container network from the host (default: false)")
201+
cmd.Flags().BoolVar(&config.TrustProxyHeaders, "trust-proxy-headers", false,
202+
"Trust X-Forwarded-* headers from reverse proxies (X-Forwarded-Proto, X-Forwarded-Host, X-Forwarded-Port, X-Forwarded-Prefix)")
198203
cmd.Flags().StringArrayVarP(&config.Labels, "label", "l", []string{}, "Set labels on the container (format: key=value)")
199204
cmd.Flags().BoolVarP(&config.Foreground, "foreground", "f", false, "Run in foreground mode (block until container exits)")
200205
cmd.Flags().StringArrayVar(
@@ -428,6 +433,7 @@ func buildRunnerConfig(
428433
runner.WithAuditConfigPath(runFlags.AuditConfig),
429434
runner.WithPermissionProfileNameOrPath(runFlags.PermissionProfile),
430435
runner.WithNetworkIsolation(runFlags.IsolateNetwork),
436+
runner.WithTrustProxyHeaders(runFlags.TrustProxyHeaders),
431437
runner.WithK8sPodPatch(runFlags.K8sPodPatch),
432438
runner.WithProxyMode(types.ProxyMode(runFlags.ProxyMode)),
433439
runner.WithTransportAndPorts(transportType, runFlags.ProxyPort, runFlags.TargetPort),

deploy/charts/operator-crds/Chart.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ apiVersion: v2
22
name: toolhive-operator-crds
33
description: A Helm chart for installing the ToolHive Operator CRDs into Kubernetes.
44
type: application
5-
version: 0.0.31
5+
version: 0.0.32
66
appVersion: "0.0.1"

deploy/charts/operator-crds/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
# ToolHive Operator CRDs Helm Chart
33

4-
![Version: 0.0.31](https://img.shields.io/badge/Version-0.0.31-informational?style=flat-square)
4+
![Version: 0.0.32](https://img.shields.io/badge/Version-0.0.32-informational?style=flat-square)
55
![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square)
66

77
A Helm chart for installing the ToolHive Operator CRDs into Kubernetes.

deploy/charts/operator-crds/crds/toolhive.stacklok.dev_mcpservers.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8942,6 +8942,13 @@ spec:
89428942
- streamable-http
89438943
- sse
89448944
type: string
8945+
trustProxyHeaders:
8946+
default: false
8947+
description: |-
8948+
TrustProxyHeaders indicates whether to trust X-Forwarded-* headers from reverse proxies
8949+
When enabled, the proxy will use X-Forwarded-Proto, X-Forwarded-Host, X-Forwarded-Port,
8950+
and X-Forwarded-Prefix headers to construct endpoint URLs
8951+
type: boolean
89458952
volumes:
89468953
description: Volumes are volumes to mount in the MCP server container
89478954
items:

docs/cli/thv_run.md

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

0 commit comments

Comments
 (0)