From 418219c90114bd7475db0d0aaba6f9e214c8fbad Mon Sep 17 00:00:00 2001 From: Andrew Boni Signori <61259237+andrewsignori-aot@users.noreply.github.com> Date: Mon, 19 Aug 2024 12:39:30 -0700 Subject: [PATCH] #3610 - Missing Content-security-policy (#3644) - Create a different file to be consumed by `Docker` and `Docker.dev` for nginx deployment. - Moved the `add_header` instructions from "nginx.conf" to "default.conf.dev.template". Both files had the `server` defined and the headers were never added. - The only difference between "default.conf.template" and "default.conf.dev.template" is the `http://localhost:*` defined for the `connect-src`. - The only change from previous configurations was about `Content-Security-Policy` and they are the below. ``` default-src 'self'; connect-src 'self' *.gov.bc.ca; script-src 'self' 'unsafe-eval' https://cdn.form.io/flatpickr/flatpickr.min.js; style-src 'self' 'unsafe-inline' https://stackpath.bootstrapcdn.com/bootstrap/ https://cdn.form.io/flatpickr/flatpickr.min.css; font-src 'self' data:; img-src 'self' data:" ``` - Comments about the above configurations - The list was created to test the web portal. - Some are required because form.io loads external libs like `flatpickr.min.js` on demand. - `*.gov.bc.ca` was added to allow Keycloak access and logout URL for Institutions. ### Minor outside PR scope changes - Moved nginx files to a nginx folder. - Changed the `web-local` make to build to make it easier to test changes on the web app. ### Localhost sample with headers ![image](https://github.com/user-attachments/assets/1154a722-c31a-4b61-9be6-88c0d46cf942) --- sources/Makefile | 2 +- sources/packages/web/Dockerfile | 4 +-- sources/packages/web/Dockerfile.dev | 4 +-- sources/packages/web/default.conf.template | 21 --------------- sources/packages/web/nginx.conf | 23 ---------------- .../web/nginx/default.conf.dev.template | 26 +++++++++++++++++++ .../packages/web/nginx/default.conf.template | 26 +++++++++++++++++++ sources/packages/web/nginx/nginx.conf | 15 +++++++++++ 8 files changed, 72 insertions(+), 49 deletions(-) delete mode 100644 sources/packages/web/default.conf.template delete mode 100644 sources/packages/web/nginx.conf create mode 100644 sources/packages/web/nginx/default.conf.dev.template create mode 100644 sources/packages/web/nginx/default.conf.template create mode 100644 sources/packages/web/nginx/nginx.conf diff --git a/sources/Makefile b/sources/Makefile index 76574e27dc..82065e5ea3 100644 --- a/sources/Makefile +++ b/sources/Makefile @@ -180,7 +180,7 @@ api: ## :: Executes into the workspace container. # Local Web (nginx) web-local: @echo "+\n++ Make: Run local web (nginx).\n+" - @docker compose -f docker-compose.yml up web + @docker compose -f docker-compose.yml up --build -d web local-db: @echo "Make: Shelling into database workspace ..." diff --git a/sources/packages/web/Dockerfile b/sources/packages/web/Dockerfile index 8a57ddd13e..4dc0ee3fd5 100644 --- a/sources/packages/web/Dockerfile +++ b/sources/packages/web/Dockerfile @@ -8,7 +8,7 @@ RUN npm ci COPY . ./ # Replace ${PORT} variable in the template and save as default.conf. -RUN sed 's/${PORT}/'"${PORT}"'/g' default.conf.template > default.conf +RUN sed 's/${PORT}/'"${PORT}"'/g' nginx/default.conf.template > default.conf RUN npm run build @@ -25,7 +25,7 @@ COPY --from=builder /opt/app-root/src/dist . COPY --from=builder /opt/app-root/src/default.conf /etc/nginx/conf.d # Copying the main configuration file. -COPY nginx.conf /etc/nginx/nginx.conf +COPY nginx/nginx.conf /etc/nginx/nginx.conf # Daemon off makes nginx to run on the foreground with only one process. # Docker will kill the container if the process dies. diff --git a/sources/packages/web/Dockerfile.dev b/sources/packages/web/Dockerfile.dev index 1b460cbc10..2eb0d53994 100644 --- a/sources/packages/web/Dockerfile.dev +++ b/sources/packages/web/Dockerfile.dev @@ -32,12 +32,12 @@ RUN mkdir /etc/nginx/templates COPY --from=builder /app/dist /opt/app-root/src # Copying the main configuration file. -COPY nginx.conf /etc/nginx/nginx.conf +COPY nginx/nginx.conf /etc/nginx/nginx.conf # Copying the configuration template file to templates dir. # It will be processed to transform the vars in the template files into # evaluated values and save the resulting files into /etc/nginx/conf.d/ dir. -COPY default.conf.template /etc/nginx/templates/ +COPY nginx/default.conf.dev.template /etc/nginx/templates/default.conf.template # Changing ownwership of some nginx directories as it will run as nginx user. RUN chown nginx /var/cache/nginx/ -R diff --git a/sources/packages/web/default.conf.template b/sources/packages/web/default.conf.template deleted file mode 100644 index a70e325e54..0000000000 --- a/sources/packages/web/default.conf.template +++ /dev/null @@ -1,21 +0,0 @@ -# nginx default configuration. - -log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - -server { - # Log to stdout - set $loggable 1; - if ($http_user_agent ~* "^kube-probe/") { - set $loggable 0; - } - access_log /dev/stdout main if=$loggable; - - listen ${PORT}; - location / { - root /opt/app-root/src; - index index.html; - try_files $uri $uri/ /index.html; - } -} \ No newline at end of file diff --git a/sources/packages/web/nginx.conf b/sources/packages/web/nginx.conf deleted file mode 100644 index 3ecf0e2745..0000000000 --- a/sources/packages/web/nginx.conf +++ /dev/null @@ -1,23 +0,0 @@ -worker_processes auto; - -# Log to stdout -error_log /dev/stdout info; - -pid /tmp/nginx.pid; -events { - worker_connections 1024; -} -http { - include /etc/nginx/mime.types; - include /etc/nginx/conf.d/default.conf; - default_type application/octet-stream; - sendfile on; - keepalive_timeout 65; - server { - add_header 'X-Content-Type-Options' "nosniff"; - add_header 'Content-Security-Policy' "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'"; - add_header 'Strict-Transport-Security' "max-age=31536000; includeSubDomains; preload"; - add_header 'Referrer-Policy' "same-origin"; - add_header 'X-Frame-Options' "sameorigin"; - } -} \ No newline at end of file diff --git a/sources/packages/web/nginx/default.conf.dev.template b/sources/packages/web/nginx/default.conf.dev.template new file mode 100644 index 0000000000..09654bc254 --- /dev/null +++ b/sources/packages/web/nginx/default.conf.dev.template @@ -0,0 +1,26 @@ +# nginx default configuration. + +log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + +server { + # Log to stdout + set $loggable 1; + if ($http_user_agent ~* "^kube-probe/") { + set $loggable 0; + } + access_log /dev/stdout main if=$loggable; + + listen ${PORT}; + location / { + root /opt/app-root/src; + index index.html; + try_files $uri $uri/ /index.html; + } + add_header 'X-Content-Type-Options' "nosniff"; + add_header 'Content-Security-Policy' "default-src 'self'; connect-src 'self' *.gov.bc.ca http://localhost:*; script-src 'self' 'unsafe-eval' https://cdn.form.io/flatpickr/flatpickr.min.js; style-src 'self' 'unsafe-inline' https://stackpath.bootstrapcdn.com/bootstrap/ https://cdn.form.io/flatpickr/flatpickr.min.css; font-src 'self' data:; img-src 'self' data:"; + add_header 'Strict-Transport-Security' "max-age=31536000; includeSubDomains; preload"; + add_header 'Referrer-Policy' "same-origin"; + add_header 'X-Frame-Options' "sameorigin"; +} \ No newline at end of file diff --git a/sources/packages/web/nginx/default.conf.template b/sources/packages/web/nginx/default.conf.template new file mode 100644 index 0000000000..9aab0d7d28 --- /dev/null +++ b/sources/packages/web/nginx/default.conf.template @@ -0,0 +1,26 @@ +# nginx default configuration. + +log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + +server { + # Log to stdout + set $loggable 1; + if ($http_user_agent ~* "^kube-probe/") { + set $loggable 0; + } + access_log /dev/stdout main if=$loggable; + + listen ${PORT}; + location / { + root /opt/app-root/src; + index index.html; + try_files $uri $uri/ /index.html; + } + add_header 'X-Content-Type-Options' "nosniff"; + add_header 'Content-Security-Policy' "default-src 'self'; connect-src 'self' *.gov.bc.ca; script-src 'self' 'unsafe-eval' https://cdn.form.io/flatpickr/flatpickr.min.js; style-src 'self' 'unsafe-inline' https://stackpath.bootstrapcdn.com/bootstrap/ https://cdn.form.io/flatpickr/flatpickr.min.css; font-src 'self' data:; img-src 'self' data:"; + add_header 'Strict-Transport-Security' "max-age=31536000; includeSubDomains; preload"; + add_header 'Referrer-Policy' "same-origin"; + add_header 'X-Frame-Options' "sameorigin"; +} \ No newline at end of file diff --git a/sources/packages/web/nginx/nginx.conf b/sources/packages/web/nginx/nginx.conf new file mode 100644 index 0000000000..4dfab3dce6 --- /dev/null +++ b/sources/packages/web/nginx/nginx.conf @@ -0,0 +1,15 @@ +worker_processes auto; + +# Log to stdout +error_log /dev/stdout info; +pid /tmp/nginx.pid; +events { + worker_connections 1024; +} +http { + include /etc/nginx/mime.types; + include /etc/nginx/conf.d/default.conf; + default_type application/octet-stream; + sendfile on; + keepalive_timeout 65; +} \ No newline at end of file