0

I have the following ingress defined:

---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: someName
  namespace: test
  annotations:
    kubernetes.io/ingress.class: "ingress-public"
    nginx.ingress.kubernetes.io/affinity: "cookie"
    nginx.ingress.kubernetes.io/session-cookie-name: "JSESSIONID"
    nginx.ingress.kubernetes.io/connection-proxy-header: "keep-alive"
    nginx.ingress.kubernetes.io/server-snippet: |
      # block if not / or /test or /something
      if ($request_uri !~* "(^\/(?:(?:test|something)(?:\/|$)|$))") {
        return 404 ;
        break;
      }
      # redirect if proto_http
      if ($http_x_forwarded_proto = 'http') {
        return 301 https://$host$request_uri;
        break;
      }

      # hsts required header
      add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

spec:
  rules:
  - host: myhost.example.com
    http:
      paths:
      - path: /
        backend:
          serviceName: someservice
          servicePort: 80

The regex covers most cases where requests are something like /config - as this doesn't match the regex, it returns a 404.

There are two problems that I currently have.

  1. Requesting /test%2F..%2Fconfig does NOT return a 404 even though this doesn't match the regex.
  2. Requesting /test/..%2Fconfig allows you to reach /config.

So is there either a better regex that would cover these cases, or is there a way to convert $request_uri into an absolute uri so the regex can work on that instead of an encoded uri?

The regex is here with some test cases: https://regex101.com/r/Msu402/1

Farhan.K
  • 63
  • 7

1 Answers1

3

You might want to try using a location (doc) or $uri (doc) since both match a normalized URI. Since if is evil I would suggest a location (untested):

location ~* ^/(?!test|something) {
  return 404;
}

Edit: I reread your question and it should BLOCK access to the mentioned locations in the regex. So I added the "not"...

boppy
  • 476
  • 2
  • 5
  • Thanks for your answer. I did try using `location` before but the issue was that I was using `!~*` instead of `~*`, and now know you can only using to match things not for things that don't match. And also I was missing a `;` after the return and the online config checker I was using didn't point that out :( Seems to be working well now – Farhan.K Oct 13 '20 at 08:57