GKE ingress pass cookie as header - nginx

I would like to use some kubernetes ingress (doesn't matter the ingress type) on google cloud GKE 1.19.7-gke.1302, and nginx ingress deployed by nginx-ingress-0.8.0 helm chart, and my need is to fetch a cookie and use it later to authenticate to our service. When I use nginx as deployment it works, but when I use nginx ingress it seems to ignore the annotation.
I tried using this configuration snippet for the nginx ingress, which works on the nginx deployment but not on the ingress:
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_set_header "Authorization" "Basic $cookie_myToken";
And this is my entire ingress yaml:
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-nginx-ingress
namespace: default
annotations:
kubernetes.io/ingress.class: nginx
# enable backend redirections
kubernetes.io/tls-acme: "true"
# enable stickiness
nginx.ingress.kubernetes.io/affinity: "cookie"
nginx.ingress.kubernetes.io/session-cookie-name: "route"
nginx.ingress.kubernetes.io/session-cookie-expires: "172800"
nginx.ingress.kubernetes.io/session-cookie-max-age: "172800"
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_set_header "Authorization" "Basic $cookie_myToken";
spec:
tls:
- secretName: my-tls
hosts:
- "test.com"
defaultBackend:
service:
name: my-nodeport
port:
number: 80
rules:
- host: "test.com"
http:
paths:
- path: /
pathType: ImplementationSpecific
backend:
service:
name: my-nodeport
port:
number: 80
Any ideas?

Posting this answer to make it more visible as issue was identified and solved in comment section.
Root cause of this issue was Nginx Ingress Controller misconfiguration.
In the OP's setup Nginx Ingress Controller, v.0.8.0 was used. After redeploying Nginx Ingress to latest version (v0.44.0) from Nginx Ingress Documentation it started working properly.
Yes, reinstalling nginx ingress to the latest version with helm solved the problem.

Related

Kubernetes Nginx Ingress - Rewrite Dynamic URL

Here i have kubernetes running on minikube and it has 2 services backend and frontend. And i have installed ingress addon for minikube.
I wanted to rewrite whenever the frontend request the path url is /users/{user-id} it goes to backend service with the same url dynamically.
Let say the request is /users it rewrite to backend service to /users, /users/1 it goes to /users/1.
I tried to read nginx manual found some special expression i don't understand.
This is my ingress configuration.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-be
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /users/$1
spec:
ingressClassName: nginx
rules:
- host: backend
http:
paths:
- path: /users/(.*)
pathType: Prefix
backend:
service:
name: backend
port:
number: 5000
My configuration seems fine when the request is /users/{users-id} but when the request is /users, my ingress won't redirect me to '/users' in backend service.
When i tested with curl, this is the output.
curl http://backend/users/3
{"id":3,"name":"Sofia","email":"sofia#gmail.com","gender":"Female","createdAt":"2022-04-05T15:46:46.000Z","updatedAt":"2022-04-05T15:46:46.000Z"}%
curl http://backend/users
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
What am i missing here?
Thank you in advance for your help!
Update!
Andreas in the comment suggest me to use /users/ and it works!
Then i decided to modified my ingress configuration.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-be
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /users/$2
spec:
ingressClassName: nginx
rules:
- host: backend
http:
paths:
- path: /users(/|$)(.*)
pathType: Prefix
backend:
service:
name: backend
port:
number: 5000

nginx ingress redirect traffic

I deployed nginx ingress controller and randomApp to minikube cluster.
I have 2 requirements:
All traffic for "random/.*" should go to the random service
Other paths should go to the nginx.
This configuration is correct?
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: path-rule-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
defaultBackend:
service:
name: ingress-nginx-controller
port:
number: 80
rules:
- host: random.localdev.me
http:
paths:
- path: /random/(.*)
backend:
service:
name: random
port:
number: 8000
pathType: Prefix
You also need to add metadata.annotations: kubernetes.io/ingress.class: "nginx" or spec.ingressClassName: nginx to allow nginx-ingress-controller to discover the ingress.
Also you shouldn't define default backend service as ingress-nginx-controller. Because you will get 503 Service Temporarily Unavailable since nginx-ingress-controller's nginx.conf didn't be configured for this. You can give another nginx server's service for it.

Nginx Ingress resource annotation to setup proxy_pass directive

When I use nginx as ingress controller for my k8s cluster, specifying an ingress rule automatically creates corresponding configurations in the /etc/nginx/conf.d/ files of nginx pod.
So, it configures proxy_pass directive there to relevant upstream/backend service. And it is http.
For this ingress rule for my service:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: my-ingress
# annotations:
# nginx.org/redirect-to-https: "false"
# #nginx.ingress.kubernetes.io/ssl-passthrough: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- test.myapp.com
secretName: test-tls-secret
rules:
- host: test.myapp.com
http:
paths:
- backend:
serviceName: myui
servicePort: 80
- path: /api/
backend:
serviceName: myapp
servicePort: 88
By default, it automatically creates this directive for backend in nginx configuration:
proxy_pass http://default-my-ingress-test.myapp.com-myapp-88;
But instead, i need it to be https like this:
proxy_pass https://default-my-ingress-test.myapp.com-myapp-88;
Then only my application will work as that backend accepts https requests only.
Is there any way to modify that proxy_pass directive for a particular backend service for this purpose, using any annotations or something like that via Ingress resource?
EDIT:
Is there any annotation like that available?
Or Is there any option that I could handle it with a sidecar container in the same pod with the actual myapp container?
I had a similar requirement very recently where the backend pods expected the request on https.
What you'd need is ssl-passthrough feature of nginx controller. You need to start the nginx ingress controller with flag --enable-ssl-passthrough. This can be passed as a command line argument to the nginx deployment.
Thereafter, the ingress resource needs to be deployed with the following annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
nginx.ingress.kubernetes.io/secure-backends: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
to instruct the controller to send TLS connections directly to the backend.

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

Nginx headers not appearing with Ingress controller

I'm having a problem where my NGINX headers are not showing when I connect to the ingress controller's IP. For example, let's say I have a HTTP header called "x-Header" setup in my NGINX config map. If I go to the ingress controller's IP I don't see the header, but when I go to the NGINX load balancer IP, I see the headers. Also when I go to the ingress IP, I get the correct cert, but the NGINX IP gives me a self signed cert. I don't think I have the controller setup right.
Ingress:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: example-ingress
annotations:
kubernetes.io/ingress.class: "nginx"
kubernetes.io/ingress.global-static-ip-name: staticip
labels:
app: exam
spec:
tls:
- hosts:
- www.example.com
secretName: tls-secret
backend:
serviceName: example-app
servicePort: 80
Ingress node:
apiVersion: v1
kind: Service
metadata:
name: exam-node
labels:
app: exam
spec:
type: NodePort
selector:
app: example-app
tier: backend
ports:
- port: 80
targetPort: 80
To create the NGINX controller I used the command helm install stable/nginx-ingress --name nginx-ingress --set rbac.create=true
My nginx controller logs say this:
2018-07-29 19:57:11.000 CDT
updating Ingress default/example-ingress status to [{12.346.151.45 }]
It seems the nginx controller knows about ingress but ingress doesn't know about the controller. I am probably confused on how Ingress and NGINX work together.

Resources