From baeb3748a586246378dfeb21bf6802e4434839fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20K=C3=BCnzel?= <simonk@fsmpi.rwth-aachen.de> Date: Fri, 14 Jun 2024 17:03:53 +0200 Subject: [PATCH] Remove nginx. Fix Cross Site requests --- Dockerfile | 25 +-------------- config/api_example_config.py | 11 +++++++ config/nginx_example.conf | 55 -------------------------------- config/uwsgi_example.ini | 11 ++++--- docker-compose.yaml | 1 - docker_start.sh | 5 ++- src/api/routes/authentication.py | 19 ++++++++--- src/run_tests.py | 0 8 files changed, 36 insertions(+), 91 deletions(-) delete mode 100644 config/nginx_example.conf mode change 100644 => 100755 src/run_tests.py diff --git a/Dockerfile b/Dockerfile index bd8156c..8e5d737 100755 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM nginx:stable-alpine +FROM python:3.12 # Empty by default ARG GIT_COMMIT_HASH= @@ -8,32 +8,9 @@ ENV VIDEOAG_API_GIT_COMMIT_HASH $GIT_COMMIT_HASH RUN mkdir -p /code WORKDIR /code -RUN apk update && apk add --no-cache --virtual .build-deps build-base linux-headers python3-dev -RUN apk add --no-cache \ - bash \ - python3 \ - py3-pip \ - # Required for uwsgi (Logging) - pcre2 \ - pcre2-dev \ - # Required for psycopg - libpq-dev \ - git \ - logrotate - -# create a virtual environment -RUN python3 -m venv /venv -ENV PATH="/venv/bin:$PATH" COPY requirements.txt /code RUN pip3 install -r requirements.txt -RUN apk del .build-deps - -RUN adduser -D -g '' uwsgi -RUN mkdir /uwsgi/ -RUN chown uwsgi /uwsgi/ -RUN chgrp uwsgi /uwsgi/ - COPY docker_start.sh /code/docker_start.sh COPY .pylintrc /code/.pylintrc COPY tests/ /code/tests/ diff --git a/config/api_example_config.py b/config/api_example_config.py index 78446d8..41680c5 100644 --- a/config/api_example_config.py +++ b/config/api_example_config.py @@ -8,6 +8,17 @@ API_SERVER_NAME = "dev" # Must include the last / FILE_PATH_PREFIX = "https://video.fsmpi.rwth-aachen.de/files/" +# Used for all cookies +# While the frontend and api are on different subdomains, that still counts as 'same-site' +COOKIES_SAMESITE = "strict" +COOKIES_SECURE = False +COOKIES_DOMAIN = ".video.fsmpi.rwth-aachen.de" + +# These are flask's options for the session cookie +SESSION_COOKIE_SAMESITE = COOKIES_SAMESITE +SESSION_COOKIE_SECURE = COOKIES_SECURE +SESSION_COOKIE_DOMAIN = COOKIES_DOMAIN + # Used by flask to sign the cookies SECRET_KEY = "something random" diff --git a/config/nginx_example.conf b/config/nginx_example.conf deleted file mode 100644 index 1d67d7d..0000000 --- a/config/nginx_example.conf +++ /dev/null @@ -1,55 +0,0 @@ -# Debug-only nginx config for this website - -pid ../nginx.pid; -error_log log/nginx.err.log; - -events { - worker_connections 768; -} - -http { - access_log log/nginx.log; - client_body_in_file_only off; - include /etc/nginx/mime.types; - default_type application/octet-stream; - sendfile on; - tcp_nopush on; - tcp_nodelay on; - keepalive_timeout 65; - types_hash_max_size 2048; - server { - listen 5000; - #listen [::]:5000; - #listen localhost:5000; - - location /files/ { - # TODO this auth request path is missing - auth_request /internal/auth; - auth_request_set $trackingcookie $upstream_http_set_cookie; - # For use with sshfs (recommended) - #alias /mnt/videoag/srv/videoag/released/; - #add_header Set-Cookie $trackingcookie; - # For use without sshfs - # NO TRAILING SLASH so that /files/ will not be skipped of the request! - proxy_pass https://video.fsmpi.rwth-aachen.de; - proxy_set_header Host "video.fsmpi.rwth-aachen.de"; - proxy_set_header Set-Cookie $trackingcookie; - } - - location /api { - include /etc/nginx/uwsgi_params; - uwsgi_param REQUEST_URI $uri; - uwsgi_param HTTP_X_ORIGINAL_URI $request_uri; - uwsgi_param HTTP_X_REAL_IP $remote_addr; - uwsgi_pass unix:/uwsgi/uwsgi.sock; - } - - location / { - proxy_pass http://host.docker.internal:3000/; - # pass websocket for react fast-refresh - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - } - } -} diff --git a/config/uwsgi_example.ini b/config/uwsgi_example.ini index 7714050..3ba12c1 100644 --- a/config/uwsgi_example.ini +++ b/config/uwsgi_example.ini @@ -1,11 +1,14 @@ [uwsgi] strict = true # Fail on invalid/unknown options -uid = uwsgi -gid = uwsgi +# It's running in a container, so we can just use root instead of creating a new user +uid = root +gid = root -chmod-socket = 666 -socket = /uwsgi/uwsgi.sock +http = 0.0.0.0:5000 +add-header = Access-Control-Allow-Origin: http://localhost:3000 +add-header = Access-Control-Allow-Credentials: true +add-header = Access-Control-Allow-Headers: Cookie, Content-Type, X-Csrf-Token manage-script-name = true chdir = ./src/ diff --git a/docker-compose.yaml b/docker-compose.yaml index 30f40bd..c613c90 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -10,5 +10,4 @@ services: environment: - VIDEOAG_API_CONFIG=../config/api_example_config.py - VIDEOAG_API_LIVE_CONFIG=../config/live_config.json - - VIDEOAG_NGINX_CONFIG=/code/config/nginx_example.conf - VIDEOAG_UWSGI_CONFIG=/code/config/uwsgi_example.ini \ No newline at end of file diff --git a/docker_start.sh b/docker_start.sh index 250ea17..0c9598c 100755 --- a/docker_start.sh +++ b/docker_start.sh @@ -20,7 +20,6 @@ if [ $# = 1 ] && [ $1 = "-test" ]; then python3 -m coverage html -d "../coverage/html/" --data-file "../coverage/.data" --include "./*" || { echo "Coverage report html failed"; exit 1; } else - echo "Running nginx and uWSGI" - nginx -c ${VIDEOAG_NGINX_CONFIG} -p . & - exec uwsgi --ini ${VIDEOAG_UWSGI_CONFIG} + echo "Running uWSGI" + uwsgi --ini ${VIDEOAG_UWSGI_CONFIG} fi diff --git a/src/api/routes/authentication.py b/src/api/routes/authentication.py index cfb5f62..1e2e7c7 100644 --- a/src/api/routes/authentication.py +++ b/src/api/routes/authentication.py @@ -10,6 +10,9 @@ from api.authentication import (is_lecture_authenticated, get_currently_authenti import api _API_AUTH_RATE_LIMITERS = create_configured_host_rate_limiters("authentication", api.config["API_AUTH_RATE_LIMIT"]) +_COOKIES_SAMESITE = api.config.get("COOKIES_SAMESITE", "strict") +_COOKIES_SECURE = api.config.get("COOKIES_SECURE", True) +_COOKIES_DOMAIN = api.config.get("COOKIES_DOMAIN", None) @api_add_route("/authentication/password", ["POST"]) @@ -90,15 +93,23 @@ def _set_moderator_cookies(response: ApiResponse): get_csrf_token(), max_age=None, # Only for session httponly=False, - samesite="Strict") + samesite=_COOKIES_SAMESITE, + secure=_COOKIES_SECURE, + domain=_COOKIES_DOMAIN) # Used for nginx caching - response.response.set_cookie("moderator", "#", max_age=None, httponly=True, samesite="Strict") + response.response.set_cookie("moderator", + "#", + max_age=None, + httponly=True, + samesite=_COOKIES_SAMESITE, + secure=_COOKIES_SECURE, + domain=_COOKIES_DOMAIN) @api_route("/authentication/moderator_logout", ["POST"], allow_while_readonly=True) def api_route_authentication_moderator_logout(): logout_moderator() response = ApiResponse({}) - response.response.delete_cookie("csrf_token", httponly=False, samesite="Strict") - response.response.delete_cookie("moderator", httponly=True, samesite="Strict") + response.response.delete_cookie("csrf_token", httponly=False, samesite=_COOKIES_SAMESITE, secure=_COOKIES_SECURE, domain=_COOKIES_DOMAIN) + response.response.delete_cookie("moderator", httponly=True, samesite=_COOKIES_SAMESITE, secure=_COOKIES_SECURE, domain=_COOKIES_DOMAIN) return response diff --git a/src/run_tests.py b/src/run_tests.py old mode 100644 new mode 100755 -- GitLab