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