Batman kid

Nginx Ingress: The Security Hero We Need!

I love Nginx Ingress! It is a very powerful Kubernetes Ingress, with so many capabilities. But I think it does not get enough appreciation in the AppSec world. Just by using Nginx Ingress, you could get so many security features for almost free. And even better, you can enable them once – and every workload in the cluster will have them! For example, you can monitor and chase after developers to enable security headers. Or just do it once, test it once, and forget. That’s it. An entire class of bugs doesn’t exist anymore. Isn’t that existing? Let’s see what else Nginx ingress can do for us!

Wait, what is an Ingress?

In Kubernetes world, an Ingress Controller allows you to expose a workload to the external world, outside your cluster. There are many controllers, but Nginx Ingress is one of the most popular ones. It is basically a deployment of the very popular Nginx web server, with a Kubernetes controller. The controller translates Ingress API into the Nginx configuration file. Meaning, any (well, most) of the things you can do with Nginx – you can do with Nginx Ingress. And there is a lot you can do…

Security Headers

I started with this example at the beginning of the post. Security Headers are HTTP headers that you can add to the HTTP response and can improve the security of your website. For Example, the Strict-Transport-Security header instructs the browser to redirect any HTTP request to HTTPS – before it lives the browser. This is why there are many security tools out there testing a website for security headers. And many AppSec folks waste their time triaging reports on missing headers. And many developers spend a lot of their time adding them to their websites. Well, this is pretty boring, right? Lucking, with Nginx Ingress you can configure it once for all the ingress inside the cluster! For example, if you deploy Nginx ingress using Helm, you can simply configure the chart to add any security header you’d like:
controller:
  addHeaders:
    Strict-Transport-Security: max-age=604800; includeSubDomains
Just deploy the controller with these settings, and you’re done. You can now forget about STS for the rest of your life!

IP Filtering

Imagine you want to limit which IPs could call your service. There are many reasons to do so. For example, maybe it’s a webhook that responds to GitHub events. There is no reason someone outside GitHub will ever call it – so why not limit it only to GitHub IPs? And here is where Nginx really shines: You can configure it either once in the controller (like we did at the previous example) or per ingress with annotations, which is a better fit for this case:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: github-handler
  annotations:    
    nginx.ingress.kubernetes.io/whitelist-source-range: <GitHub IP range / CIDRS>
Now, just deploy the ingress with this annotation. If you’ll try calling it outside those IPs, you will get 403 Forbidden from Nginx:
Nginx 403 forbidden example
Nginx 403 forbidden example
And the request didn’t even hit your service. Isn’t that cool?

Path Blocking

Prometheus is a very popular metric solution, with one small downside: It is pull-based instead of push. Meaning, to expose metrics you’re website need to expose the /metrics endpoint with all of its internal metrics (See my talk about it for more details). How do you allow only internal traffic to access this endpoint (or any other endpoint like health check)? Nginx to the rescue!
kind: Ingress
metadata:
  name: very-secure-service
  labels:
  annotations:
    nginx.ingress.kubernetes.io/server-snippet: |
      location /metrics {
        return 401;
      }
Using an annotation, we can add a specific Nginx configuration to the one generated by the controller. Here, we instruct Nginx to return 401 each time someone accesses the /metrics endpoint. Neat!

Rate Limiting

This is a very popular security controller. To prevent denial-of-service attacks, one of the simplest mitigations is to limit how many requests a user can send. Not so surprising, Nginx supports this too. There are many options here (see the documentation for more details), so make sure to choose the one that fits your use-case…

Web Application Firewall (WAF)

A WAF is a tool that inspects the incoming traffic and tries to block various attacks. While regular firewalls work on the network level, WAF focused on the application level and usually understands application protocols well – protocols like HTTP. While there are many WAF solutions out there (and many of them are very expensive), Nginx ingress comes with the free and open-source WAF ModSecurity. You can easily enable it (see the documentation) and easily customize it. OWASP maintains a list of security rules you can use, and you even can pretty easily author your own rules.

Authentication

One of the things that keep me awake at night is how secure are our internal tools. Especially open source tools like Prometheus or Alert Manager that usually don’t come with authentication. And this is just another thing Nginx ingress can solve for us! Nginx Ingress can integrate with a tool like OAuth Proxy, allowing you to offer every developer “one-click” SSO authentication – just by adding an annotation to their ingress. And that’s it, one huge problem just went away…

Road Paving

All the things I mentioned here (well, most of them) can be configured either at the controller level (enabled for all ingresses) or per ingress (check the documentation to find out). This gives you a lot of room to pave the road and free developers from the need to worry about those things:
  • Using different ingress controller with different settings – for example, one for web application configured with the best security headers and one for REST APIs without them. Developers just need to use the right one, and the rest is taken care of.
  • Using templating tools like Helm, Kustomize or Jsonnet to provides templates with all the security goodies. For example, a template that abstract the rate limiting annotations, freeing developering from understanding how to configure it.
  • Using tools like GateKeeper to enforce specific annotations – for example, all services must use the path block annotations, otherwise the deployment is denied.
And there are many other ways you could explore!

Wait, what about *** Ingress?

There are many many many ingress controllers out there. Are you not using Nginx ingress right now? The one you are using probably offers some of those features (and maybe others, that Nginx doesn’t). It’s time to dig into the docs to find out 🙂

Wrapping Up

I started this post by saying how much I love Nginx Ingress. I hope you’re now starting to understand why! Now it’s the time for you to take an action – which features you’re going to enable today, to make the world a bit more secure? Featured image – Photo by TK Hammonds on Unsplash. Thank you!

Leave a Reply

Your email address will not be published. Required fields are marked *