Просмотр исходного кода

tests: Add tests for how Let's Encrypt ACME challenge is handled

At the moment no changes to functionality are done, only the current
behavior is captured.
Povilas Kanapickas 1 год назад
Родитель
Сommit
d6c38a0bab

+ 7 - 0
test/conftest.py

@@ -510,6 +510,13 @@ def nginxproxy():
     yield requests_for_docker()
 
 
+@pytest.fixture()
+def acme_challenge_path():
+    """
+    Provides fake Let's Encrypt ACME challenge path used in certain tests
+    """
+    return ".well-known/acme-challenge/test-filename"
+
 ###############################################################################
 #
 # Py.test hooks

+ 1 - 0
test/test_ssl/acme_root/.well-known/acme-challenge/test-filename

@@ -0,0 +1 @@
+challenge-teststring

+ 9 - 0
test/test_ssl/test_https_port.py

@@ -17,3 +17,12 @@ def test_nonstandardport_Host_header(docker_compose, nginxproxy):
     r = nginxproxy.get("https://web.nginx-proxy.tld:8443/headers")
     assert r.status_code == 200
     assert "Host: web.nginx-proxy.tld:8443" in r.text
+
+@pytest.mark.parametrize("subdomain", ["foo", "bar"])
+def test_web1_acme_challenge_works(docker_compose, nginxproxy, acme_challenge_path, subdomain):
+    r = nginxproxy.get(
+        f"http://{subdomain}.nginx-proxy.tld:8080/{acme_challenge_path}",
+        allow_redirects=False
+    )
+    assert r.status_code == 200
+    assert "challenge-teststring\n" in r.text

+ 1 - 0
test/test_ssl/test_https_port.yml

@@ -14,6 +14,7 @@ services:
     volumes:
       - /var/run/docker.sock:/tmp/docker.sock:ro
       - ./certs:/etc/nginx/certs:ro
+      - ./acme_root:/usr/share/nginx/html:ro
     environment:
       HTTP_PORT: 8080
       HTTPS_PORT: 8443

+ 7 - 0
test/test_ssl/test_nohttp.py

@@ -7,6 +7,13 @@ def test_web2_http_is_connection_refused(docker_compose, nginxproxy):
         nginxproxy.get("http://web2.nginx-proxy.tld/")
 
 
+def test_web2_http_is_connection_refused_for_acme_challenge(
+    docker_compose, nginxproxy, acme_challenge_path
+):
+    with pytest.raises(requests.exceptions.RequestException, match="Connection refused"):
+        nginxproxy.get(f"http://web2.nginx-proxy.tld/{acme_challenge_path}")
+
+
 def test_web2_https_is_forwarded(docker_compose, nginxproxy):
     r = nginxproxy.get("https://web2.nginx-proxy.tld/port", allow_redirects=False)
     assert r.status_code == 200

+ 1 - 0
test/test_ssl/test_nohttp.yml

@@ -15,3 +15,4 @@ services:
     volumes:
       - /var/run/docker.sock:/tmp/docker.sock:ro
       - ./certs:/etc/nginx/certs:ro
+      - ./acme_root:/usr/share/nginx/html:ro

+ 8 - 0
test/test_ssl/test_nohttps.py

@@ -10,3 +10,11 @@ def test_http_is_forwarded(docker_compose, nginxproxy):
 def test_https_is_disabled(docker_compose, nginxproxy):
     with pytest.raises(ConnectionError):
         nginxproxy.get("https://web.nginx-proxy.tld/", allow_redirects=False)
+
+
+def test_http_acme_challenge_does_not_work(docker_compose, nginxproxy, acme_challenge_path):
+    r = nginxproxy.get(
+        f"http://web.nginx-proxy.tld/{acme_challenge_path}",
+        allow_redirects=False
+    )
+    assert r.status_code == 404

+ 1 - 0
test/test_ssl/test_nohttps.yml

@@ -14,3 +14,4 @@ services:
     image: nginxproxy/nginx-proxy:test
     volumes:
       - /var/run/docker.sock:/tmp/docker.sock:ro
+      - ./acme_root:/usr/share/nginx/html:ro

+ 9 - 1
test/test_ssl/test_noredirect.py

@@ -16,4 +16,12 @@ def test_web3_https_is_forwarded(docker_compose, nginxproxy):
 def test_web2_HSTS_policy_is_inactive(docker_compose, nginxproxy):
     r = nginxproxy.get("https://web3.nginx-proxy.tld/port", allow_redirects=False)
     assert "answer from port 83\n" in r.text
-    assert "Strict-Transport-Security" not in r.headers
+    assert "Strict-Transport-Security" not in r.headers
+
+
+def test_web3_acme_challenge_does_not_work(docker_compose, nginxproxy, acme_challenge_path):
+    r = nginxproxy.get(
+        f"http://web3.nginx-proxy.tld/{acme_challenge_path}",
+        allow_redirects=False
+    )
+    assert r.status_code == 404

+ 1 - 0
test/test_ssl/test_noredirect.yml

@@ -15,3 +15,4 @@ services:
     volumes:
       - /var/run/docker.sock:/tmp/docker.sock:ro
       - ./certs:/etc/nginx/certs:ro
+      - ./acme_root:/usr/share/nginx/html:ro

+ 9 - 0
test/test_ssl/test_virtual_path.py

@@ -1,4 +1,5 @@
 import pytest
+from requests import ConnectionError
 
 @pytest.mark.parametrize("path", ["web1", "web2"])
 def test_web1_http_redirects_to_https(docker_compose, nginxproxy, path):
@@ -13,3 +14,11 @@ def test_web1_https_is_forwarded(docker_compose, nginxproxy, path, port):
     assert r.status_code == 200
     assert "answer from port %d\n" % port in r.text
 
+
+@pytest.mark.parametrize("port", [81, 82])
+def test_acme_challenge_does_not_work(docker_compose, nginxproxy, acme_challenge_path, port):
+    with pytest.raises(ConnectionError):
+        nginxproxy.get(
+            f"http://www.nginx-proxy.tld:{port}/{acme_challenge_path}",
+            allow_redirects=False
+        )

+ 1 - 0
test/test_ssl/test_virtual_path.yml

@@ -26,3 +26,4 @@ services:
     volumes:
       - /var/run/docker.sock:/tmp/docker.sock:ro
       - ./certs:/etc/nginx/certs:ro
+      - ./acme_root:/usr/share/nginx/html:ro

+ 10 - 0
test/test_ssl/test_wildcard.py

@@ -21,3 +21,13 @@ def test_web1_HSTS_policy_is_active(docker_compose, nginxproxy, subdomain):
     r = nginxproxy.get(f"https://{subdomain}.nginx-proxy.tld/port", allow_redirects=False)
     assert "answer from port 81\n" in r.text
     assert "Strict-Transport-Security" in r.headers
+
+
+@pytest.mark.parametrize("subdomain", ["foo", "bar"])
+def test_web1_acme_challenge_works(docker_compose, nginxproxy, acme_challenge_path, subdomain):
+    r = nginxproxy.get(
+        f"http://web3.nginx-proxy.tld/{acme_challenge_path}",
+        allow_redirects=False
+    )
+    assert r.status_code == 200
+    assert "challenge-teststring\n" in r.text

+ 1 - 0
test/test_ssl/test_wildcard.yml

@@ -14,3 +14,4 @@ services:
     volumes:
       - /var/run/docker.sock:/tmp/docker.sock:ro
       - ./certs:/etc/nginx/certs:ro
+      - ./acme_root:/usr/share/nginx/html:ro

+ 1 - 0
test/test_ssl/wildcard_cert_and_nohttps/acme_root/.well-known/acme-challenge/test-filename

@@ -0,0 +1 @@
+challenge-teststring

+ 1 - 0
test/test_ssl/wildcard_cert_and_nohttps/docker-compose.yml

@@ -7,6 +7,7 @@ services:
     volumes:
       - /var/run/docker.sock:/tmp/docker.sock:ro
       - ./certs:/etc/nginx/certs:ro
+      - ./acme_root:/usr/share/nginx/html:ro
 
   web1:
     image: web

+ 23 - 0
test/test_ssl/wildcard_cert_and_nohttps/test_wildcard_cert_nohttps.py

@@ -1,5 +1,6 @@
 import pytest
 from ssl import CertificateError
+from requests import ConnectionError
 from requests.exceptions import SSLError
 
 
@@ -32,3 +33,25 @@ def test_https_request_to_nohttps_vhost_goes_to_fallback_server(docker_compose,
 
     r = nginxproxy.get("https://3.web.nginx-proxy.tld/port", verify=False)
     assert r.status_code == 503
+
+
+@pytest.mark.parametrize("subdomain,acme_should_work", [
+    (1, True),
+    (2, True),
+    (3, False),
+])
+def test_acme_challenge_works(
+    docker_compose, nginxproxy, acme_challenge_path, subdomain, acme_should_work
+):
+    if acme_should_work:
+        r = nginxproxy.get(
+            f"https://{subdomain}.web.nginx-proxy.tld/{acme_challenge_path}",
+            allow_redirects=False
+        )
+        assert r.status_code == 404
+    else:
+        with pytest.raises(ConnectionError):
+            nginxproxy.get(
+                f"https://{subdomain}.web.nginx-proxy.tld/{acme_challenge_path}",
+                allow_redirects=False
+            )