Search code examples
kubernetes-ingressnginx-ingress

NGINX ingress controller ip restriction for certain path


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.


Solution

  • 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: