V.Junior
V.Junior

Reputation: 29

Istio EnvoyFilter Lua HttpCall doesn't work with HTTPS?

I need to decrypt the body of a request in an external API. But, when I try to do it with an EnvoyFilter using lua it doesn't work. If I try the same code that I'm posting here, but without HTTPS, works. But with HTTPS returns 503.

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: eva-decrypt-filter
  namespace: istio-system
spec:
  configPatches:
    - applyTo: HTTP_FILTER
      match:
        context: ANY
        listener:
          filterChain:
            filter:
              name: "envoy.filters.network.http_connection_manager"
      patch:
        operation: INSERT_BEFORE
        value:
          name: envoy.lua
          typed_config:
            "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
            inlineCode: |
              function envoy_on_request(request_handle)
               local buffered = request_handle:body()
               local bodyString = tostring(buffered:getBytes(0, buffered:length()))
               print("bodyString ->")
               print(bodyString)
               if string.match(bodyString, "valcirtest") then
                print("iniciando http_Call")
                local responseHeaders, responseBody = request_handle:httpCall(
                  "thirdparty",
                  {
                   [":method"] = "POST",
                   [":path"] = "/decrypt",
                   [":authority"] = "keycloack-dev-admin.eva.bot",
                   [":scheme"] = "https",
                   ["content-type"] = "application/json",
                   ["content-length"] = bodyString:len(),
                  },
                  bodyString,
                  3000)
                print("acabou a requisicao")
                print("responseHeaders -> ")
                print(responseHeaders)
                print(responseHeaders[":status"])
                print("responseBody -> ")
                print(responseBody)
                local content_length = request_handle:body():setBytes(responseBody)
                request_handle:headers():replace("content-length", content_length)
               else
                print("nao entrou")
               end
              end
    - applyTo: CLUSTER
      match:
        context: SIDECAR_OUTBOUND
      patch:
        operation: ADD
        value: # cluster specification
          name: thirdparty
          connect_timeout: 1.0s
          type: STRICT_DNS
          dns_lookup_family: V4_ONLY
          lb_policy: ROUND_ROBIN
          load_assignment:
            cluster_name: thirdparty
            endpoints:
              - lb_endpoints:
                  - endpoint:
                      address:
                        socket_address:
                          protocol: TCP
                          address: keycloack-dev-admin.eva.bot
                          port_value: 443

The response error is:

503
responseBody ->
upstream connect error or disconnect/reset before headers. reset reason: connection termination

I'm using Istio v.1.11.4.

Upvotes: 2

Views: 1250

Answers (3)

Ivan Meireles
Ivan Meireles

Reputation: 1

You can do this way.

kind: ServiceEntry
apiVersion: networking.istio.io/v1beta1
metadata:
  name: externalhttps-se
  namespace: istio-system
spec:
  hosts:
    - externalhttps.domain.com
  ports:
    - number: 443
      protocol: HTTPS
      name: http
      targetPort: 443
  resolution: DNS

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: externalhttps-dr
  namespace: istio-system
spec:
  host: externalhttps.domain.com
  trafficPolicy:
    portLevelSettings:
    - port:
        number: 443
      tls:
        mode: SIMPLE
        sni: externalhttps.domain.com

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: externalhttps-ef
  namespace: istio-system
spec:
  workloadSelector:
    labels:
      istio: curity-ingress
  configPatches:
  - applyTo: HTTP_FILTER
    match:
      context: GATEWAY
      listener:
        filterChain:
          filter:
            name: "envoy.filters.network.http_connection_manager"
    patch:
      operation: INSERT_BEFORE
      value: 
       name: envoy.filters.http.lua
       typed_config:
          "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
          defaultSourceCode:
            inlineString: |
              function envoy_on_request(request_handle)

                local resp_headers, resp_body = request_handle:httpCall(
                  "outbound|443||externalhttps.domain.com", 
                  {
                    [":method"] = "GET",
                    [":path"] = "/",
                    [":authority"] = "externalhttps.domain.com"
                  }, 
                  nil,
                  5000)
                
              end

Upvotes: 0

David S.
David S.

Reputation: 11148

To add to @koffi-kodjo's answer, you also need to specify the typed_config property. The transport_socket node should be placed at the same level of the name: thirdparty node.

        transport_socket:
          name: envoy.transport_sockets.tls
          typed_config: 
            "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext

ref:

Upvotes: 0

koffi kodjo
koffi kodjo

Reputation: 11

It should be configured on your "thirdparty" cluster adding the following on your cluster config:

transport_socket:
  name: envoy.transport_sockets.tls

Upvotes: 1

Related Questions