3

I have an nginx-ingress calling a custom auth-service before sending requests to the backend service, using this simple ConfigMap and Ingress:

apiVersion: v1
kind: ConfigMap
metadata:
  ...
data:
  global-auth-url: auth-service-url:8080/authenticate
  global-auth-method: GET
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: "nginx"
  ...
spec:
  rules:
  - host: host1
    http:
      paths:
      - backend:
          serviceName: backend-service
          servicePort: 8080 

Now I need something different.

How can I send requests, all with the same "Host" header, through different flows, one with auth-service and connected to backend-service1 and the other without any authentication and connecting to backend-service2?

To be clear, and using the custom header "Example-header: test"

  1. If "Example-header" is "test", authenticate via my auth-service before sending to backend-service, as it's done now.
  2. If "Example-header" is not defined, I want to send requests to a different backend service and do not use auth-service in the process.

I tried a couple of things, namely having 2 Ingresses, one with global-auth-url and the other with nginx.ingress.kubernetes.io/enable-global-auth: "false" but the auth-service is always called.

Can I do this with NGINX, or do I have to use Istio or Ambassador?

João Pereira
  • 673
  • 1
  • 9
  • 29
  • Maybe this will help: https://stackoverflow.com/a/63374847/14484111 – Cloudziu Oct 31 '21 at 09:29
  • I tried that but it still makes a call to the `auth-service` that I want to avoid. – João Pereira Nov 03 '21 at 09:45
  • @JoãoPereira Did you try to implement the provided solution without `auth-service`? Just to check the possibility for Headers usage for redirection: with configuration-snippet and "test" in Header it connects to `backend-service1` and without "test" in Header to `backend-service2` respectivly. – Andrew Skorkin Nov 08 '21 at 21:58

1 Answers1

6

One way you can achieve this behavior is by abusing the canary feature.

For your backend-service, create a normal Ingress, e. g.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-backend
spec:
  ingressClassName: nginx
  rules:
  - host: localhost
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: backend-service
            port:
              number: 80

Create a second Ingress for you auth-service with enabled canary and set the header name and value, e. g.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-auth
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-header: Example-header
    nginx.ingress.kubernetes.io/canary-by-header-value: test
spec:
  ingressClassName: nginx
  rules:
  - host: localhost
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: auth-service
            port:
              number: 80

Now, every request with Example-header: test routes to auth-service. Any other value, e. g. Example-header: some-value, will not route to auth-service but rather go to your backend-service.

malte.h
  • 73
  • 1
  • 7
  • 2
    Note that [the documentation](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#canary) states that a maximum of 1 canary is supported, so this cannot be used to support multiple API versions for exampe. – user239558 Mar 28 '23 at 09:52