ingress-nginx icon indicating copy to clipboard operation
ingress-nginx copied to clipboard

hsts-preload does not work with www-redirect

Open SvenKirschbaum opened this issue 7 months ago • 5 comments

What happened:

Setting hsts-preload: true in the ingress-nginx controller configmap and creating an ingress with the nginx.ingress.kubernetes.io/from-to-www-redirect annotation for the www subdomain of a domain does no result in a hsts preload eligible configuration for the used domain.

The resulting redirects are:

http://domain.tld -> http://www.domain.tld -> https://www.domain.tld (with HSTS header)

and

https://domain.tld (without HSTS header) -> https://www.domain.tld (with HSTS header)

What you expected to happen:

I would expect this configuration to result in the domain being eligible for submission to chromes hsts preload lists. This would require the following redirects:

http://domain.tld -> https://domain.tld (with HSTS header)-> https://www.domain.tld (with HSTS header)

NGINX Ingress controller version (exec into the pod and run nginx-ingress-controller --version.):

NGINX Ingress controller Release: v1.10.1 Build: 4fb5aac1dd3669daa3a14d9de3e3cdb371b4c518 Repository: https://github.com/kubernetes/ingress-nginx nginx version: nginx/1.25.3

Kubernetes version (use kubectl version): 1.29.6

Environment:

  • Cloud provider or hardware configuration: k3s single node cluster

  • OS (e.g. from /etc/os-release): Debian GNU/Linux 12 (bookworm)

  • Kernel (e.g. uname -a): Linux 6.1.0-21-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.90-1 (2024-05-03) x86_64 GNU/Linux

  • Install tools: k3s

  • Basic cluster related info:

    • Client Version: v1.29.6+k3s2 Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3 Server Version: v1.29.6+k3s2
  • How was the ingress-nginx-controller installed:

    • Via helm
    • ingress-nginx ingress-nginx 15 2024-04-26 18:50:45.211182831 +0000 UTC deployed ingress-nginx-4.10.1 1.10.1
    • Values controller: kind: DaemonSet ingressClassResource: default: true service: ipFamilyPolicy: RequireDualStack ipFamilies: - IPv4 - IPv6 externalTrafficPolicy: Local allocateLoadBalancerNodePorts: false metrics: enabled: true serviceMonitor: enabled: true scrapeInterval: 15s config: ssl-reject-handshake: true enable-ocsp: true hsts-preload: true ssl-ciphers: "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES256-GCM-SHA384" ssl-ecdh-curve: "secp521r1:secp384r1" ssl-session-timeout: 1d http-snippet: | ssl_conf_command Options PrioritizeChaCha; ssl_conf_command Ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256; otlp-collector-host: grafana-k8s-monitoring-grafana-agent.monitoring.svc.cluster.local enable-opentelemetry: true opentelemetry-trust-incoming-span: false otel-sampler: AlwaysOn otel-sampler-ratio: "1.0" opentelemetry: enabled: true addHeaders: X-Frame-Options: SAMEORIGIN X-Content-Type-Options: nosniff Referrer-Policy: "strict-origin-when-cross-origin" Server-Timing: "traceparent;desc=\"$opentelemetry_context_traceparent\""

How to reproduce this issue:

  • Create a new kind cluster with the ports 80 and 443 exposed: curl https://gist.githubusercontent.com/SvenKirschbaum/91eb6f19c5b320b4265794f33d934232/raw/ceacfbc4a57ca8b23ac1858171f02b9794b71522/kind.yaml | kind create cluster --config=-
  • Install ingress-nginx kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.11.0/deploy/static/provider/kind/deploy.yaml
  • Enable the hsts-preload option: kubectl patch configmap/ingress-nginx-controller -n ingress-nginx --type merge -p '{"data":{"hsts-preload": "true"}}'
  • Create an ingress for a www subdomain and add the annotation nginx.ingress.kubernetes.io/from-to-www-redirect: "true": kubectl apply -f https://gist.githubusercontent.com/SvenKirschbaum/364de5c2b3c537b91ac124ec1d9ffc33/raw/2cd2c2c885e614be1a82984f27c9f4c236a88ce4/ingress.yaml
  • Access the domain and observe the presence of the hsts header and the redirects:
$ curl -vk http://localhost 2>&1 |grep "Location\|strict"
< Location: http://www.localhost
$ curl -vk http://www.localhost 2>&1 |grep "Location\|strict"
< Location: https://www.localhost
$ curl -vk https://localhost 2>&1 |grep "Location\|strict"
< Location: https://www.localhost
$ curl -vk https://www.localhost 2>&1 |grep "Location\|strict"
< strict-transport-security: max-age=31536000; includeSubDomains; preload

SvenKirschbaum avatar Jul 09 '24 21:07 SvenKirschbaum