Closed maeve-fpf closed 4 years ago
Should be partially addressed by https://github.com/freedomofpress/securethenews/pull/246.
It seems like Strict-Transport-Security:
is not being set in production. For reference, we turned it on with: https://docs.djangoproject.com/en/3.0/ref/settings/#secure-hsts-seconds . Note that that says "sets the HTTP Strict Transport Security header on all responses that do not already have it." (emphasis mine).
To debug, I added SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
and did a request faking that header to the app running in both development and production. In dev, I get:
< HTTP/1.1 200 OK
< Date: Thu, 16 Jul 2020 20:37:10 GMT
< Server: WSGIServer/0.2 CPython/3.6.8
< Content-Type: text/html; charset=utf-8
< Strict-Transport-Security: max-age=63072000; preload
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< X-Frame-Options: SAMEORIGIN
< Content-Length: 6095
< Vary: Cookie, Origin
and prod (i.e. against local docker-compose with env set to production
):
< HTTP/1.1 200 OK
< Server: gunicorn/19.7.1
< Date: Thu, 16 Jul 2020 20:38:00 GMT
< Connection: close
< Vary: Cookie, Origin
< Content-Type: text/html; charset=utf-8
< Content-Length: 6134
< X-XSS-Protection: 1; mode=block
< X-Content-Type-Options: nosniff
< X-Frame-Options: SAMEORIGIN
I'm stumped, as I don't see anything in the STN code or any libraries that would remove the header. Any ideas?
Hmmm, that is confusing. @chigby do you have any ideas here?
Could this have something to do with it?
from https://docs.djangoproject.com/en/2.2/ref/middleware/#http-strict-transport-security
Edit: I see now that you already tried with this header, so nevermind this suggestion.
@chigby we probably do need to set this setting on production! However, I think that ingress-nginx is sending it. In my local test, if I enable the setting and do send the header, the response only has Strict-Transport-Security:
if the env is development
, and not for production
.
@maeve-fpf So, I tried this locally and I was able to get the header to appear using these steps:
securethenews/settings/base.py
to contain the line SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
. I had to do this before running the other commands, otherwise I think it will not be included in the local-prod environment.make build-prod-container
make run-prod-env
After that, here's what I get:
$ curl -I http://localhost:8000 --header "X-Forwarded-Proto: https"
HTTP/1.1 200 OK
Server: gunicorn/19.7.1
Date: Mon, 20 Jul 2020 20:50:43 GMT
Connection: close
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=3; preload
Content-Length: 44991
Vary: Cookie, Origin
X-XSS-Protection: 1; mode=block
Content-Type: text/html; charset=utf-8
X-Frame-Options: SAMEORIGIN
(also ignore the max-age=3
there, that was just something I changed it to make sure it was really using the right settings file)
I am not all that familiar with starting a local docker-compose setup with the production environment enabled, so it's possible what I did here differs from what you did and/or that these make commands are not reflective of how the production environment works.
One thing that also slightly confused me for a minute was that with this setup was that the site did not "auto-update" if I changed the code or the settings files. It's possible there's a simpler way, but with by making the change first, it seemed to at least run with the code I had saved before before I ran any docker-compose commands.
Aha! You're right, my build was out of date. OK, PR coming up.
Now that we're on GKE, we are missing/have changed some headers and access control that used to be handled by nginx. They are:
Strict-Transport-Security: max-age=63072000; includeSubdomains; preload
(we are sending a value for this from GKE, but it'smax-age=15724800; includeSubDomains
. I think it's totally fine to change the max-age we look for in the tests butpreload
should probably be there)X-Content-Type-Options: nosniff
(missing)X-Frame-Options: SAMEORIGIN
(for some reason this is being sent asSAMEORIGIN, SAMEORIGIN
which i assume would have the same effect but the test is a string match)X-XSS-Protection: 1; mode=block
(missing)Referrer-Policy: same-origin
(missing)and returning a 403 on
/django-admin/
(as a stopgap, I have blocked this route with GitHub auth)Once the app handles these, tests in fpf-www-projects should pass without any changes over there.