envoyproxy / envoyproxy/envoy

[gRPC-JSON transcoder] Request validation triggers 404 for CORS preflight OPTIONS requests

Open
#17,148 3 comments 2 reactions 0 assignees View on GitHub
area/grpc-transcoding bug help wanted
Dominant language
C++
Stars
28.9k
Forks
5.6k
Avg merge
1d 20h
Merged PRs (30d)
437

Description

*Title*: Request validation triggers 404 for CORS preflight OPTIONS requests

*Description*:

When a grpc-json transcoder is deployed with CORS enabled preflight (OPTIONS) requests fail if request validation is enabled. This likely happens because the transcoder attempts to validate the HTTP request's method before CORS, triggering an error as OPTIONS is not recognized as a valid "transcodable" method.

---
*Repro steps*:

Setup the grpc-json transcoder with request validation enabled and CORS rules and observe that when `request_validation_options` with `reject_unknown_method` is set CORS will fail with a 404 error:

```yaml
cors:
allow_origin_string_match: [{ prefix: "*" }]
allow_methods: GET, PUT, DELETE, POST, PATCH, OPTIONS
allow_headers: authorization, keep-alive, user-agent, cache-control, content-type, content-transfer-encoding, x-accept-content-transfer-encoding, x-accept-response-streaming, x-user-agent, x-grpc-web, referer
expose_headers: grpc-status, grpc-message, x-envoy-upstream-service-time
allow_credentials: true
routes:
- match: { prefix: "/" }
route: { cluster: grpc, timeout: 60s }
```

```yaml
request_validation_options:
reject_unknown_method: true
reject_unknown_query_parameters: true
```

Comment out or remove the `request_validation_options` block and observe that CORS preflight (OPTIONS) works again correctly:

```yaml
# request_validation_options:
# reject_unknown_method: true
# reject_unknown_query_parameters: true
```

---
*Config*:

```
admin:
address:
socket_address: { address: 0.0.0.0, port_value: 9901 }

static_resources:
listeners:
- name: rest-listener
address:
socket_address: { address: 0.0.0.0, port_value: 8080 }
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: grpc_json
codec_type: AUTO
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
cors:
allow_origin_string_match: [{ prefix: "*" }]
allow_methods: GET, PUT, DELETE, POST, PATCH, OPTIONS
allow_headers: authorization, keep-alive, user-agent, cache-control, content-type, content-transfer-encoding, x-accept-content-transfer-encoding, x-accept-response-streaming, x-user-agent, x-grpc-web, referer
expose_headers: grpc-status, grpc-message, x-envoy-upstream-service-time
allow_credentials: true
routes:
- match: { prefix: "/" }
route: { cluster: grpc, timeout: 60s }
http_filters:
- name: envoy.filters.http.cors
- name: envoy.filters.http.grpc_json_transcoder
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.grpc_json_transcoder.v3.GrpcJsonTranscoder
services:
- animeshon.crossrefs.v1alpha1.Referrer
# - google.iam.v1.IAMPolicy
- google.longrunning.Operations
print_options:
add_whitespace: true
always_print_enums_as_ints: false
always_print_primitive_fields: true
preserve_proto_field_names: false
request_validation_options:
reject_unknown_method: true
reject_unknown_query_parameters: true
convert_grpc_status: true
proto_descriptor: /etc/envoy/proto.bin
- name: envoy.filters.http.router

clusters:
- name: grpc
connect_timeout: 5s
type: LOGICAL_DNS
lb_policy: ROUND_ROBIN
dns_lookup_family: V4_ONLY
typed_extension_protocol_options:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
explicit_http_config:
http2_protocol_options: {}
load_assignment:
cluster_name: grpc
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: host.docker.internal
port_value: 5000
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.