Contour Integration

This guide explains how to integrate heimdall with Contour, an open source, high performance ingress controller for Kubernetes.

Contour is an ingress controller for Kubernetes, implementing a control plane for Envoy edge and a service proxy.

Prerequisites

  • Integration with Contour requires heimdall being operated in Decision Operation Mode exposing Envoy’s external authorization GRPC protocol.

  • Being security first ingress controller, Contour enforces TLS for communication between Envoy and any external authorization service. For that reason, heimdall must be configured with an appropriate key material and certificate. Same is actually also true for the http route definition of the actual upstream service. The only exception is when configuring Contour using heimdall as a global external auth service.

General Configuration

The official External Authorization Guide from Contour describes the required steps in great detail. While following it, please make attention to the following details specific to heimdall as described below.

  • If you use cert-manager, ensure the feature gate AdditionalCertificateOutputFormats is set to true. This lets cert-manager creating secrets with a property named tls-combined.pem, combining both the key and the certificate in one object, as also typically provided by any other CA and expected by heimdall.

  • When you configure the Certificate resource to let cert-manager issue a TLS certificate for heimdall, configure the additionalOutputFormats property with the type CombinedPEM to make use of the aforesaid feature gate and have the tls-combined.pem property set in the resulting secret. Here a small snippet showing the relevant parts:

    apiVersion: cert-manager.io/v1
    kind: Certificate
    spec:
      # ...
      additionalOutputFormats:
        - type: CombinedPEM
      # ...
  • If TLS is enabled, which, as said above, is required for integration with Contour, by default heimdall is configured to support TLS v1.3 only. However, it looks like Contour does not configure Envoy to support TLS v1.3 so that the communication with heimdall happens via TLS v1.2 and below. For that reason you have to configure the decision service of heimdall to TLS v1.2 being the minimum supported version. Otherwise, Envoy will not be able communicating with heimdall, resulting in 403 responses for any request. The following snippet shows the relevant parts in the heimdall configuration file:

    # ...
    serve:
      decision:
        tls:
          # important! see explanations above
          min_version: TLS1.2
          key_store:
            # path to the pem file with key and certificates
            path: /certs/tls-combined.pem
    # ...
  • Ensure heimdall is started in Decision Operation Mode exposing Envoy’s external authorization GRPC protocol (achieved by passing the --envoy-grpc flag while starting heimdall) and the required secret with the TLS key material is available to the heimdall container. The following snippet shows the relevant values configuration if you use helm for installing/updating heimdall:

    extraArgs:
      - --envoy-grpc
    deployment:
      volumes:
      - name: tls-cert-volume
        secret:
          secretName: <name of the corresponding secret>
      volumeMounts:
      - name: tls-cert-volume
        readOnly: true
        mountPath: /certs
  • Define an ExtensionService as described in the referenced Contour guide for heimdall and also shown below

    apiVersion: projectcontour.io/v1alpha1
    kind: ExtensionService
    metadata:
      namespace: <namespace in which heimdall is installed>
      name: heimdall-ext-service
    spec:
      protocol: h2
      services:
        - name: heimdall
          port: 4456

    The ExtensionService resource definition tells Contour to program Envoy with an upstream cluster directing traffic to heimdall. That way, as also described in the Envoy Integration Guide, Envoy will delegate authentication and authorization to heimdall. If heimdall answers with a 200 OK HTTP code, Envoy grants access and forwards the original request to the upstream service. Otherwise, the response from heimdall is treated as an error and is returned to the client.

Global Configuration

A global configuration allows you to setup a single external authorization configuration for all your virtual hosts (HTTP and HTTPS). The only thing you have to do is to reference the ExtensionService, defined above in your Contour config. This is achieved with the following snippet:

globalExtAuth:
  extensionService: <namespace in which heimdall is installed>/<name of the extention service>
  failOpen: false
  responseTimeout: 1s

You can now define your Ingress Rules. When using HTTPProxy resources instead, Contour allows overriding or disabling of the external auth service on the route level for HTTPs routes.

Route-based Configuration

The only way to have route based external auth service configuration in Contour, is the usage of HTTPProxy resource instead of the regular Ingress rules, allowing referencing the ExtensionService. Here an example:

apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
  name: echo-app
  namespace: quickstarts
  labels:
    app.kubernetes.io/name: echo-app
spec:
  virtualhost:
    fqdn: echo-app.local
    tls:
      secretName: echo-app
    authorization: (1)
      extensionRef:
        namespace: heimdall
        name: heimdall-ext-service
  routes:
    - conditions:
        - prefix: /
      services:
        - name: echo-app
          port: 8080
1Reference to the ExtensionService.

Additional Resources

Checkout the examples on GitHub for a working demo.

Last updated on Mar 18, 2024