Istio local rate limit with header + path toghther config

Hello

I am trying to have rate limit based on 2 conditions:

  • match path
  • match path and header value

I tried following config but doesn’t look like it is working:

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: httpbin-ratelimit
spec:
  workloadSelector:
    labels:
      app: httpbin
  configPatches:
    - applyTo: HTTP_FILTER
      match:
        context: SIDECAR_INBOUND
        listener:
          filterChain:
            filter:
              name: 'envoy.filters.network.http_connection_manager'
      patch:
        operation: INSERT_BEFORE
        value:
          name: envoy.filters.http.local_ratelimit
          typed_config:
            "@type": type.googleapis.com/udpa.type.v1.TypedStruct
            type_url: type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
            value:
              stat_prefix: http_local_rate_limiter
    - applyTo: HTTP_ROUTE
      match:
        context: SIDECAR_INBOUND
        routeConfiguration:
          vhost:
            name: "inbound|http|80"
            route:
              action: ANY
      patch:
        operation: MERGE
        value:
          route:
            rate_limits:
              - actions:
                - request_headers:
                    header_name: ":path"
                    descriptor_key: path
              - actions:
                - request_headers:
                    header_name: ":path"
                    descriptor_key: headerpath
                - request_headers:
                    descriptor_key: "service"
                    header_name: "x-service"

          typed_per_filter_config:
            envoy.filters.http.local_ratelimit:
              "@type": type.googleapis.com/udpa.type.v1.TypedStruct
              type_url: type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
              value:
                stat_prefix: http_local_rate_limiter
                enable_x_ratelimit_headers: DRAFT_VERSION_03
                descriptors:
                  - entries:
                      - key: path
                        value: /headers
                    token_bucket:
                      max_tokens: 3
                      tokens_per_fill: 3
                      fill_interval: 60s
                  - entries:
                      - key: path
                        value: /ip
                    token_bucket:
                      max_tokens: 2
                      tokens_per_fill: 2
                      fill_interval: 60s
                  - entries:    
                      - key: headerpath
                        value: /get
                        descriptors:
                          - entries:
                              - key: service
                                value: test                      
                    token_bucket:
                      max_tokens: 7
                      tokens_per_fill: 7
                      fill_interval: 60s
                filter_enabled:
                  runtime_key: local_rate_limit_enabled
                  default_value:
                    numerator: 100
                    denominator: HUNDRED
                filter_enforced:
                  runtime_key: local_rate_limit_enforced
                  default_value:
                    numerator: 100
                    denominator: HUNDRED
                response_headers_to_add:
                  - append: false
                    header:
                      key: x-local-rate-limit
                      value: 'true'
                token_bucket:
                  max_tokens: 10
                  tokens_per_fill: 10
                  fill_interval: 20s

What does the resulting Envoy config look like when applied?

A faster way to debug this (and make sure the rate limit config is correct) is to directly just use an instance of an Envoy proxy (take Istio out of the picture) and start with the barebones configuration - i.e. remove all matches, start with a single descriptor and build from there.