diff --git a/docker/ploughshares/Dockerfile b/docker/ploughshares/Dockerfile index d8a9d99..8644578 100644 --- a/docker/ploughshares/Dockerfile +++ b/docker/ploughshares/Dockerfile @@ -25,8 +25,27 @@ COPY static/ ./static/ # Create uploads directory RUN mkdir -p uploads +# Calculate CSP hashes for static resources +RUN echo "Calculating CSP hashes for static resources..." && \ + # Calculate hash for JS files + JS_HASH=$(openssl dgst -sha256 -binary static/js/bootstrap.bundle.min.js | openssl base64) && \ + echo "JS hash: $JS_HASH" && \ + # Calculate hash for CSS files + CSS_HASH=$(openssl dgst -sha256 -binary static/css/bootstrap.min.css | openssl base64) && \ + echo "CSS hash: $CSS_HASH" && \ + CUSTOM_CSS_HASH=$(openssl dgst -sha256 -binary static/css/custom.css | openssl base64) && \ + echo "Custom CSS hash: $CUSTOM_CSS_HASH" && \ + # Create environment variables file for CSP hashes + echo "export CSP_JS_HASH=$JS_HASH" > /app/csp_hashes.env && \ + echo "export CSP_CSS_HASH=$CSS_HASH" >> /app/csp_hashes.env && \ + echo "export CSP_CUSTOM_CSS_HASH=$CUSTOM_CSS_HASH" >> /app/csp_hashes.env + +# Set build argument for APP_VERSION +ARG APP_VERSION=unknown +ENV APP_VERSION=$APP_VERSION + # Expose the port the app runs on EXPOSE 5001 -# Command to run the application -CMD ["python", "app.py"] \ No newline at end of file +# Command to run the application with CSP hashes +CMD ["/bin/bash", "-c", "source /app/csp_hashes.env && exec python app.py"] \ No newline at end of file diff --git a/docker/ploughshares/app.py b/docker/ploughshares/app.py index 9a1f6c2..c17ef13 100644 --- a/docker/ploughshares/app.py +++ b/docker/ploughshares/app.py @@ -40,12 +40,27 @@ app.config['VERSION'] = VERSION APP_DOMAIN = os.environ.get('APP_DOMAIN', '') APP_ENV = os.environ.get('APP_ENV', 'development') +# Get CSP hashes from environment variables +CSP_JS_HASH = os.environ.get('CSP_JS_HASH', '') +CSP_CSS_HASH = os.environ.get('CSP_CSS_HASH', '') +CSP_CUSTOM_CSS_HASH = os.environ.get('CSP_CUSTOM_CSS_HASH', '') + +# Log the CSP hashes +if CSP_JS_HASH: + logger.info(f"Using pre-calculated CSP hash for JS: sha256-{CSP_JS_HASH}") +if CSP_CSS_HASH: + logger.info(f"Using pre-calculated CSP hash for CSS: sha256-{CSP_CSS_HASH}") +if CSP_CUSTOM_CSS_HASH: + logger.info(f"Using pre-calculated CSP hash for custom CSS: sha256-{CSP_CUSTOM_CSS_HASH}") + # Configure security headers with Talisman -# Base CSP settings - much more restrictive now that we use local resources +# Base CSP settings with pre-calculated hashes for static resources csp = { 'default-src': ["'self'"], - 'script-src': ["'self'"], - 'style-src': ["'self'"], + 'script-src': ["'self'"] + ([f"'sha256-{CSP_JS_HASH}'"] if CSP_JS_HASH else []), + 'style-src': ["'self'"] + + ([f"'sha256-{CSP_CSS_HASH}'"] if CSP_CSS_HASH else []) + + ([f"'sha256-{CSP_CUSTOM_CSS_HASH}'"] if CSP_CUSTOM_CSS_HASH else []), 'img-src': ["'self'", "data:"], 'font-src': ["'self'"], 'connect-src': "'self'",