Nginx ingress - Combining Basic Authentication with Access Restriction by IP Address

Hi all,
I use helm install chart kubernetes/ingress-nginx
My request : ingress rule to expose my app :

  • Allow access from my IP
  • If request not come from my IP, force client to authenticate, allow if success , deny if fail.

I follow these docs

https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#whitelist-source-range
https://kubernetes.github.io/ingress-nginx/examples/auth/basic/

This is my yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: simple-frontend-ingress-tls
  annotations:
    kubernetes.io/ingress.class: nginx

    cert-manager.io/issuer: letsencrypt-prod
    cert-manager.io/acme-challenge-type: http01

    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"

    nginx.ingress.kubernetes.io/satisfy: "any"

    nginx.ingress.kubernetes.io/whitelist-source-range: "my IP/32"

    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required'
spec:
  tls:
  - hosts:
      - app.mydomain.com
    secretName: my-tls-prod
  rules:
  - host: app.mydomain.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-frontend-service
            port: 
              number: 80
kubectl describe ing simple-frontend-ingress-tls
Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
Name:             simple-frontend-ingress-tls
Namespace:        
Address:          
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
TLS:
  my-tls-prod terminates app.mydomain.com
Rules:
  Host                      Path  Backends
  ----                      ----  --------
  app.mydomain.com
                            /   web-frontend-service:80 (10.240.0.85:80)
Annotations:                cert-manager.io/acme-challenge-type: http01
                            cert-manager.io/issuer: letsencrypt-prod
                            kubernetes.io/ingress.class: nginx
                            nginx.ingress.kubernetes.io/auth-realm: Authentication Required
                            nginx.ingress.kubernetes.io/auth-secret: basic-auth
                            nginx.ingress.kubernetes.io/auth-type: basic
                            nginx.ingress.kubernetes.io/force-ssl-redirect: true
                            nginx.ingress.kubernetes.io/satisfy: any
                            nginx.ingress.kubernetes.io/whitelist-source-range: my IP/32
Events:
  Type    Reason             Age                From                      Message
  ----    ------             ----               ----                      -------
  Normal  CreateCertificate  43m                cert-manager              Successfully created Certificate "my-tls-prod"
  Normal  Sync               43m (x2 over 44m)  nginx-ingress-controller  Scheduled for sync

I even checked /etc/nginx/nginx.conf in ingress controller pod to make sure

...
        ## start server app.mydomain.com
        server {
                server_name app.mydomain.com ;
...
                        allow my IP/32;
                        deny all;

                        auth_basic "Authentication Required";
                        auth_basic_user_file /etc/ingress-controller/auth/zzz-a0cd0d6c-446f-42da-81a8-d079af3baed3-679c7ee6-f533-448f-8329-c5d8654a4d99.passwd;
                        satisfy any;
...

But it doesn’t work, request from anywhere including my IP is asked for authentication.
Where should I look to troubleshoot it ? Please let me know if you need more information.

When I look further in /etc/nginx/nginx.conf in ingress controller pod I find this

        ## start server app.mydomain.com
        server {
                server_name app.mydomain.com ;
                location / {

                        set $namespace      "zzz";
                        set $ingress_name   "simple-frontend-ingress-tls";
                        set $service_name   "web-frontend-service";
                        set $service_port   "80";

                        # be careful with `access_by_lua_block` and `satisfy any` directives as satisfy any
                        # will always succeed when there's `access_by_lua_block` that does not have any lua code doing `ngx.exit(ngx.DECLINED)`
                        # other authentication method such as basic auth or external auth useless - all requests will be allowed.
                        #access_by_lua_block {
                        #}
...
                        allow my IP/32;
                        deny all;

                        auth_basic "Authentication Required";
                        auth_basic_user_file /etc/ingress-controller/auth/zzz-a0cd0d6c-446f-42da-81a8-d079af3baed3-679c7ee6-f533-448f-8329-c5d8654a4d99.passwd;
                        satisfy any;
...

Can anyone give me some advice ?

I found issue report at #3480 and #3649 , this should be fixed from controller version 0.21.0
I’m using 0.47.0

kubectl --namespace ingress exec -it nginx-ingress-ingress-nginx-controller-6f4dbcc6bb-4tpzr -- /nginx-ingress-controller --version
-------------------------------------------------------------------------------
NGINX Ingress controller
  Release:       v0.47.0
  Build:         7201e37633485d1f14dbe9cd7b22dd380df00a07
  Repository:    https://github.com/kubernetes/ingress-nginx
  nginx version: nginx/1.20.1

-------------------------------------------------------------------------------

Should I open an issue report on github ?

The problem is fixed , the controller should be upgraded with value controller.service.externalTrafficPolicy=“Local” , for more information please view Annotation satisfy any fail · Issue #7354 · kubernetes/ingress-nginx · GitHub