Add Gitea SSO, fix security audit findings, harden production defaults

Gitea SSO: cookie-based single sign-on via nginx auth_request — sets
cml_session cookie on login/refresh, validates via /api/auth/gitea-sso-validate,
injects X-WEBAUTH-USER header for reverse proxy auth. Dedicated GITEA_SSO_SECRET
and SERVICE_PASSWORD_SALT env vars isolate secret rotation.

Security fixes from March 30 audit: IDOR on ticketed events (requireEventOwnership
middleware), IDOR on action items (admin/assignee/creator check), path traversal
on photos (resolve-based validation), CSV upload size limit (5MB), shared calendar
email exposure removed.

Gitea provisioner: auto-sync docs repo collaborator access based on role
(CONTENT_ROLES get write, SUPER_ADMIN gets admin). Gitea client extended
with collaborator management API methods.

Production hardening: NODE_ENV defaults to production in docker-compose.prod.yml,
Grafana anonymous auth disabled, install.sh branch ref updated to main.

Admin UI: moved docs reset from toolbar to MkDocs Settings danger zone,
improved collab Ctrl+S to explicitly save + cache-bust preview.

MkDocs site rebuild with updated repo data, upgrade screenshots, and content.

Bunker Admin
This commit is contained in:
2026-03-31 11:20:01 -06:00
parent 9321aeb263
commit 91db29402c
175 changed files with 9683 additions and 1184 deletions

View File

@@ -1,4 +1,5 @@
# Gitea — allows iframe embedding from admin (app.${DOMAIN})
# SSO: nginx validates cml_session cookie via API auth_request, injects X-WEBAUTH-USER
server {
listen 80;
server_name git.${DOMAIN};
@@ -7,7 +8,20 @@ server {
# Increase max body size for large git pushes (2GB)
client_max_body_size 2048M;
# Internal: validate SSO session cookie via API
location = /_auth {
internal;
set $upstream_api http://changemaker-v2-api:4000;
proxy_pass $upstream_api/api/auth/gitea-sso-validate;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header Cookie $http_cookie;
}
location / {
auth_request /_auth;
auth_request_set $gitea_user $upstream_http_x_gitea_user;
set $upstream_gitea http://gitea-changemaker:3000;
proxy_pass $upstream_gitea;
proxy_hide_header X-Frame-Options;
@@ -15,6 +29,8 @@ server {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# SSO header — empty string if not authenticated (Gitea ignores it)
proxy_set_header X-WEBAUTH-USER $gitea_user;
}
}
@@ -300,11 +316,26 @@ server {
}
}
# Gitea embed proxy — SSO via auth_request (same as subdomain block)
server {
listen ${GITEA_EMBED_PORT};
# Increase max body size for large git pushes (2GB)
client_max_body_size 2048M;
# Internal: validate SSO session cookie via API
location = /_auth {
internal;
set $upstream_api http://changemaker-v2-api:4000;
proxy_pass $upstream_api/api/auth/gitea-sso-validate;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header Cookie $http_cookie;
}
location / {
auth_request /_auth;
auth_request_set $gitea_user $upstream_http_x_gitea_user;
set $upstream_gitea http://gitea-changemaker:3000;
proxy_pass $upstream_gitea;
proxy_hide_header X-Frame-Options;
@@ -314,6 +345,8 @@ server {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# SSO header — empty string if not authenticated (Gitea ignores it)
proxy_set_header X-WEBAUTH-USER $gitea_user;
}
}