Istio EnvoyFilter Lua HttpCall doesn't work with HTTPS?

3 min read 05-10-2024
Istio EnvoyFilter Lua HttpCall doesn't work with HTTPS?


Istio EnvoyFilter Lua HttpCall: Why HTTPS Doesn't Always Play Nice

Istio's powerful EnvoyFilter allows fine-grained control over Envoy's behavior using Lua scripts. One common use case is using the HttpCall function to interact with external services. However, many users encounter issues when trying to use HttpCall with HTTPS connections. This article will delve into the reasons behind these challenges and provide solutions for overcoming them.

The Scenario: A Frustrating HTTPS Connection

Let's imagine you're trying to implement a simple EnvoyFilter that makes a secure HTTPS request to an external API:

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: https-call-example
spec:
  workloadSelector:
    labels:
      app: my-service
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: SIDECAR_INJECTION
      listener:
        portNumber: 8080
    patch:
      operation: INSERT_BEFORE
      value:
        code:
          "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v3.HttpFilter
          name: lua-filter
          config:
            "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.Lua
            inlineCode: |
              function envoy_on_request(request_handle)
                local response = request_handle:HttpCall({
                  method: "GET",
                  path: "/api/v1/data",
                  hostname: "api.example.com",
                  port: 443,
                  use_tls: true
                })
                -- Process response here
              end

This EnvoyFilter aims to perform an HTTP GET request to api.example.com on port 443, using HTTPS. However, you'll likely find that this code snippet fails to connect successfully, often leading to errors related to certificate validation.

Understanding the Challenge: The Missing Pieces

The issue stems from the fact that Envoy, by default, doesn't automatically trust any certificates for HTTPS connections made within a Lua HttpCall. This is a security measure to prevent potential vulnerabilities.

Here's a breakdown of the problem:

  1. Default behavior: Envoy, in its standard configuration, doesn't know about your external API's certificate. It relies on the root certificates present in the system's trust store.
  2. Certificate validation: When the HttpCall is made, Envoy attempts to verify the certificate presented by the API. Without proper trust configuration, this validation fails, leading to the connection error.

Solutions: Bridging the Gap

To resolve this, we need to provide Envoy with the necessary information to trust the API's certificate. There are two main approaches:

  1. Trust Store Configuration:

    • Using Secret Volumes: You can mount a secret volume containing the API's certificate into the Envoy container. This allows Envoy to use the specified certificate during verification.
    • Manual Configuration: Alternatively, you can configure Envoy to use a specific trust store file through the trust_chain parameter in the http_connection_manager configuration.
  2. Disabling SSL Verification:

    • Caution: This approach should only be used in controlled environments with a high level of trust in the external API, as it circumvents certificate validation.

Here's an example of how you can update your EnvoyFilter to include a trusted certificate:

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: https-call-example
spec:
  workloadSelector:
    labels:
      app: my-service
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: SIDECAR_INJECTION
      listener:
        portNumber: 8080
    patch:
      operation: INSERT_BEFORE
      value:
        code:
          "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v3.HttpFilter
          name: lua-filter
          config:
            "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.Lua
            inlineCode: |
              function envoy_on_request(request_handle)
                local response = request_handle:HttpCall({
                  method: "GET",
                  path: "/api/v1/data",
                  hostname: "api.example.com",
                  port: 443,
                  use_tls: true,
                  tls_context: {
                    alpn: "h2",
                    trust_chain: "path/to/certificate.pem" 
                  }
                })
                -- Process response here
              end

In this example, we've added the tls_context parameter to the HttpCall configuration. This allows you to specify the path to the certificate file (trust_chain) that should be used for verification.

Conclusion

By understanding the reasons behind certificate validation issues and implementing the appropriate solutions, you can successfully use the Istio EnvoyFilter Lua HttpCall function to interact with secure HTTPS services. Remember to prioritize security and only disable verification when absolutely necessary.

For further reference, consult the official Istio documentation on EnvoyFilter and the Lua filter configuration: