jcmoraisjr / haproxy-ingress

HAProxy Ingress
https://haproxy-ingress.github.io
Apache License 2.0
1.05k stars 269 forks source link

Unable to retrive the requested URL in external auth-server while using auth-url annotation #926

Open rohan-97 opened 2 years ago

rohan-97 commented 2 years ago

Description of the problem

Hello, I am trying to integrate an external authentication server using ha-proxy ingress using the auth-url annotation.

the authentication server(Flask server) expects following information to be present in the headers.

  1. Basic auth header
  2. url which was requested from client side
  3. Client IP address

Expected behavior It is expected that when ha-proxy ingress controller creates a request to auth-server, it adds all the headers from the client request and also adds above 3 values in headers.

However when I set up the auth-url, I am able to fetch the basic auth headers and client IP but unable to identify the url which was requested in headers.

Following are the headers received at auth-server by ha-proxy ingress controller

requested url : http://localhost/endpoint

User-Agent: curl/7.74.0
X-Real-Ip: 127.0.0.1
X-Forwarded-Proto: http
Accept: */*
Authorization: Basic dXNlcjE6cGFzc3dvcmQ=
Host: auth-server-service.test-namespace.svc.cluster.local
X-Forwarded-For: 127.0.0.1

I tried same thing with nginx-ingress controller and I get following headers in same auth-server from nginx-controller

X-Request-Id: 67085ed4b2c9f29aefb8f2aeb9dc2434
Host: auth-server-service.test-namespace.svc.cluster.local
X-Original-Url: http://localhost/endpoint
X-Original-Method: GET
X-Sent-From: nginx-ingress-controller
X-Real-Ip: 10.31.2.238
X-Forwarded-For: 10.31.2.238
X-Auth-Request-Redirect: /endpoint
Connection: close
Authorization: Basic dXNlcjE6cGFzc3dvcmQ=
User-Agent: curl/7.74.0
Accept: */*

refer X-Auth-Request-Redirect or X-Original-Url header in nginx headers, we get the requested URL in the headers, however this information is not present in headers added by haproxy ingress.

It is very important to identify which URL was requested so that auth-server can perform custom authentication based on accessed URL.

Steps to reproduce the problem

  1. Setup kubernetes cluster using microk8s
  2. Create a sample echo server listening at url http://localhost/endpoint
  3. Expose echoserver using a service
  4. Add rules to redirect incoming requet to the service.
  5. Add a custom auth server running on following URL (this URL can be of any server, I have hosted a local server hence provided the ip of the server) : "http://192.168.1.3/auth"
  6. log the headers received by custom auth server.
  7. Add annotation haproxy-ingress.github.io/auth-url: "http://192.168.1.3/auth"
  8. Make REST API calls with basic auth headers
  9. check the headers logged by custom auth server.
  10. the url which was accessed would not be present as in the headers received by custom auth-server

CURL syntax:

curl --user user1:password http://localhost/endpoint

Environment information

HAProxy Ingress version: v0.13

Ingress objects:

Ingress yaml file


apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: haproxy-ingress
  namespace: test-namespace
  annotations:
    kubernetes.io/ingress.class: haproxy
    haproxy-ingress.github.io/auth-url: "http://192.168.1.3/auth"
spec:
  rules:
    - host: localhost
      http:
        paths:
          - path: /endpoint
            pathType: Prefix
            backend:
              service:
                name: target-app-service
                port:
                  number: 4567
    - host: localhost
      http:
        paths:
          - path: /token
            pathType: Prefix
            backend:
              service:
                name: auth-server-service
                port:
                  number: 80
    - host: localhost
      http:
        paths:
          - path: /echo
            pathType: Prefix
            backend:
              service:
                name: echoserver
                port:
                  number: 8080

haproxy-ingress-values.yaml

# Default values are present here : https://github.com/haproxy-ingress/charts/blob/release-0.13/haproxy-ingress/values.yaml
controller:
  hostNetwork: true
  dnsPolicy: ClusterFirstWithHostNet
rohan-97 commented 2 years ago

Hi Guys,
Is there any update on this?
Please let me know if I am doing anything wrong or if there are other options/configuration available to achieve this?

Also let me know if anything is the issue is not clear

jcmoraisjr commented 2 years ago

Hi, thanks for the detailed report and sorry about the long delay. Yes it's pretty clear and your request makes sense. I'm not sure you can dynamically configure it, anyway a new tag should be issued shortly adding some new headers.

rohan-97 commented 2 years ago

Hi @jcmoraisjr ,

I used config-backend ingress annotation to add the requested URL in the request headers.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: haproxy-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: haproxy
    haproxy-ingress.github.io/config-backend: |
      http-request set-header X-Auth-Request-Redirect %[capture.req.uri]

This configuration works fine, in the endpoint I am able to see X-Auth-Request-Redirect headers set with requested URL.

But when I include auth-server in configuration (refer below yaml file for configuration) I am not able to see the headers getting set in the request received by auth-server

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: haproxy-ingress
  namespace: pty-service-dispatcher
  annotations:
    kubernetes.io/ingress.class: haproxy
    haproxy-ingress.github.io/config-backend: |
      http-request set-header X-Auth-Request-Redirect %[capture.req.uri]
    haproxy-ingress.github.io/auth-url: "http://auth-server-service.default.svc.cluster.local/auth"

Is there any way I can inject config snippet which will be applied to request being send to auth-server

jcmoraisjr commented 1 year ago

Hi @rohan-97 this issue was in the backlog longer than it should. After digging a bit more into a way to implement that, I just realized that you can use the headers config key to configure additional headers:

      haproxy-ingress.github.io/headers: |
        X-Original-Host %[var(req.host)]
        X-Original-Method %[capture.req.method]
        X-Auth-Request-Redirect %[capture.req.uri]

The only drawback is that it is backend scoped, which means that you cannot add these headers only for some hosts/paths that target a backend, all other hosts/paths targeting the same backend will see these same headers. Planning to add a specific auth-external config which is path scoped, as well as a few more doc about this tip, because of that I'll leave this opened.