nginx.ingress.kubernetes.io/server-snippet annotation contains invalid word location - nginx

I am new to kubernetes and using AWS EKS cluster 1.21. I am trying to write the nginx ingress config for my k8s cluster and blocking some request using server-snippet. My ingress config is below
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: abc-ingress-external
namespace: backend
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
kubernetes.io/ingress.class: nginx-external
nginx.ingress.kubernetes.io/server-snippet: |
location = /ping {
deny all;
return 403;
}
spec:
rules:
- host: dev-abc.example.com
http:
paths:
- backend:
service:
name: miller
port:
number: 80
path: /
pathType: Prefix
When I apply this config, I get this error:
for: "ingress.yml": admission webhook "validate.nginx.ingress.kubernetes.io" denied the request: nginx.ingress.kubernetes.io/server-snippet annotation contains invalid word location
I looked into this and got this is something related to annotation-value-word-blocklist. However i don't know how to resolve this. Any help would be appreciated.

Seems there's issue using location with some versions. The following was tested successfully on EKS cluster.
Install basic ingress-nginx on EKS:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.1.0/deploy/static/provider/aws/deploy.yaml
Note: If your cluster version is < 1.21, you need to comment out ipFamilyPolicy and ipFamilies in the service spec.
Run a http service:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/docs/examples/http-svc.yaml
Create an ingress for the service:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: http-svc
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/server-snippet: |
location = /ping {
deny all;
return 403;
}
spec:
rules:
- host: test.domain.com
http:
paths:
- path: /
pathType: ImplementationSpecific
backend:
service:
name: http-svc
port:
number: 8080
Return 200 as expected:
curl -H 'HOST: test.domain.com' http://<get your nlb address from the console>
Return 200 as expected:
curl -H 'HOST: test.domain.com' -k https://<get your nlb address from the console>
Return 403 as expected, the snippet is working:
curl -H 'HOST: test.domain.com' -k https://<get your nlb address from the console>/ping
Use the latest release to avoid the "annotation contains invalid word location" issue.

Alternatively, replacing nginx.ingress.kubernetes.io/server-snippet by nginx.org/server-snippets fixed the issue for me. See for instance here

Related

Nginx Ingress block all path (/*) and allow only some specific path (/code-refiner/ and /v1/unsubscribed/*)

I wanted to create an nginx ingress which allows only few paths for users to connect and rest all block or provide an 403 error. Any way to achieve that ?
I only wanted users to allow to connect "/code-refiner/", /v1/unsubscribed/* and rest all should be blocked.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: code-refiner-service-ingress-external
namespace: backend
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
kubernetes.io/ingress.class: nginx-external
spec:
rules:
- host: code-refiner.example.com
http:
paths:
- backend:
service:
name: code-refiner-service
port:
number: 80
path: /
pathType: Prefix
I need to achieve something like this
location /* {
deny all;
}
location /code-refiner/ or /v1/unsubscribed/{
allow all;
}
As per this git link, you can create two Ingress and only add the annotations to the ingress with the path you want to protect
For your issues create two Ingresses first by default without any restriction.
Then, create a secret for auth as described in the doc.(Create a htpasswd and secret)
Creating the htpasswd
$ htpasswd -c auth foo
New password: <bar>
New password: \
Re-type new password:
Adding password for user foo
Creating the secret:
kubectl create secret generic basic-auth --from-file=auth secret
3.Second Ingress with auth for paths which you need to restrict.
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
annotations:
kubernetes.io/ingress.class: nginx
ingress.kubernetes.io/rewrite-target: /
kubernetes.io/tls-acme: true
# type of authentication
ingress.kubernetes.io/auth-type: basic
# name of the secret that contains the user/password definitions
ingress.kubernetes.io/auth-secret: basic-auth
# message to display with an appropiate context why the authentication is required
ingress.kubernetes.io/auth-realm: "Authentication Required - foo"
# Below configuration-snippet is to pass on the authenticated user-name to serviceB
ingress.kubernetes.io/configuration-snippet: |
proxy_set_header X-AUTH-USER $remote_user;
name: my-nginx-ingress-auth
spec:
tls:
hosts:
myhost
secretName: mysecret
rules:
host: myhost
http:
paths:
path: /serviceB/
backend:
serviceName: serviceB-service
servicePort: 7070
For your reference adding these stack links [1] [2].
Second one is with usage of ConfigMaps and Server-snippet:
What you have to do is to locate your configMap:
kubectl get pod <nginx-ingress-controller> -o yaml
This is located the container args:
spec:
containers:
- args:
- /nginx-ingress-controller
- configmap=$(POD_NAMESPACE)/nginx-loadbalancer-conf
And then just edit it and place add the server-snippet part
apiVersion: v1
data: server-snippet: |
location /admin-access {
deny all;
}
This approach allows you to define restricted locations globally for all hosts defined in Ingress resource.
Please note that with usage of server-snippet the path that you are blocking cannot be defined in ingress resource object. There is however another way with location-snippet via ConfigMap:
location ~* "^/web/admin {
deny all;
}
With this for every existing path in ingress object there will be ingress rule but it will be blocked for specific uri (In the example above it will be blocked when admin will appear after web). All of the other uri will be passed through.

www.example.com gives 404 while example.com works perfectly

I have a problem with Kubernetes deployment. My service works perfectly when accessing "example.com" or "https://example.com" but it does not work when accessing over "www.example.com" or "http://example.com" the default nginx backend shows up with a 404.
Here is my ingress implementation:
# Ingress
apiVersion: networking.k8s.io/v1
# make a new cert
kind: Ingress
metadata:
name: ${APP_NAME}
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/from-to-www-redirect: 'true'
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: example.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: ${APP_NAME}
port:
number: 80
tls:
- secretName: ${APP_NAME}
hosts:
- example.com
- www.example.com
Here is my certificate configuration:
# Certificate
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: ${APP_NAME}
spec:
secretName: ${APP_NAME}
dnsNames:
- example.com
- www.example.com
issuerRef:
name: letsencrypt-production
# We can reference ClusterIssuers by changing the kind here.
# The default value is Issuer (i.e. a locally namespaced Issuer)
kind: ClusterIssuer
group: cert-manager.io
I configured the following DNS records:
example.com A 300 xx.xxx.xx.xx
*.example.com A 300 xx.xxx.xx.xx
www.example.com CNAME 300 example.com
Does anyone knows what could be the issue here? Every help is appreciated a lot!
You need to map your ingress controller external IP to your domain as a DNS record:
it's present under your services
kubectl -n $NAMESPACE get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.0.XX.XXX XX.XXX.XX.XXX 80:XXXXX/TCP,443:XXXX/TCP Xd
Add a DNS record in your DNS zone example.com ==> $EXTERNAL-IP
the 404 was coming from Nginx. I'm not sure what went wrong but after reinstalling Nginx on my cluster it works now. I recommend everyone having this problem runing a curl -v and see if it is a redirect header or not.

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: Cannot redirect to backend service

I have scoured the Net to try to resolve something that seems to be a common issue, but unfortunately all of the documentation and suggestions have not solve my problem. I hope that you can help me and others with it.
We are migrating from another ingress to nginx-ingress. To validate our installation, I am using httpbin as the backend service.
When I create the following ingress with a path of '/' and send the query, I receive a proper response.
curl -I -k http://abczzz.com/anything
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: mikie-ingress
namespace: mikie
spec:
ingressClassName: nginx
rules:
- host: abczzz.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: httpbin-service
port:
number: 8999
What we really need is to be able to redirect to different services off of this single host, so I changed the ingress to the following, but the query always fails with a 404. Basically, I want the /httpbin to disappear and pass the path onto the backend service, httpbin.
curl -I -k http://abczzz.com/httpbin/anything
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: mikie-ingress
namespace: mikie
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
nginx.ingress.kubernetes.io/configuration-snippet: |
rewrite ^(/httpbin)$ $1/ redirect;
spec:
ingressClassName: nginx
rules:
- host: abczzz.com
http:
paths:
- path: /httpbin(/|$)(.*)
pathType: Prefix
backend:
service:
name: httpbin-service
port:
number: 8999
I'd really appreciate your help to resolve what must be a simple routing issue.
Thanks for your time and interest.
I finally figured things out... Hopefully, the following snippet will help others...
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: mikie-ingress
namespace: mikie
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
ingressClassName: nginx
rules:
- host: abczzz.com
http:
paths:
- backend:
service:
name: httpbin-service
port:
number: 8999
path: /httpbin/(.*)
pathType: Prefix

Nginx Ingress controller with K8s returning 404

I have a service which is accepting the request at /api/v1/orders. I was able to validate the response using the Cluster IP. I logged into a pod and hit the curl http://order-service/api/v1/orders and getting the response.
I then set up a Nginx Ingress Controller and the ingress with the below yaml definition. I used the cafe example and the cafe ingress is working fine.
When I try to access my order-service I am getting 404. I am not sure how to debug this.
Note: My API is accessible on http://context/api/v1/orders endpoint. How do I redirect the path the /orders/api/v1/orders from the ingress?
curl -v -H "Content-type: application/j son" -H "Accept: application/json" https://classpath.com/orders/api/v1/orders --insec ure
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: orders-microservice-ingress
spec:
ingressClassName: nginx # use only with k8s version >= 1.18.0
tls:
- hosts:
- classpath.com
secretName: cafe-secret
rules:
- host: classpath.com
http:
paths:
- path: /orders
backend:
serviceName: order-service
servicePort: 80
I have set the aws loadbalancer IP to classpath.com in the /etc/hosts file.

Resources