Explorar el Código

fix: force enable HTTP when both vhost and default cert are missing

Nicolas Duchon hace 7 meses
padre
commit
023a3d17da

+ 4 - 6
docs/README.md

@@ -580,13 +580,11 @@ By default, [HTTP Strict Transport Security (HSTS)](https://developer.mozilla.or
 
 ### Missing Certificate
 
-If no matching certificate is found for a given virtual host, nginx-proxy will:
+If no matching certificate is found for a given virtual host, nginx-proxy will configure nginx to use the default certificate (`default.crt` with `default.key`).
 
-- configure nginx to use the default certificate (`default.crt` with `default.key`),
-- force enable HTTP; i.e. `HTTPS_METHOD` will switch to `noredirect` if it was set to `nohttp` or `redirect`.
-  If this switch to HTTP is not wanted set `ENABLE_HTTP_ON_MISSING_CERT=false` (default is `true`).
-
-If the default certificate is also missing, nginx-proxy will configure nginx to reject the SSL handshake. Client browsers will render a TLS error page. As of October 2024, web browsers display the following error messages:
+If the default certificate is also missing, nginx-proxy will:
+- force enable HTTP; i.e. `HTTPS_METHOD` will switch to `noredirect` if it was set to `nohttp` or `redirect`. If this switch to HTTP is not wanted set `ENABLE_HTTP_ON_MISSING_CERT=false` (default is `true`).
+- configure nginx to reject the SSL handshake for this vhost. Client browsers will render a TLS error page. As of October 2024, web browsers display the following error messages:
 
 #### Chrome:
 

+ 4 - 2
nginx.tmpl

@@ -681,8 +681,10 @@ proxy_set_header Proxy "";
     {{- $default := eq $globals.config.default_host $hostname }}
     {{- $https_method := groupByKeys $vhost_containers "Env.HTTPS_METHOD" | first | default $globals.config.https_method }}
     {{- $enable_http_on_missing_cert := groupByKeys $vhost_containers "Env.ENABLE_HTTP_ON_MISSING_CERT" | first | default $globals.config.enable_http_on_missing_cert | parseBool }}
-    {{- /* When the certificate is missing we want to ensure that HTTP is enabled; hence switching from 'nohttp' or 'redirect' to 'noredirect' */}}
-    {{- if (and $enable_http_on_missing_cert (not $cert_ok) (or (eq $https_method "nohttp") (eq $https_method "redirect"))) }}
+    {{- /* When both the vhost and default certificates are missing we want to ensure that HTTP is enabled; hence switching from 'nohttp' or 'redirect' to 'noredirect' */}}
+    {{- $https_method_disable_http := list "nohttp" "redirect" | has $https_method }}
+    {{- $no_vhost_or_default_cert := or $cert_ok $globals.config.default_cert_ok | not }}
+    {{- if and $https_method_disable_http $no_vhost_or_default_cert $enable_http_on_missing_cert }}
         {{- $https_method = "noredirect" }}
     {{- end }}
     {{- $http2_enabled := groupByLabel $vhost_containers "com.github.nginx-proxy.nginx-proxy.http2.enable" | keys | first | default $globals.config.enable_http2 | parseBool }}

+ 1 - 1
test/test_fallback.data/nohttp-on-app.yml

@@ -5,7 +5,7 @@ services:
     image: nginxproxy/nginx-proxy:test
     volumes:
       - /var/run/docker.sock:/tmp/docker.sock:ro
-      - ./withdefault.certs:/etc/nginx/certs:ro
+      - ./nodefault.certs:/etc/nginx/certs:ro
     environment:
       HTTPS_METHOD: redirect
 

+ 1 - 1
test/test_fallback.data/nohttp-with-missing-cert.yml

@@ -5,7 +5,7 @@ services:
     image: nginxproxy/nginx-proxy:test
     volumes:
       - /var/run/docker.sock:/tmp/docker.sock:ro
-      - ./withdefault.certs:/etc/nginx/certs:ro
+      - ./nodefault.certs:/etc/nginx/certs:ro
     environment:
       HTTPS_METHOD: nohttp
 

+ 1 - 1
test/test_fallback.data/nohttp.yml

@@ -5,7 +5,7 @@ services:
     image: nginxproxy/nginx-proxy:test
     volumes:
       - /var/run/docker.sock:/tmp/docker.sock:ro
-      - ./withdefault.certs:/etc/nginx/certs:ro
+      - ./nodefault.certs:/etc/nginx/certs:ro
     environment:
       HTTPS_METHOD: nohttp
 

+ 8 - 8
test/test_fallback.py

@@ -43,7 +43,7 @@ INTERNAL_ERR_RE = re.compile("TLSV1_UNRECOGNIZED_NAME")
     ("withdefault.yml", "https://https-only.nginx-proxy.test/", 200, None),
     ("withdefault.yml", "http://http-only.nginx-proxy.test/", 200, None),
     ("withdefault.yml", "https://http-only.nginx-proxy.test/", 503, None),
-    ("withdefault.yml", "http://missing-cert.nginx-proxy.test/", 200, None),
+    ("withdefault.yml", "http://missing-cert.nginx-proxy.test/", 301, None),
     ("withdefault.yml", "https://missing-cert.nginx-proxy.test/", 200, None),
     ("withdefault.yml", "http://unknown.nginx-proxy.test/", 503, None),
     ("withdefault.yml", "https://unknown.nginx-proxy.test/", 503, None),
@@ -58,24 +58,24 @@ INTERNAL_ERR_RE = re.compile("TLSV1_UNRECOGNIZED_NAME")
     ("nodefault.yml", "https://missing-cert.nginx-proxy.test/", None, INTERNAL_ERR_RE),
     ("nodefault.yml", "http://unknown.nginx-proxy.test/", 503, None),
     ("nodefault.yml", "https://unknown.nginx-proxy.test/", None, INTERNAL_ERR_RE),
-    # HTTPS_METHOD=nohttp on nginx-proxy, HTTPS_METHOD unset on the app container.
+    # HTTPS_METHOD=nohttp on nginx-proxy, no default.crt, HTTPS_METHOD unset on the app container.
     ("nohttp.yml", "http://https-only.nginx-proxy.test/", 503, None),
     ("nohttp.yml", "https://https-only.nginx-proxy.test/", 200, None),
     ("nohttp.yml", "http://unknown.nginx-proxy.test/", 503, None),
-    ("nohttp.yml", "https://unknown.nginx-proxy.test/", 503, None),
-    # HTTPS_METHOD=redirect on nginx-proxy, HTTPS_METHOD=nohttp on the app container.
+    ("nohttp.yml", "https://unknown.nginx-proxy.test/", None, INTERNAL_ERR_RE),
+    # HTTPS_METHOD=redirect on nginx-proxy, no default.crt, HTTPS_METHOD=nohttp on the app container.
     ("nohttp-on-app.yml", "http://https-only.nginx-proxy.test/", 503, None),
     ("nohttp-on-app.yml", "https://https-only.nginx-proxy.test/", 200, None),
     ("nohttp-on-app.yml", "http://unknown.nginx-proxy.test/", 503, None),
-    ("nohttp-on-app.yml", "https://unknown.nginx-proxy.test/", 503, None),
-    # Same as nohttp.yml, except there is a vhost with a missing cert.  This causes its
+    ("nohttp-on-app.yml", "https://unknown.nginx-proxy.test/", None, INTERNAL_ERR_RE),
+    # Same as nohttp.yml, except there is a vhost with a missing cert. This causes its
     # HTTPS_METHOD=nohttp setting to effectively become HTTPS_METHOD=noredirect.
     ("nohttp-with-missing-cert.yml", "http://https-only.nginx-proxy.test/", 503, None),
     ("nohttp-with-missing-cert.yml", "https://https-only.nginx-proxy.test/", 200, None),
     ("nohttp-with-missing-cert.yml", "http://missing-cert.nginx-proxy.test/", 200, None),
-    ("nohttp-with-missing-cert.yml", "https://missing-cert.nginx-proxy.test/", 200, None),
+    ("nohttp-with-missing-cert.yml", "https://missing-cert.nginx-proxy.test/", None, INTERNAL_ERR_RE),
     ("nohttp-with-missing-cert.yml", "http://unknown.nginx-proxy.test/", 503, None),
-    ("nohttp-with-missing-cert.yml", "https://unknown.nginx-proxy.test/", 503, None),
+    ("nohttp-with-missing-cert.yml", "https://unknown.nginx-proxy.test/", None, INTERNAL_ERR_RE),
     # HTTPS_METHOD=nohttps on nginx-proxy, HTTPS_METHOD unset on the app container.
     ("nohttps.yml", "http://http-only.nginx-proxy.test/", 200, None),
     ("nohttps.yml", "https://http-only.nginx-proxy.test/", None, INTERNAL_ERR_RE),