Before you begin

  1. Follow the Get started guide to install Gloo Gateway, set up a gateway resource, and deploy the httpbin sample app.

  2. Get the external address of the gateway and save it in an environment variable.

Enable extProc in Gloo Gateway

You can enable external processing for all routes that the gateway serves by using the Gloo Gateway Settings resource.

  1. Edit the Gloo Gateway Settings resource and add your extProc settings.
      kubectl edit settings default -n gloo-system
      
  2. Add the following extProc settings to the spec section. This example configures the standard extProc filter, which runs in the middle of the Envoy filter chain. Gloo Gateway also supports extProcEarly (runs early in the filter chain) and extProcLate (runs as the final filter before a request leaves Envoy). For more information, see ExtProc filter variants.
      
    spec:
      extProc:
        allowModeOverride: false
        failureModeAllow: false
        filterStage:
          predicate: After
          stage: AuthZStage
        grpcService:
          extProcServerRef:
            name: ext-proc-grpc
            namespace: gloo-system
        processingMode:
          requestHeaderMode: SEND
          responseHeaderMode: SKIP
      
    SettingDescription
    allowModeOverrideAllow the extProc server to override the processing mode settings that you set. Default value is false.
    failureModeAllowAllow the extProc server to continue when an error is detected during external processing. If set to true, the extProc server continues. If set to false, external processing is stopped and an error is returned to the Envoy proxy.
    filterStage.predicateHow to apply the filter relative to filterStage.stage. Applies to extProcEarly and extProc. Has no effect on extProcLate, which always runs as the final filter.
    filterStage.stageThe stage in the filter chain where you want to enable external processing. In this example, external processing is added after the authorization stage.
    grpcService.extProcServerRefThe name and namespace of the Upstream resource that represents your external processing server.
    processingMode.requestHeaderModeSend (SEND) or skip sending (SKIP) request header information to the extProc server.
    processingMode.responseHeaderModeSend (SEND) or skip sending (SKIP) response header information to the extProc server.

Deploy an extProc server

  1. Set up the extProc server. This example uses a prebuilt extProc server that manipulates request and response headers based on instructions that are sent in an instructions header.

      kubectl apply -n gloo-system -f- <<EOF
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: ext-proc-grpc
    spec:
      selector:
        matchLabels:
          app: ext-proc-grpc
      replicas: 1
      template:
        metadata:
          labels:
            app: ext-proc-grpc
        spec:
          containers:
            - name: ext-proc-grpc
              image: gcr.io/solo-test-236622/ext-proc-example-basic-sink:0.0.5
              imagePullPolicy: IfNotPresent
              ports:
                - containerPort: 18080
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: ext-proc-grpc
      labels:
        app: ext-proc-grpc
      annotations:
        gloo.solo.io/h2_service: "true"
    spec:
      ports:
      - port: 4444
        targetPort: 18080
        protocol: TCP
      selector:
        app: ext-proc-grpc
    EOF
      

    The instructions header must be provided as a JSON string in the following format:

      {
      "addHeaders": {
        "header1": "value1",
        "header2": "value2"
      },
      "removeHeaders": [ "header3", "header4" ],
      }
    }
      
  2. Verify that the extProc server is up and running.

      kubectl get pods -n gloo-system | grep ext-proc-grpc
      
  3. Create an Upstream resource that represents the extProc server. Note that you must include the useHttp2: true setting, because the extProc server requires the HTTP/2 protocol.

      kubectl apply -n gloo-system -f- <<EOF        
    apiVersion: gloo.solo.io/v1
    kind: Upstream
    metadata:
      labels:
        app: ext-proc-grpc
        discovered_by: kubernetesplugin
      name: ext-proc-grpc
      namespace: gloo-system
    spec:
      discoveryMetadata: {}
      useHttp2: true
      kube:
        selector:
          app: ext-proc-grpc
        serviceName: ext-proc-grpc
        serviceNamespace: gloo-system
        servicePort: 4444
    EOF
      

Verify extProc

  1. Send a simple request to the httpbin app and make sure that you get back a 200 HTTP response code. The following request passes in two headers header1 and header2 that you see in your response.

    Example output:

       {
         "headers": {
           "Accept": [
             "*/*"
           ],
           "Header1": [
             "value1"
           ],
           "Header2": [
             "value2"
           ],
           "Host": [
             "www.example.com:8080"
           ],
           "User-Agent": [
             "curl/7.77.0"
           ],
           "X-Envoy-Expected-Rq-Timeout-Ms": [
             "15000"
           ],
           "X-Forwarded-Proto": [
             "http"
           ],
           "X-Request-Id": [
             "5ebe6cb0-24fc-427f-9bb7-8aa47e360c94"
          ]
         }
       }
       

  2. Send another request to the httpbin app. This time, you pass along instructions for the extProc server in an instruction header. In the following example, you use the extProc server to add the header3 header, and to remove the header2 header.

    Example output:

       {
         "headers": {
           "Accept": [
             "*/*"
           ],
           "Header1": [
             "value1"
           ],
           "Header3": [
             "value3"
           ],
           "Header4": [
             "value4"
           ],
           "Host": [
             "www.example.com:8080"
           ],
           "User-Agent": [
             "curl/7.77.0"
           ],
           "X-Envoy-Expected-Rq-Timeout-Ms": [
             "15000"
           ],
           "X-Forwarded-Proto": [
             "http"
           ],
           "X-Request-Id": [
             "a3fd7124-8485-45d5-8326-cf025bc7a01c"
           ]
         }
       }
       

Overwrite gateway settings with RouteOptions

  1. Create a RouteOption resource that overwrites the gateway-level settings. In this example, you want to skip sending request headers to the extProc server.

      kubectl apply -f- <<EOF
    apiVersion: gateway.solo.io/v1
    kind: RouteOption
    metadata:
      name: extproc
      namespace: httpbin
    spec:
      options:
        extProc:
          overrides: 
            processingMode: 
              requestHeaderMode: SKIP
    EOF
      
  2. Create an HTTPRoute resource for the httpbin app that references the RouteOption resource that you created for the extproc.example domain.

      kubectl apply -f- <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: httpbin-extproc
      namespace: httpbin
    spec:
      parentRefs:
      - name: http
        namespace: gloo-system
      hostnames:
        - extproc.example
      rules:
        - filters:
            - type: ExtensionRef
              extensionRef:
                group: gateway.solo.io
                kind: RouteOption
                name: extproc
          backendRefs:
            - name: httpbin
              port: 8000
    EOF
      
  3. Send a request to the httpbin app and pass along instructions for the extProc server in an instruction header. Verify that the request header information is not processed because you configured Gloo Gateway to skip sending request headers to the extProc server for that route. For example, the header2 header is not removed, and header3 and header4 are not added. Instead, you get back the instructions in an instructions header.

    Example output:

       {
         "headers": {
           "Accept": [
             "*/*"
           ],
           "Header1": [
             "value1"
           ],
           "Header2": [
             "value2"
           ],
           "Host": [
             "extproc.example:8080"
           ],
           "Instructions": [
             "{\"addHeaders\":{\"header3\":\"value3\",\"header4\":\"value4\"},\"removeHeaders\":[\"instructions\", \"header2\"]}"
           ],
           "User-Agent": [
             "curl/7.77.0"
           ],
           "X-Envoy-Expected-Rq-Timeout-Ms": [
             "15000"
           ],
           "X-Forwarded-Proto": [
             "http"
           ],
           "X-Request-Id": [
             "c896a2ec-2dc2-4f91-8836-5377f2c53e7d"
           ]
         }
       }
       

  4. Change the RouteOption resource and set processingMode.requestHeaderMode: SEND to send request headers for that route.

      kubectl apply -f- <<EOF
    apiVersion: gateway.solo.io/v1
    kind: RouteOption
    metadata:
      name: extproc
      namespace: httpbin
    spec:
      options:
        extProc:
          overrides: 
            processingMode: 
              requestHeaderMode: SEND
    EOF
      
  5. Send another request to the httpbin app. Verify that your instructions are now processed, and header3 header is added and the header2 header is removed.

    Example output:

       {
         "headers": {
           "Accept": [
             "*/*"
           ],
           "Header1": [
             "value1"
           ],
           "Header3": [
             "value3"
           ],
           "Header4": [
             "value4"
           ],
           "Host": [
             "extproc.example:8080"
           ],
           "User-Agent": [
             "curl/7.77.0"
           ],
           "X-Envoy-Expected-Rq-Timeout-Ms": [
             "15000"
           ],
           "X-Forwarded-Proto": [
            "http"
           ],
           "X-Request-Id": [
             "943e4d99-f6c7-465e-9a25-be760220f7ec"
           ]
         }
       }
       

Use multiple extProc filter variants

You can configure extProcEarly and extProcLate alongside extProc to run multiple external processors at different stages of the filter chain. For example, you might want to debug your extProc server by logging requests at both the earliest and latest stages so that you can compare what changed in between. You can also use this setup to integrate with different extProc servers.

  1. Update the default Settings resource to configure all three extProc variants. In this example, all extProc variants use the same extProc server. However, you can configure a specific extProc server for each phase. The extProc stages are processed as follows:

    • extProcEarly: Requests are modified before the Fault Envoy filter, which is the first filter in the filter chain.
    • extProc: Requests are modified after the AuthZ Envoy filter.
    • extProcLate: Requests are modified in the upstream_http_filter that is part of the Router phase. Note that although you must provide a filterStage setting, this setting is ignored as the extProcLate variant is always executed as part of the upstream_http_filter filter.
      kubectl edit settings default -n gloo-system
      

    Update your settings as follows:

      extProcEarly:
      grpcService:
        extProcServerRef:
          name: ext-proc-grpc
          namespace: gloo-system
      filterStage:
        stage: FaultStage
        predicate: Before
      processingMode:
        requestHeaderMode: SEND
        responseHeaderMode: SEND
    extProc:
      grpcService:
        extProcServerRef:
          name: ext-proc-grpc
          namespace: gloo-system
      filterStage:
        stage: AuthZStage
        predicate: After
      failureModeAllow: false
      allowModeOverride: false
      processingMode:
        requestHeaderMode: SEND
        responseHeaderMode: SKIP
    extProcLate:
      # The filter stage is ignored as it is always executed in the upstream_http_filter.
      filterStage:
        stage: AuthZStage
        predicate: After
      grpcService:
        extProcServerRef:
          name: ext-proc-grpc
          namespace: gloo-system
      processingMode:
        requestHeaderMode: SEND
        responseHeaderMode: SEND
      
  2. Create an HTTPRoute resource to expose the httpbin app on the gateway.

      kubectl apply -f- <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: httpbin-extproc
      namespace: httpbin
    spec:
      parentRefs:
      - name: http
        namespace: gloo-system
      hostnames:
        - extproc.example
      rules:
        - backendRefs:
            - name: httpbin
              port: 8000
    EOF
      
  3. Send a request to the httpbin app.

    Verify that you get back a 200 HTTP response code.

      HTTP/1.1 200 OK
      
  4. Check the extProc server logs to verify that it received 3 processing requests (one for each stage). Because each variant sends request headers (requestHeaderMode: SEND), the server receives three separate gRPC processing calls per request.

      kubectl logs -l app=ext-proc-grpc -n gloo-system --tail=50
      

    Example output:

    "Process"
    "Got RequestHeaders"
    "Sending ProcessingResponse"
    "Process"
    "Got RequestHeaders"
    "Sending ProcessingResponse"
    "Process"
    "Got RequestHeaders"
    "Sending ProcessingResponse"
    "Got ResponseHeaders"
    "Sending ProcessingResponse"

Cleanup

  1. Remove the resources that you created in this guide.

      kubectl delete httproute httpbin-extproc -n httpbin
    kubectl delete routeoption extproc -n httpbin
    kubectl delete upstream ext-proc-grpc -n gloo-system
    kubectl delete deployment ext-proc-grpc -n gloo-system
    kubectl delete service ext-proc-grpc -n gloo-system
      
  2. Edit the Settings resource and remove the extProc settings.

      kubectl edit settings default -n gloo-system