Pre-release audit fixes: - External Administrators can only act on investors already in their own funds (grant_access, create_statement, set_partner_exited, import match), closing a cross-fund account-takeover chain. - Role and is_active changes are gated: no self-escalation, non-approvers cannot mint or alter approver accounts, and the Service Admin is protected. - must_change_password is enforced server-side, not just in the client. - Session cookie is Secure with a 12h max-age and SameSite; CSP and standard security headers on every response; the app refuses to boot on a known or short session secret; uvicorn runs with proxy-headers so login throttling keys on the real client IP behind the platform proxy. - Import preview no longer confirms cross-fund investors; no-store on document downloads. - Adds backend/tests/test_security_hardening.py (15 tests); full suite 76 passing. - SECURITY-AUDIT.md records the swarm audit, findings, and remediation status.
51 lines
1.5 KiB
Docker
51 lines
1.5 KiB
Docker
# Build context is the repo root (docker build -f deploy/Dockerfile .)
|
|
|
|
# --- Frontend build stage ---
|
|
# Build on the native builder arch ($BUILDPLATFORM) so the JS bundler runs without
|
|
# cross-arch emulation. The output is static assets (HTML/CSS/JS), which are
|
|
# architecture-independent and copied into the target-arch runtime stage below.
|
|
FROM --platform=$BUILDPLATFORM node:20-slim AS frontend-build
|
|
|
|
WORKDIR /build
|
|
COPY frontend/package.json frontend/package-lock.json ./
|
|
RUN npm ci --include=dev
|
|
COPY frontend/ ./
|
|
RUN npx vite build
|
|
|
|
# --- Backend + runtime stage ---
|
|
FROM python:3.11-slim
|
|
|
|
WORKDIR /app
|
|
|
|
# Install Python deps
|
|
COPY backend/pyproject.toml ./
|
|
COPY backend/ten31portal/ ./ten31portal/
|
|
COPY backend/alembic/ ./alembic/
|
|
COPY backend/alembic.ini ./
|
|
RUN pip install --no-cache-dir .
|
|
|
|
# Copy built frontend
|
|
COPY --from=frontend-build /build/dist ./static/
|
|
|
|
# Startup script
|
|
COPY deploy/start.sh ./start.sh
|
|
RUN chmod +x ./start.sh
|
|
|
|
# Data volume mount point
|
|
RUN mkdir -p /data
|
|
|
|
# Unprivileged account for the server process. The container still starts as root (see start.sh)
|
|
# so it can chown the platform-mounted /data volume, then drops to this uid via setpriv.
|
|
RUN groupadd --gid 10001 appuser \
|
|
&& useradd --uid 10001 --gid 10001 --no-create-home --shell /usr/sbin/nologin appuser
|
|
|
|
ENV TEN31_DB_PATH=/data/portal.db
|
|
ENV TEN31_DOCS_DIR=/data/documents
|
|
ENV TEN31_SESSION_SECRET=change-me
|
|
# Served behind the platform's TLS-terminating proxy, so the session cookie is Secure.
|
|
ENV TEN31_SESSION_COOKIE_SECURE=true
|
|
|
|
EXPOSE 8000
|
|
|
|
CMD ["./start.sh"]
|