NGINX ingress controller ip restriction for certain path

Viewed 94

I'm using NGINX Ingress contorller (https://github.com/nginxinc/kubernetes-ingress) with Kubernetes v1.21 in Amazon EKS.

I want to set IP restriction for certain path in one Ingress object

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
    - host: my-app.my-host.com
      http:
        paths:
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-server
                port:
                  number: 80
          - path: /admin               # I want to restrict IP only for /admin path
            pathType: Prefix
            backend:
              service:
                name: admin-server
                port:
                  number: 80

I've tried to use server snippet annotation (https://docs.nginx.com/nginx-ingress-controller/configuration/ingress-resources/advanced-configuration-with-snippets/)

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.org/server-snippets: |
      location /admin {
          allow 192.168.111.111;       # My IP address
          deny all;
      }      
...

It's failed with the error message: "duplicate location /admin in /etc/nginx/conf.d/..."

Is there any way to set snippet for certain path in Ingress object? I think preparing two Ingress and merging them would be a solution, but I don't want to do that for ease of management.

2 Answers

I did it by use merging master and minion Ingress

Notice that it is nginx-ingress, not ingress-nginx communitiy version. I've to use nginx.org annotation.

I prepared three Ingress objects

  • Master Ingress to setup host (there should be no paths)
  • Minion Ingress with public access
  • Minion Ingress with private access
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress-master
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.org/mergeable-ingress-type: master
spec:
  rules:
    - host: my-app.my-host.com
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress-minion-public
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.org/mergeable-ingress-type: minion
spec:
  rules:
    - host: my-app.my-host.com
      http:
        paths:
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-server
                port:
                  number: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress-minion-private
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.org/mergeable-ingress-type: minion
    # Be aware to use location-snippet instead of server-snippet
    nginx.org/location-snippets: |
      allow 192.168.111.111;
      deny all;
spec:
  rules:
    - host: my-app.my-host.com
      http:
        paths:
          - path: /admin
            pathType: Prefix
            backend:
              service:
                name: admin-server
                port:
                  number: 80

reference links:

it's due to duplicating a similar path so maybe you can try to change the path like in server-snippet

location ~* "^/admin"

You can create the two different ingress for path management

All the traffic on the domain and path /api will be allowed to access the service

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: allowed-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
    - host: my-app.my-host.com
      http:
        paths:
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-server
                port:
                  number: 80

ingress with restricted IP option, you can use the annotation nginx.ingress.kubernetes.io/whitelist-source-range: "10.0.0.0/16" and update the whitelist source ranges as per requirement.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: restricted-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/whitelist-source-range: "192.168.111.111/32"
spec:
  rules:
    - host: my-app.my-host.com
      http:
        paths:
          - path: /admin               
            pathType: Prefix
            backend:
              service:
                name: admin-server
                port:
                  number: 80
Related