Kuberenetes Ingress - Whitelist particular APIs

10/23/2019

We have a host of microservices all being served via a single api-gateway service, in Kubernetes, with an ingress to forward to the same that looks like below ->

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: beta-https
  namespace: beta
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
    nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
  tls:
    - hosts:
      - beta.xyz.com
      secretName: beta-secret
  rules:
  - host: beta.xyz.com
    http:
      paths:
      - path: /api/(.*)
        backend:
          serviceName: api-svc
          servicePort: 8443

Now we have a new requirement, wherein a subset of the apis - /api/secure , must be IP restricted. Any ideas on how to achieve this?

I am assuming I can use nginx.ingress.kubernetes.io/whitelist-source-range, in a new config to foroward traffic to /api/secure, but how do I ensure the above config does not server /api/secure?

-- praven john
kubernetes-ingress
whitelist

2 Answers

10/24/2019

From what I see you are trying to create two separate paths where /api/secure will be accesible only for specific ip addresses.

I have replicated your problem, made some tests and found a solution.

When creating two ingress objects like yours, which differ on path field e.g. one has path: /api/(.*) and second has path: /api/secure

nginx will generate the following configuration (output is shortened):

server { server_name beta.xyz.com ;

  listen 80  ;
  listen 443  ssl http2 ;

      ...

  location ~* "^/api/secure" {
      ...
  }

  location ~* "^/api/(.*)" {
      ...
  }

and in nginx documentation you can read:

To find location matching a given request, nginx first checks locations defined using the prefix strings (prefix locations). Among them, the location with the longest matching prefix is selected and remembered. Then regular expressions are checked, in the order of their appearance in the configuration file. The search of regular expressions terminates on the first match, and the corresponding configuration is used.

meaning: NGINX always fulfills requests using the most specific match

Based on this information, creating two separate ingresses, just like you mentioned, should solve your problem, because /api/secure will always be more specific path than /api/(.*).

Let me know if that helped.

-- HelloWorld
Source: StackOverflow

10/23/2019

so for someone looking into doing something similar, I was able to get this working by using nginx.ingress.kubernetes.io/server-snippet to add a snippet and block the traffic

      location ~ "^/api/secure/(.*)" {
        deny all;
        return 403;
      }
-- praven john
Source: StackOverflow