From 11e92cdae0461428018a1923c5b197350020c498 Mon Sep 17 00:00:00 2001 From: Mikko Heikkinen Date: Sat, 30 Nov 2024 14:31:08 +0200 Subject: [PATCH] Add security headers --- README.md | 2 ++ app/main.py | 11 +++++++++++ tests-playwright/requirements.txt | 4 ++-- tests-playwright/test_admin_login.py | 3 ++- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 40ec25c..01f88b2 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,8 @@ The application will be visible http://localhost:8081 - Login to playwright container with `docker exec -ti species-challenge-playwright-1 bash` - Run tests with `python -m pytest -v -s`. The `-s` option enables print outputs. +- Note: if tests fail with `page.goto("http://web:8081/login?token=nonrealtoken")`, restart the Docker containers and try again. + ## Deploying to Rahti 2 - Run e2e-tests diff --git a/app/main.py b/app/main.py index d431f12..646e84b 100644 --- a/app/main.py +++ b/app/main.py @@ -70,6 +70,17 @@ def before_request(): # Make itsystem_id available for controllers g.itsystem_name = get_version_info() +@app.after_request +def set_security_headers(response): + response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains' + response.headers['Content-Security-Policy'] = "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'" + response.headers['X-Content-Type-Options'] = 'nosniff' + response.headers['X-Frame-Options'] = 'SAMEORIGIN' + response.headers['Referrer-Policy'] = 'strict-origin-when-cross-origin' + response.headers['X-Permitted-Cross-Domain-Policies'] = 'none' + response.headers['Feature-Policy'] = "microphone 'none'" + return response + # Make data available for templates @app.context_processor def inject_data(): diff --git a/tests-playwright/requirements.txt b/tests-playwright/requirements.txt index 8e4d701..fab88bc 100644 --- a/tests-playwright/requirements.txt +++ b/tests-playwright/requirements.txt @@ -1,2 +1,2 @@ -pytest -pytest-playwright +pytest == 8.3.* +pytest-playwright == 0.6.* diff --git a/tests-playwright/test_admin_login.py b/tests-playwright/test_admin_login.py index a8965de..6d46eca 100644 --- a/tests-playwright/test_admin_login.py +++ b/tests-playwright/test_admin_login.py @@ -6,6 +6,7 @@ from urllib.parse import urljoin, urlparse, parse_qs + def extract_token(url): parsed_url = urlparse(url) query_params = parse_qs(parsed_url.query) @@ -59,7 +60,7 @@ def test_login_and_save_state(browser): # Issue: Playwright cannot follow these login redirections, but gets stuck at /login. # Workaround: extract token and navigate to /login manually. - token = extract_token(page.url) + token = extract_token(page.url) page.goto("http://web:8081/login?token=" + token) page.wait_for_selector('#logout')