envoyproxy/envoy

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

Open

#17 148 ouverte le 25 juin 2021

Voir sur GitHub
 (3 commentaires) (2 réactions) (0 assignés)C++ (5 373 forks)batch import
area/grpc-transcodingbughelp wanted

Métriques du dépôt

Stars
 (27 997 stars)
Métriques de merge PR
 (Merge moyen 8j) (378 PRs mergées en 30 j)

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:

                      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 }
                      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:

                      # 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

Guide contributeur