Block particular path on ingress-nginx Loadbalancer

Viewed 3284

I have many domain pointing to Ingress Controller IP. I want to block /particular-path for all the domains/sites. Is there a way to do this. I can use nginx.ingress.kubernetes.io/configuration-snippet: | for each site. But looking for way to do for all sites/domains/Ingress resource at once.

Controller used: https://kubernetes.github.io/ingress-nginx/

3 Answers

There are two ways to achieve this:

1. First one is with using server-snippet annotation:

Using the annotation nginx.ingress.kubernetes.io/server-snippet it is possible to add custom configuration in the server configuration block.

Here is my manifest for the ingress object:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: minimal-ingress
  annotations:
     nginx.ingress.kubernetes.io/server-snippet: |
          location ~* /admin-access {
              deny all;
              return 403;
            }
spec:
  rules:
  - host: domain.com
    http:
      paths:
      - path: /
        backend:
          serviceName: web 
          servicePort: 80

Please note that using this approach :

This annotation can be used only once per host.


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 location globally for all host 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 be be blocked when admin will appear after web). All of the other uri will be passed through.


3. Here`s a test:

➜  curl -H "Host: domain.com"  172.17.0.4/test             
...
 "path": "/test",
 "headers": {
...
 },
 "method": "GET",
 "body": "",
 "fresh": false,
 "hostname": "domain.com",
 "ip": "172.17.0.1",
 "ips": [
   "172.17.0.1"
 ],
 "protocol": "http",
 "query": {},
 "subdomains": [],
 "xhr": false,
 "os": {
   "hostname": "web-6b686fdc7d-4pxt9"
...  

And here is a test with a path that has been denied:

➜  curl -H "Host: domain.com"  172.17.0.4/admin-access

<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.19.0</center>
</body>
</html>

➜  curl -H "Host: domain.com"  172.17.0.4/admin-access/test
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.19.0</center>
</body>
</html>

Additional information: Deprecated APIs Removed In 1.16. Here’s What You Need To Know:

The v1.22 release will stop serving the following deprecated API versions in favor of newer and more stable API versions:

Ingress in the extensions/v1beta1 API version will no longer be served

You cannot block specific paths. What you can do is point the path of the host inside your ingress to a default backedn application that says 404 default backedn for example.

you can apply it using the ingress annotation

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: channel-dev
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/whitelist-source-range: "27.110.30.45, 68.50.85.421"
  name: dev-ingress
  namespace: development
spec:
  rules:
  - host: hooks.dev.example.com
    http:
      paths:
      - backend:
          serviceName: hello-service
          servicePort: 80
        path: /incoming/message/
  tls:
  - hosts:
    - hooks.dev.example.com
    secretName: channel-dev

path https://hooks.dev.example.com/incoming/message/ will be only accessible from mentioned IPs other users will get 403 error and wont be able to access the URL.

just add this annotation in ingress

nginx.ingress.kubernetes.io/whitelist-source-range
Related