Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add additional CSRF setting #477

Merged
merged 2 commits into from
Jul 25, 2023
Merged

Conversation

knabar
Copy link
Member

@knabar knabar commented Jun 1, 2023

Following #471, this PR adds another required setting to make CSRF requests work:

omero config set omero.web.csrf_trusted_origins '[".example.com"]'

Without this setting, it is not possible to perform cross-domain unsafe HTTP requests (POST, PUT, and DELETE), even if cookies etc. are configured correctly.

Reference:

@knabar knabar added this to the 5.22.0 milestone Jun 1, 2023
@knabar knabar requested a review from will-moore June 1, 2023 14:37
(
"A list of hosts which are trusted origins for unsafe requests. "
"When starting with '.', all subdomains are included. "
"""Example: '[".example.com", "another.example.net"]'"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to SECURE_PROXY_SSL_HEADER below, might be a good idea to link to the Django documentation for CSRF_TRUSTED_ORIGINS:

@will-moore
Copy link
Member

With this PR included on merge-ci I was able to get Django 4.0 working (avoided the CSRF errors I was seeing previously) by setting:

omero config append omero.web.csrf_trusted_origins '"https://merge-ci.openmicroscopy.org"'

This appears to be a requirement for Django 4.0+ to avoid CSRF errors.
Also, there is a breaking change in upgrade from 3.2 - previously the origins needed to have no schema (as in the your docstring examples) but in Django 4.0 you need to have the schema.
So the update of that setting would be a required step in upgrade from 3.2 to 4.0+.

Just a thought: would it make sense to hold off on this change until we bump Django to 4.0 (or 4.2) to avoid those upgrade issues?

https://docs.djangoproject.com/en/4.0/ref/settings/#csrf-trusted-origins

@will-moore
Copy link
Member

will-moore commented Jun 14, 2023

I don't really understand why Django 4.0 requires the setting in order for login to work (on merge-ci) but that wasn't needed for Django 3.2. The docs above don't say anything about Django 4.0 being more strict. The only change mentioned for 3.2 -> 4.0 is the addition of the schema to origins.

Although we're not the first to see this https://stackoverflow.com/questions/73338124/csrf-token-issue-when-upgrading-django-to-version-4

@sbesson
Copy link
Member

sbesson commented Jun 14, 2023

@will-moore do you have a link for the error you were receiving? Scanning quickly the docs, this might be related to the changes described in the CSRF section and bear some relationship with the configuration of the OME CI architecture and the way requests are proxied from merge-ci.openmicroscopy.org to the underlying OMERO.web application.
If correct, I would expect other deployment would be affected and we might need to work out best recommendations in terms of the headers that should be set on requests.

@will-moore
Copy link
Member

I'm just seeing the csrf_failure response

def csrf_failure(request, reason=""):
as configured at
CSRF_FAILURE_VIEW = "omeroweb.feedback.views.csrf_failure"

on login.

But yes, that CSRF section of the docs seems to match what we're seeing.

It might be nice if omero-web could automatically add it's own origin to the CSRF_TRUSTED_ORIGINS setting, so that users didn't have to do it?

@chris-allan
Copy link
Member

chris-allan commented Jun 14, 2023

At least for our systems we have no requirement to set CSRF_TRUSTED_ORIGINS with Django 4.0 in a semi-production setting. This includes scenarios there are SSL certificates.

If you are having CSRF errors you'll definitely want to look at the OMEROweb.log for the full reason. As @sbesson has implied, problems with merge-ci are likely due to Host, Origin or Referrer header mismatch which is more strict in 4.0. This suggests that actually other things in this OMERO.web deployment, including fully qualified URL generation, may not be working correctly if that's the case.

@will-moore
Copy link
Member

Ah - that reminds me that on merge-ci Django doesn't know it is running under https.
E.g. build_absolute_uri() returns http://... - e.g. https://merge-ci.openmicroscopy.org/web/api/ has "url:base": "http://merge-ci.openmicroscopy.org/web/api/v0/".
So it's probably failing because of that mismatch.
It would be good to fix that on merge-ci, as it's causing issues elsewhere (e.g. ome/omero-web-zarr#7)

@chris-allan
Copy link
Member

@will-moore
Copy link
Member

Tried looking into this some more with no luck...

I found a couple of examples of others seeing similar issues, but can't tell how to apply their fixes to merge-ci:

https://stackoverflow.com/questions/11441832/request-is-secure-always-returns-false-with-uwsgi-server
https://stackoverflow.com/questions/66176881/django-request-is-secure-always-returns-false

I added an output of the nginx conf on merge-ci, see
https://merge-ci.openmicroscopy.org/jenkins/job/OMERO-web/213/console

15:47:41 upstream omeroweb_web {
15:47:41     server web:4080 fail_timeout=0;
15:47:41 }
15:47:41 
15:47:41 server {
15:47:41     listen 80;
15:47:41     server_name $hostname;
15:47:41 
15:47:41     sendfile on;
15:47:41     client_max_body_size 0;
15:47:41 
15:47:41 
15:47:41 
15:47:41     # maintenance page serve from here
15:47:41     location @maintenance_web {
15:47:41         root /home/omero-web/workspace/OMERO-web/OMERO.web/etc/templates/error;
15:47:41         try_files $uri /maintainance.html =502;
15:47:41     }
15:47:41 
15:47:41     # weblitz django apps serve media from here
15:47:41     location /web/static {
15:47:41         alias /home/omero-web/static/web;
15:47:41     }
15:47:41 
15:47:41     location @proxy_to_app_web {
15:47:41         proxy_set_header X-Forwarded-Proto $scheme;
15:47:41         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
15:47:41         proxy_set_header Host $http_host;
15:47:41         proxy_redirect off;
15:47:41         proxy_buffering off;
15:47:41 
15:47:41         proxy_pass [http://omeroweb_web;](http://omeroweb_web%3B/)
15:47:41     }
15:47:41 
15:47:41     location /web {
15:47:41 
15:47:41         error_page 502 @maintenance_web;
15:47:41         # checks for static file, if not found proxy to app
15:47:41         try_files $uri @proxy_to_app_web;
15:47:41     }
15:47:41 
15:47:41 }

which has the line mentioned in one of those posts: proxy_set_header X-Forwarded-Proto $scheme.

@chris-allan
Copy link
Member

That's the HTTP rather than HTTPS configuration, no?

@will-moore
Copy link
Member

I don't know.
I don't see 2 different nginx confs. This is what's generated at https://merge-ci.openmicroscopy.org/jenkins/job/OMERO-web/configure
by

omero web config nginx --http "$OMERO_WEB_PORT" >$OMERO_DIST/nginx.conf.tmp

sudo cp $OMERO_DIST/nginx.conf.tmp $HOME/nginx/$NODE_NAME.conf

@chris-allan
Copy link
Member

Then you'll need to find out as it's the HTTPS request pipeline that is in question here. If TLS is being terminated further up the chain there is further work to do 12.

Footnotes

  1. https://omero.readthedocs.io/en/stable/sysadmins/config.html#omero.web.secure

  2. https://omero.readthedocs.io/en/stable/sysadmins/config.html#omero.web.secure_proxy_ssl_header

@will-moore
Copy link
Member

@jburel - do you have any idea how https is getting set-up on merge-ci?

It looks like we are already doing:

omero config set omero.web.secure_proxy_ssl_header '["HTTP_X_FORWARDED_PROTO", "https"]'

as suggested fix for this mentions at
https://stackoverflow.com/questions/66176881/django-request-is-secure-always-returns-false

But reading the warning at https://docs.djangoproject.com/en/3.2/ref/settings/#secure-proxy-ssl-header I don't know if we're satisfying all these conditions on merge-ci.
Does NGINX do all that for us?

@jburel
Copy link
Member

jburel commented Jun 29, 2023

@will-moore
Copy link
Member

@jburel - Thanks for that. I'm not sure exactly what it's doing! Been reading https://realpython.com/django-nginx-gunicorn/ but management_tools and ansible is outside of the scope of that...

It seems like this line is relevant:

nginx_proxy_forward_scheme_header: X-Forwarded-Proto-Web-Proxy

The nginx config generated by omero-web contains:

proxy_set_header X-Forwarded-Proto $scheme;

and this is not configurable since it's in the template:

proxy_set_header X-Forwarded-Proto $scheme;

The setting passed to Django in merge-ci is currently:

omero config set omero.web.secure_proxy_ssl_header '["HTTP_X_FORWARDED_PROTO", "https"]'

I'm not sure if all 3 need to be the same, or if the ansible setting overrides the one in the nginx config generated by omero-web?

Copy link
Member

@will-moore will-moore left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is working as expected.
I don't think this PR needs to be held up by the ongoing discussion on merge-ci http vv https since that is not closely related to this setting.

@knabar knabar merged commit d207e0a into ome:master Jul 25, 2023
8 checks passed
@knabar knabar deleted the feature-csrf-trusted-origin branch July 25, 2023 07:29
@imagesc-bot
Copy link

This pull request has been mentioned on Image.sc Forum. There might be relevant details there:

https://forum.image.sc/t/release-of-omero-server-5-6-8-and-omero-web-5-22-0/84157/1

@imagesc-bot
Copy link

This pull request has been mentioned on Image.sc Forum. There might be relevant details there:

https://forum.image.sc/t/docker-image-of-omero-web-5-23-0-still-with-v5-22-1/88699/13

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants