martin
martin copied to clipboard
Enabling CORS via Martin
Hi,
I'm trying to prevent access to resources on a website (from any other not supposed to) by using CORS on Nginx. I did setup a reverse proxy to direct tiles requests to Martin (localhost:3000). On Nginx I tried : add_header "Access-Control-Allow-Origin" "https://www.myWebsite.com";
Looking at the response header I don't see that. So I went and edited Martin to enable it there by modifying "server.rs": line 16:
use actix_web::{
http, middleware, route, web, App, HttpMessage, HttpRequest, HttpResponse, HttpServer, Responder,
Result,
};
line 422:
let server = HttpServer::new(move || {
let cors_middleware = Cors::default()
.allowed_origin("https://www.myWebsite.com")
.allowed_origin_fn(|origin, _req_head| {
origin.as_bytes().ends_with(b".myWebsite.com")
})
.allowed_methods(vec!["GET"])
.allowed_headers(vec![http::header::AUTHORIZATION, http::header::ACCEPT])
.allowed_header(http::header::CONTENT_TYPE)
.max_age(3600);
I rebuilt Martin and started it. Then I looked at the response header and I'm not seeing the allow origin there still: HTTP/1.1 200 OK Server: nginx/1.18.0 (Ubuntu) Date: Tue, 10 Oct 2023 10:49:33 GMT Content-Type: image/jpeg Content-Length: 19397 Connection: keep-alive vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers X-Cache-Status: MISS
My ngnix config for the reverse proxy is:
proxy_set_header X-Rewrite-URL $uri;
proxy_set_header X-Forwarded-Host $host:$server_port;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
proxy_connect_timeout 5m;
proxy_send_timeout 5m;
proxy_read_timeout 5m;
send_timeout 5m;
proxy_cache backend_cache;
proxy_cache_lock on;
proxy_cache_revalidate on;
proxy_cache_valid 200 204 302 1d;
proxy_cache_valid 404 1m;
proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
add_header X-Cache-Status $upstream_cache_status;
proxy_pass http://127.0.0.1:3000/;
I must be doing some thing wrong. Thanks for any light you can shed on this.
For more debug insight, can you curl directly the martin server to see from which server the missing header is coming from.
Also on the martin code, Is the allowed_origin_fn
method is supposed to be ran after allowed_origin
? I think it's probably either allowed_origin
or allowed_origin_fn
Thanks @lefuturiste. If i curl the website with one tile request (nginx) or directly the Martin server, I get the same response:
Inside the Martin Server box: curl -v "http://127.0.0.1:3000/../../15634/13390"
- Trying 127.0.0.1:3000... ... < HTTP/1.1 200 OK < content-length: 22757 < content-type: image/jpeg < vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers < date: Tue, 10 Oct 2023 15:12:19 GMT <
From outside the Martin server box: curl -v "https://www.MyWebSite.com/../../15634/13390"
< HTTP/1.1 200 OK < Server: nginx/1.18.0 (Ubuntu) < Date: Tue, 10 Oct 2023 15:09:54 GMT < Content-Type: image/jpeg < Content-Length: 22757 < Connection: keep-alive < vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers < X-Cache-Status: HIT
This seems to mean that the response I get is coming from Martin server ?
Just FYI - the only CORs related code is here - enabling actix_cors middleware: https://github.com/maplibre/martin/blob/8b34cd374c707548f9e1dccd9385aad0e804f62c/martin/src/srv/server.rs#L424-L434
Thanks @nyurik. I think that is the code section I edited (must be different commits between what is currently in github and last time I pulled the code: few days ago).
Note that this code hasn't changed in a while, so probably still the same
I pulled the latest from github and its same lines u pointed out @nyurik (lines starting at 422). I edited my original post to reflect that line number.
@lefuturiste I removed allowed_origin_fn
and got the same result as before.
So how can we act on this? Should Martin CORS handling be changed in any way? How is it different from the other similar ones like pg_tiles or geoserver?
Ideally this should be configurable through the .yaml to avoid editing and rebuilding. GeoServer appears to use "web.xml" to configures CORS.
Do you see it as a bool, or a more advanced setting? What config is actually needed?
A string should do it. A default value would be: access-control-allow-origin: *
. Eventualy one can set their access control to a specific domain. Example: access-control-allow-origin: https://www.example.com
The Actix Cors support is fairly involved, and has many configuration params. We may actually need to expose more than just origin wildcard. I started a https://github.com/actix/actix-extras/issues/359 to document various common params users may need, and we should pick which of these should be configurable by Martin users, and how to translate them into the Cors middleware configuration.
If i curl the website with one tile request (nginx) or directly the Martin server, I get the same response:
Inside the Martin Server box: curl -v "http://127.0.0.1:3000/../../15634/13390"
@nouryf This is expected behavior for this invocation of cURL. To trigger CORS handling, you need to add an Origin
header to the request; browsers do this automatically.
$ curl -v "http://127.0.0.1:3000/../../15634/13390" --header "Origin: http://127.0.0.1"