diff --git a/config/envoyconfig/per_filter_config.go b/config/envoyconfig/per_filter_config.go index 16ffd1989..0de97cc6b 100644 --- a/config/envoyconfig/per_filter_config.go +++ b/config/envoyconfig/per_filter_config.go @@ -21,6 +21,22 @@ func PerFilterConfigExtAuthzContextExtensions(authzContextExtensions map[string] }) } +// PerFilterConfigExtAuthzContextExtensionsWithBody returns a per-filter config for ext authz that +// sets context extensions and includes the request body. +func PerFilterConfigExtAuthzContextExtensionsWithBody(mcpRequestBodyMaxBytes uint32, authzContextExtensions map[string]string) *anypb.Any { + return marshalAny(&envoy_extensions_filters_http_ext_authz_v3.ExtAuthzPerRoute{ + Override: &envoy_extensions_filters_http_ext_authz_v3.ExtAuthzPerRoute_CheckSettings{ + CheckSettings: &envoy_extensions_filters_http_ext_authz_v3.CheckSettings{ + ContextExtensions: authzContextExtensions, + WithRequestBody: &envoy_extensions_filters_http_ext_authz_v3.BufferSettings{ + MaxRequestBytes: mcpRequestBodyMaxBytes, + AllowPartialMessage: true, + }, + }, + }, + }) +} + // PerFilterConfigExtAuthzDisabled returns a per-filter config for ext authz that disables ext-authz. func PerFilterConfigExtAuthzDisabled() *anypb.Any { return marshalAny(&envoy_extensions_filters_http_ext_authz_v3.ExtAuthzPerRoute{ diff --git a/config/envoyconfig/routes.go b/config/envoyconfig/routes.go index d0bacbab0..aee875ea2 100644 --- a/config/envoyconfig/routes.go +++ b/config/envoyconfig/routes.go @@ -325,8 +325,13 @@ func (b *Builder) buildRouteForPolicyAndMatch( PerFilterConfigExtAuthzName: PerFilterConfigExtAuthzDisabled(), } } else { + extAuthzOpts := MakeExtAuthzContextExtensions(false, routeID, routeChecksum) + extAuthzCfg := PerFilterConfigExtAuthzContextExtensions(extAuthzOpts) + if policy.IsMCPServer() { + extAuthzCfg = PerFilterConfigExtAuthzContextExtensionsWithBody(policy.MCP.GetMaxRequestBytes(), extAuthzOpts) + } route.TypedPerFilterConfig = map[string]*anypb.Any{ - PerFilterConfigExtAuthzName: PerFilterConfigExtAuthzContextExtensions(MakeExtAuthzContextExtensions(false, routeID, routeChecksum)), + PerFilterConfigExtAuthzName: extAuthzCfg, } luaMetadata["remove_pomerium_cookie"] = &structpb.Value{ Kind: &structpb.Value_StringValue{ diff --git a/config/policy.go b/config/policy.go index 5dfbddbcc..c2538dd2b 100644 --- a/config/policy.go +++ b/config/policy.go @@ -216,6 +216,15 @@ type MCP struct { UpstreamOAuth2 *UpstreamOAuth2 `mapstructure:"upstream_oauth2" yaml:"upstream_oauth2,omitempty" json:"upstream_oauth2,omitempty"` // PassUpstreamAccessToken indicates whether to pass the upstream access token in the `Authorization: Bearer` header that is suitable for calling the MCP routes PassUpstreamAccessToken bool `mapstructure:"pass_upstream_access_token" yaml:"pass_upstream_access_token,omitempty" json:"pass_upstream_access_token,omitempty"` + // MaxRequestBytes is the maximum request body size in bytes that can be sent to the MCP server + MaxRequestBytes *uint32 `mapstructure:"max_request_bytes" yaml:"max_request_bytes,omitempty" json:"max_request_bytes,omitempty"` +} + +func (p *MCP) GetMaxRequestBytes() uint32 { + if p == nil || p.MaxRequestBytes == nil { + return 4 * 1024 + } + return *p.MaxRequestBytes } // HasUpstreamOAuth2 checks if the route is for the MCP Server and if it has an upstream OAuth2 configuration