Christian Fuchs
Christian Fuchs

Reputation: 635

ingress-nginx: configure chunked transfer and payload size per path

I use the ingress-nginx helm chart. Behind the ingress, I have a number of kubernetes services providing a number of REST API endpoints. In general, the ingress-nginx default configuration that blocks large requests is just fine.

But for some endpoints, I want/need to:

So far I only succeeded to set the configuration for all paths, using the annotations nginx.ingress.kubernetes.io/proxy-body-size and nginx.ingress.kubernetes.io/server-snippet. Currently my Ingress configuration looks like this:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-frontend
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: 1g
    nginx.ingress.kubernetes.io/server-snippet: |
      chunked_transfer_encoding on;
      proxy_buffering off;
      proxy_request_buffering off;
      proxy_max_temp_file_size 0;
spec:
  rules:
    - host: apply-ingress-hostname-patch-here
      http:
        paths:
          - path: /api/orgs/v1
            pathType: Prefix
            backend:
              service:
                name: organisations
                port:
                  number: 80
          - path: /api/lines/v1
            pathType: Prefix
            backend:
              service:
                name: linejsonfiles
                port:
                  number: 80
// ... more paths follow

So this enables large, chunked transfers for all endpoints, so all my REST endpoints became vulnerable to large-payload attacks.

So, how can I configure this (large request body, large response body, chunked transfer) for some endpoints only, using the ingress-nginx helm chart?

Upvotes: 0

Views: 131

Answers (1)

ArguingMussels
ArguingMussels

Reputation: 48

You can define multiple ingress configurations in the same ingress configuration file - allowing you to take a least-privilege approach & limit the large file upload/download configurations to just the endpoints you want.

Going off the example from the kubernetes/ingress-nginx User Guide for Kubernetes versions >= 1.19.x, your config could look something like this:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-myservicea
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: 1g
    nginx.ingress.kubernetes.io/server-snippet: |
      chunked_transfer_encoding on;
      proxy_buffering off;
      proxy_request_buffering off;
      proxy_max_temp_file_size 0;
spec:
  rules:
  - host: myservice.foo.org
    http:
      paths:
      - path: /foo
        pathType: Prefix
        backend:
          service:
            name: myservice
            port:
              number: 443
  ingressClassName: nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-myserviceb
spec:
  rules:
  - host: myservice.foo.org
    http:
      paths:
      - path: /bar
        pathType: Prefix
        backend:
          service:
            name: myservice
            port:
              number: 443
  ingressClassName: nginx

A few security thoughts

NB #0: Kudos for setting a larger nginx.ingress.kubernetes.io/proxy-body-size at the ingress level, and not globally in the NGINX ConfigMap.

NB #1: Saw there were some port 80's in the ingress configuration. I assume that's because you already set ssl-redirect: true in your ConfigMap?

NB #2: Since you're thinking about resource exhaustion attacks, I presume you're already thinking of common file upload security practices at the application level (OWASP).

Upvotes: 1

Related Questions