diff --git a/Dockerfile b/Dockerfile index bd8156c60059dffb55f2d88083d7561e32113b9f..8e5d737b2e4c77678fa60f6e21778892122d4a2e 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 78446d8f3e8164d64bc8f6c37d80f24ef28ced02..41680c578d8d6c378f8b2b168217bf1d14a541ec 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 1d67d7d0827e26e90d715316488ce9e4cb36fc9e..0000000000000000000000000000000000000000 --- 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 7714050b6dd64fbbe420f6a6b350b612dd40c831..3ba12c1a587ff9b450e6b4de92198c56ed8e499b 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 30f40bde8fd2404ed448a0da704c8e20d04cf473..c613c904116d7252b9b2b0d17eec446027e6e75f 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 250ea1703e449e15b092b86f2315c52bf1fe51cf..0c9598cab070b25c245b22a76685ddaadd5eeb08 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 cfb5f62af9d292e8b885d6338ab4a795782764e9..1e2e7c7083993f0e1b6d91b952befda5ff1ec554 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