I want my Ingress (NGINX) to filter by source IP address and show a basic auth before proxying to a service. While this is straightforward, the complicated part is, that I want it to do this only, if the URL contains a special character in the path.
Lets say I want to secure all paths that start with a "+" before proxying them to the correct service. On the other hand I still want that paths that do not start with a "+" will be routed (without basic auth) to the same service. It should also not change the URL that the service will see.
Examples would be:
/serviceA/what/ever -> http://192.168.0.2/what/ever
/serviceA/what/+ever -> BASIC_AUTH -> http://192.168.0.2/what/+ever
/serviceB/what/ever -> http://192.168.0.3/what/ever
/serviceB/+what/ever -> BASIC_AUTH -> http://192.168.0.3/+what/everIs it possible to achieve this either in Ingress or at least in a NGINX config? The regex for the URL path is also quite simple in NGINX but is it possible without duplicating all path entries and also without adding a second proxy nginx in front?
The ideal solution would be in Ingress yml config but I'm more familar with NGINX, so here is an example what I want to achieve in NGINX-Syntax:
Location ~ /+ {
auth_basic ...;
auth_basic_user_file ...;
< route it somehow to the similar location as it would have no +, but don't cut out the + >
}
Location /serviceA {
proxy_pass ...;
}
... more Locations ...
Or in Ingress something similar with path-entries.
You can use nginx regexes in yaml path fields.
To have auth in one and not in the other, you have to create 2 ingresses (since the auth annotations are per-ingress, not per-path). Having 2 ingresses for the same host is perfectly OK, nginx-ingress will merge them.
Something like this should work:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: without-auth
spec:
rules:
- host: example.com
http:
paths:
- path: /
backend:
serviceName: your-backend-service
servicePort: 80
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: with-auth
annotations:
# type of authentication
nginx.ingress.kubernetes.io/auth-type: basic
# name of the secret that contains the user/password definitions
nginx.ingress.kubernetes.io/auth-secret: basic-auth
# message to display with an appropriate context why the authentication is required
nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - foo'
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
rules:
- host: example.com
http:
paths:
- path: ^/+
backend:
serviceName: your-backend-service
servicePort: 80To debug if it doesn't work, or to check the result matches your expectations, you can view the generated nginx config like this (replace namespace and pod name with yours).
kubectl -n nginx-ingress exec nginx-ingress-controller-76458655df-sddg2 -- cat /etc/nginx/nginx.confFirst of all, your:
location ~ /+ {
auth_basic ...;
auth_basic_user_file ...;
< route it somehow to the similar location as it would have no +, but don't cut out the + >
}
Would only match servicex/+something , not the servicex/something/+nice
The regex you are searching is something like:
location ~ ^/(.*)\+(.*) for the "+" to be anywhere
location ~ ^(.*)\/\+(.*) for the "+" to be only after a "/"For the part:
< route it somehow to the similar location as it would have no +, but don't cut out the + >Like this you'll send the uri exactly like it came:
proxy_pass http://192.168.0.2$request_uri; And like this you'd take out the "+"
proxy_pass http://192.168.0.2$1/$2; Where $1 is the (.*) before the /+ and $2 is everything after, and we add the lacking / in the middle.
I think that will help you on what I think you want to do.
If you have any questions ask them, I feel I'm lost at some part of your explanation and my answer is not 100% on point.
Hope I helped.