Back to Ingress Nginx

Hardening Guide

docs/deploy/hardening-guide.md

latest13.0 KB
Original Source

Hardening Guide

Do not use in multi-tenant Kubernetes production installations. This project assumes that users that can create Ingress objects are administrators of the cluster.

Overview

There are several ways to do hardening and securing of nginx. In this documentation two guides are used, the guides are overlapping in some points:

This guide describes, what of the different configurations described in those guides is already implemented as default in the nginx implementation of kubernetes ingress, what needs to be configured, what is obsolete due to the fact that the nginx is running as container (the CIS benchmark relates to a non-containerized installation) and what is difficult or not possible.

Be aware that this is only a guide and you are responsible for your own implementation. Some of the configurations may lead to have specific clients unable to reach your site or similar consequences.

This guide refers to chapters in the CIS Benchmark. For full explanation you should refer to the benchmark document itself

Configuration Guide

Chapter in CIS benchmarkStatusDefaultAction to do if not default
1 Initial Setup
1.1 Installation
1.1.1 Ensure NGINX is installed (Scored)OKdone through helm charts / following documentation to deploy nginx ingress
1.1.2 Ensure NGINX is installed from source (Not Scored)OKdone through helm charts / following documentation to deploy nginx ingress
1.2 Configure Software Updates
1.2.1 Ensure package manager repositories are properly configured (Not Scored)OKdone via helm, nginx version could be overwritten, however compatibility is not ensured then
1.2.2 Ensure the latest software package is installed (Not Scored)ACTION NEEDEDdone via helm, nginx version could be overwritten, however compatibility is not ensured thenPlan for periodic updates
2 Basic Configuration
2.1 Minimize NGINX Modules
2.1.1 Ensure only required modules are installed (Not Scored)OKAlready only needed modules are installed, however proposals for further reduction are welcome
2.1.2 Ensure HTTP WebDAV module is not installed (Scored)OK
2.1.3 Ensure modules with gzip functionality are disabled (Scored)OK
2.1.4 Ensure the autoindex module is disabled (Scored)OKNo autoindex configs so far in ingress defaults
2.2 Account Security
2.2.1 Ensure that NGINX is run using a non-privileged, dedicated service account (Not Scored)OKPod configured as user www-data: See this line in helm chart values. Compiled with user www-data: See this line in build script
2.2.2 Ensure the NGINX service account is locked (Scored)OKDocker design ensures this
2.2.3 Ensure the NGINX service account has an invalid shell (Scored)OKShell is nologin: see this line in build script
2.3 Permissions and Ownership
2.3.1 Ensure NGINX directories and files are owned by root (Scored)OKObsolete through docker-design and ingress controller needs to update the configs dynamically
2.3.2 Ensure access to NGINX directories and files is restricted (Scored)OKSee previous answer
2.3.3 Ensure the NGINX process ID (PID) file is secured (Scored)OKNo PID-File due to docker design
2.3.4 Ensure the core dump directory is secured (Not Scored)OKNo working_directory configured by default
2.4 Network Configuration
2.4.1 Ensure NGINX only listens for network connections on authorized ports (Not Scored)OKEnsured by automatic nginx.conf configuration
2.4.2 Ensure requests for unknown host names are rejected (Not Scored)OKThey are not rejected but send to the "default backend" delivering appropriate errors (mostly 404)
2.4.3 Ensure keepalive_timeout is 10 seconds or less, but not 0 (Scored)ACTION NEEDEDDefault is 75sconfigure keep-alive to 10 seconds according to this documentation
2.4.4 Ensure send_timeout is set to 10 seconds or less, but not 0 (Scored)RISK TO BE ACCEPTEDNot configured, however the nginx default is 60sNot configurable
2.5 Information Disclosure
2.5.1 Ensure server_tokens directive is set to off (Scored)OKserver_tokens is configured to off by default
2.5.2 Ensure default error and index.html pages do not reference NGINX (Scored)ACTION NEEDED404 shows no version at all, 503 and 403 show "nginx", which is hardcoded see this line in nginx source codeconfigure custom error pages at least for 403, 404 and 503 and 500
2.5.3 Ensure hidden file serving is disabled (Not Scored)ACTION NEEDEDconfig not setconfigure a config.server-snippet Snippet, but beware of .well-known challenges or similar. Refer to the benchmark here please
2.5.4 Ensure the NGINX reverse proxy does not enable information disclosure (Scored)ACTION NEEDEDhide not configuredconfigure hide-headers with array of "X-Powered-By" and "Server": according to this documentation
3 Logging
3.1 Ensure detailed logging is enabled (Not Scored)OKnginx ingress has a very detailed log format by default
3.2 Ensure access logging is enabled (Scored)OKAccess log is enabled by default
3.3 Ensure error logging is enabled and set to the info logging level (Scored)OKError log is configured by default. The log level does not matter, because it is all sent to STDOUT anyway
3.4 Ensure log files are rotated (Scored)OBSOLETELog file handling is not part of the nginx ingress and should be handled separately
3.5 Ensure error logs are sent to a remote syslog server (Not Scored)OBSOLETESee previous answer
3.6 Ensure access logs are sent to a remote syslog server (Not Scored)OBSOLETESee previous answer
3.7 Ensure proxies pass source IP information (Scored)OKHeaders are set by default
4 Encryption
4.1 TLS / SSL Configuration
4.1.1 Ensure HTTP is redirected to HTTPS (Scored)OKRedirect to TLS is default
4.1.2 Ensure a trusted certificate and trust chain is installed (Not Scored)ACTION NEEDEDFor installing certs there are enough manuals in the web. A good way is to use lets encrypt through cert-managerInstall proper certificates or use lets encrypt with cert-manager
4.1.3 Ensure private key permissions are restricted (Scored)ACTION NEEDEDSee previous answer
4.1.4 Ensure only modern TLS protocols are used (Scored)OK/ACTION NEEDEDDefault is TLS 1.2 + 1.3, while this is okay for CIS Benchmark, cipherlist.eu only recommends 1.3. This may cut off old OS'sSet controller.config.ssl-protocols to "TLSv1.3"
4.1.5 Disable weak ciphers (Scored)ACTION NEEDEDDefault ciphers are already good, but cipherlist.eu recommends even stronger ciphersSet controller.config.ssl-ciphers to "EECDH+AESGCM:EDH+AESGCM"
4.1.6 Ensure custom Diffie-Hellman parameters are used (Scored)ACTION NEEDEDNo custom DH parameters are generatedGenerate dh parameters for each ingress deployment you use - see here for a how to
4.1.7 Ensure Online Certificate Status Protocol (OCSP) stapling is enabled (Scored)ACTION NEEDEDNot enabledset via this configuration parameter
4.1.8 Ensure HTTP Strict Transport Security (HSTS) is enabled (Scored)OKHSTS is enabled by default
4.1.9 Ensure HTTP Public Key Pinning is enabled (Not Scored)ACTION NEEDED / RISK TO BE ACCEPTEDHKPK not enabled by defaultIf lets encrypt is not used, set correct HPKP header. There are several ways to implement this - with the helm charts it works via controller.add-headers. If lets encrypt is used, this is complicated, a solution here is yet unknown
4.1.10 Ensure upstream server traffic is authenticated with a client certificate (Scored)DEPENDS ON BACKENDHighly dependent on backends, not every backend allows configuring this, can also be mitigated via a service meshIf backend allows it, manual is here
4.1.11 Ensure the upstream traffic server certificate is trusted (Not Scored)DEPENDS ON BACKENDHighly dependent on backends, not every backend allows configuring this, can also be mitigated via a service meshIf backend allows it, see configuration here
4.1.12 Ensure your domain is preloaded (Not Scored)ACTION NEEDEDPreload is not active by defaultSet controller.config.hsts-preload to true
4.1.13 Ensure session resumption is disabled to enable perfect forward security (Scored)OKSession tickets are disabled by default
4.1.14 Ensure HTTP/2.0 is used (Not Scored)OKhttp2 is set by default
5 Request Filtering and Restrictions
5.1 Access Control
5.1.1 Ensure allow and deny filters limit access to specific IP addresses (Not Scored)OK/ACTION NEEDEDDepends on use case, geo ip module is compiled into Ingress-Nginx Controller, there are several ways to use itIf needed set IP restrictions via annotations or work with config snippets (be careful with lets-encrypt-http-challenge!)
5.1.2 Ensure only whitelisted HTTP methods are allowed (Not Scored)OK/ACTION NEEDEDDepends on use caseIf required it can be set via config snippet
5.2 Request Limits
5.2.1 Ensure timeout values for reading the client header and body are set correctly (Scored)ACTION NEEDEDDefault timeout is 60sSet via this configuration parameter and respective body equivalent
5.2.2 Ensure the maximum request body size is set correctly (Scored)ACTION NEEDEDDefault is 1mset via this configuration parameter
5.2.3 Ensure the maximum buffer size for URIs is defined (Scored)ACTION NEEDEDDefault is 4 8kSet via this configuration parameter
5.2.4 Ensure the number of connections per IP address is limited (Not Scored)OK/ACTION NEEDEDNo limit setDepends on use case, limit can be set via these annotations
5.2.5 Ensure rate limits by IP address are set (Not Scored)OK/ACTION NEEDEDNo limit setDepends on use case, limit can be set via these annotations
5.3 Browser Security
5.3.1 Ensure X-Frame-Options header is configured and enabled (Scored)ACTION NEEDEDHeader not set by defaultSeveral ways to implement this - with the helm charts it works via controller.add-headers
5.3.2 Ensure X-Content-Type-Options header is configured and enabled (Scored)ACTION NEEDEDSee previous answerSee previous answer
5.3.3 Ensure that Content Security Policy (CSP) is enabled and configured properly (Not Scored)ACTION NEEDEDSee previous answerSee previous answer
5.3.4 Ensure the Referrer Policy is enabled and configured properly (Not Scored)ACTION NEEDEDDepends on application. It should be handled in the applications webserver itself, not in the load balancing ingresscheck backend webserver
6 Mandatory Access Controln/atoo high level, depends on backends
<style type="text/css" rel="stylesheet"> @media only screen and (min-width: 768px) { td:nth-child(1){ white-space:normal !important; } .md-typeset table:not([class]) td { padding: .2rem .3rem; } } </style>