Kubernetes Ingress controllers for wildcard url mapping - nginx

I need for each of my users to access a service at a custom url eg. abccompany.mycloudapp.com , each service being a kubernetes service I'm looking at ingress controllers but I need a way to use a wildcard host field and somehow read the value into the path: and service: fields ; here's a sample ingress controller of what I have in mind:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: test
spec:
rules:
- host: *.bar.com
http:
paths:
- path: /{{ value of * in * .bar.com }}
backend:
serviceName: {{value of * in *.bar.com }}Svc
servicePort: 80

If you use the stock controllers you will be able to switch on hostname and go to different backends services. It sounds like you don't want to enumerate all the subdomains -> service mappings, in which case you probably need to write your own controller that writes out an nginx config that uses $http_host in the appropriate proxy_pass or redirect lines. Give it a shot (https://github.com/kubernetes/contrib/tree/master/ingress/controllers) and file bugs in that same repo if you need help.

Related

Nginx ingress controller - Return 200 on root

We are using the Nginx ingress controller in Azure Kubernetes Service to direct traffic to a number of .NET Apis that we run there.
All calls to this are routed via the Azure Application Gateway for WAF and DNS reasons.
Application gateway has "health probes" that hit your backend pools (which point to the external IP of our nginx ingress controller service) performing a GET at the root.
Previously we had services for each site, setup as LoadBalancer, which gave each site their own external IP address, and we pointed the backend pool to that and it worked fine.
But now we are trying to do things more securely and route all calls via the Ingress Controller... but now we have one backend pool with the ingress controller's IP address, and as there's nothing there the health probe comes back unhealthy, and the site doesn't work.
I have setup the Ingress for the site so that if a request hits the backend pool with the domain (below) it will work, but the health probe doesn't seem to do that. As it is just doing a GET on the IP address of the controller.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- host: "api.mydomain.com"
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: my-api-service
port:
number: 443
I installed the controller using the Helm chart, and I just want to be able to set it so that a GET request to that controller will just return 200 and any other request will be directed appropriately. I had tried the below for our ingress, to route a call to the root to the api (which has a 200 response at its root) but I don't think that was the right place for it, and it didn't work. It might have to be part of the Helm command to setup the Ingress controller itself.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-api-service
port:
number: 443
- host: "api.mydomain.com"
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: my-api-service
port:
number: 443
The nginx ingress controller exposes a default backend /healthz endpoint which returns 200 OK. You can make your App gateway health probe to point to this endpoint.
Also, instead of using App gateway + NGINX ingress controller which require 2 hops before reaching your service, consider using Application Gateway ingress controller (AGIC).

Nginx rewrite-target overwritting domain/suffix/index.php to domain/index.php

recently I have deployed an kubernetes cluster which is running wordpress instance and phpmyadmin. I'm using Nginx ingress controller to perform path based routing for both the services. However, request to / is happening without any hassle but when I request domain.com/phpmyadmin/ I get a login page after which I have been redirected to domain.com/index.php instead of domain.com/phpmyadmin/index.php. Please suggest me possible turn around for this. Thank you guys for the support :)
My ingress.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-nginx
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/add-base-url : "true"
nginx.ingress.kubernetes.io/rewrite-target: "/$2"
# ingress.kubernetes.io/rewrite-target: "^/phpmyadmin/"
spec:
rules:
- host: example.domain.com
http:
paths:
- path: /
backend:
serviceName: wordpress
servicePort: 80
- path: /phpmyadmin(/|$)(.*)
backend:
serviceName: phpmyadmin
servicePort: 80
I'd say issue is not on Nginx Ingress side.
nginx.ingress.kubernetes.io/rewrite-target: "/$2"
...
- path: /phpmyadmin(/|$)(.*)
Should work properly for you.
However there is second part, configuration of myphpadmin. As you didn't provide this configuration I would guess what could cause this issue.
Like mentioned in phpmyadmin docs, sometimes you need to set $cfg['PmaAbsoluteUri']
In some setups (like separate SSL proxy or load balancer) you might have to set $cfg['PmaAbsoluteUri'] for correct redirection.
As I based on this configuration, many depends on how you configured PMA_ABSOLUTE_URI, is it http://somedomain.com/phpmyadmin or different?
Is important as you might encounter situation like:
When you enter to http://somedomain.com/phpmyadmin and login you will be redirected to http://somedomain.com/ so Ingress will redirect you to path: / set in ingress
If you will again enter http://somedomain.com/phpmyadmin you will be able to see phpmyadmin content, like you would be already logged in.
You could try to add env in your myphpadmin deployment. It would look similar like below:
env:
- name: PMA_ABSOLUTE_URI
value: http://somedomain.com/myphpadmin/
Last thing, its not recommended to use expose phpmyadmin without https.
For some extra information you can read this article.
In short:
Nginx ingress configuration looks ok
Check your myphpadmin configuration, especially PMA_ABSOLUTE_URI.

Move `X-Accel-Redirect` pattern for protected static in kubernetes setup

We are moving to kubernetes and we are totally new to it.
In our current mono service setup we have: Nginx -> Web application. These way we can protect some static assets via authentication in the web application and use internal and X-Accel-Redirect of Nginx to serve static files after authentication takes place.
Now in kubernetes we have Ingress and behind these services:
web app
private static service
Is there a way to tell in ingress from the web application to "redirect" the request as we kind of do with sendfile, so that the private static service will reply to it? Or somehow to achieve protecting our static while keeping the static service separate and independent in kubernetes setup?
We kind of made it work by chaining the private static service in front of the web application, but it feels there must be a better way to do it.
Here is how I managed to make it work.
I created two ingresses.
First:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
internal;
nginx.ingress.kubernetes.io/rewrite-target: /some/path/$1
name: static-service-internal
spec:
rules:
- http:
paths:
- backend:
serviceName: private-static-service
servicePort: 80
path: /protected/(.*)
and second service:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
name: web-app
spec:
rules:
- http:
paths:
- backend:
serviceName: web-app
servicePort: 80
path: /
What you see above is supposed to work as in this example from nginx documentation
When receiving X-Accel-Redirect: /protected/iso.img from web-app then it will request /some/path/iso.img from private static service.
Let me know if this solves you problem.

Nginx Ingress pass whole url to oauth proxy as Redirect

I am running a Kubernetes Cluster with an Nginx-ingress fronting couple of web apps. Because Nginx doesn't support SSO/OIDC by default, I use an oauth_proxy for authentication.
In detail I use oauth2_proxy (https://github.com/pusher/oauth2_proxy) with Azure AD.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginx-ingress-internal
namespace: ingress-nginx
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/auth-url: "https://example.com/oauth2/auth"
nginx.ingress.kubernetes.io/auth-signin: "https://example.com/oauth2/start?rd=$escaped_request_uri"
nginx.ingress.kubernetes.io/auth-response-headers: "authorization, x-auth-request-user, x-auth-request-email, x_auth_request_access_token"
spec:
rules:
- host: example.com
http:
paths:
- path: /home(/|$)(.*)
backend:
serviceName: app-homepage-frontend-service
servicePort: 80
- path: /homepage-backend(/|$)(.*)
backend:
serviceName: app-homepage-backend-service
servicePort: 80
I skiped some details like tls. So in general everything is working, only verified users are able to access the web pages.
The issue is that my frontend is writte in Angular which use hash-routing. And if try to enter a deep route like
https://example.com/home/#/page1/subpage2
just base path (/home) is passed as redirect url. So when I'm authorized successfully, I get redirected to https://example.com/home.
Is there any veriable instead of $escaped_request_uri, which pass the whole url?
Please try with below process might be it will help!!
Adding State Parameter will help for oauth2_proxy
State Parameter
State parameter will reserve the state prior to authentication request and pass random generated state value in request to authenticate and in call back request they will add state back i.e. Oauth2_Proxy generated id. Then Oauth2_Proxy will read that ID and provide the URL back and respond.
Use below link
https://dev.bitly.com/v4_documentation.html
Bitly Oauth2_Proxy added the same in there code.
https://github.com/bitly/oauth2_proxy/blob/master/providers/provider_default.go#L87-L89

Is it possible to rewrite HOST header in k8s Ingress Controller?

Due to some legacy application that relies on Host header to function correctly, I need to have an Ingress (proxy, etc) that capable of rewrite Host header and pass that to downstream (backend). Is there any Ingress Controller that supports this functionality?
Example:
End user access our website through foo.com/a for backend a and foo.com/b for backend b. But since a and b are legacy app, it only accept:
a accepts connection when Host: a.foo.com
b accepts connection when Host: b.foo.com
This can be done using this annotation: nginx.ingress.kubernetes.io/upstream-vhost: host.example.com
I'm not sure whether you can find appropriate annotation within NGINX Ingress Controller for Host header modification to match your requirement as well. However, you can consider using nginx.ingress.kubernetes.io/configuration-snippet annotation in order to append configuration snippet to the location block inside nginx.conf of the particular Nginx controller pod:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_set_header Host www.example-host.com;
name: my-app
spec:
rules:
- host: my-app.example.com
http:
paths:
- backend:
path: /app
serviceName: my-app
servicePort: http
We set here Host header www.example-host.com for target URL my-app.example.com.
I want to add my finding to this question of mine.
Although my solution is not using k8s Ingress Controller, our cluster is using Istio and Istio's VirtualService supports rewrite the uri and authority (Host header) as documented in this link: https://istio.io/docs/reference/config/istio.networking.v1alpha3/#HTTPRewrite
To know how I implement that in my case, you can take a look at this link: https://github.com/istio/istio/issues/11668
you can use ingress nginx controller on Kubernetes and set head and also transfer to backend and manage services connection from ingress objects.
here sharing link for rewrite target from header: https://kubernetes.github.io/ingress-nginx/examples/rewrite/
ingress nginx will be also good with SSL cert manager you can add it.
manage other thing using annotations of ingress.
check this out for ingress SSL setup you can modify it and per your need: https://www.digitalocean.com/community/tutorials/how-to-set-up-an-nginx-ingress-with-cert-manager-on-digitalocean-kubernetes
ingress will be like at last
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
tls:
- hosts:
- myapp.abc.com
secretName: ingress-tls
rules:
- host: myapp.abc.com
http:
paths:
- path: /my-service
backend:
serviceName: my-backend
servicePort: 80

Resources