Mapstore, geonetwork et CORS

44 views
Skip to first unread message

Landry Breuil

unread,
Feb 15, 2022, 4:18:15 AM2/15/22
to georchestra-dev
Hello,

CORS, c'est compliqué. Tout le monde s'est déja fait insulter par la
console du browser avec des messages comme 'Cross-Origin Request
Blocked: The Same Origin Policy disallows reading the remote resource at
https://geobretagne.fr/geonetwork/srv/fre/csw?service=CSW&version=2.0.2&request=.
(Reason: CORS header ‘Access-Control-Allow-Origin’ missing).'

Vu que j'y ai passé un peu de temps et que je pense avoir compris des
trucs, autant les documenter/partager ici.

le but est relativement simple: charger dans mapstore des couches depuis
un catalogue CSW (ou un geoserver) 'distant' (ie n'étant pas sur le même
domaine que mapstore). Si CORS est fonctionnel, la requête va partir
directement du navigateur vers le service distant, sinon elle passe par
le proxy interne de mapstore. Pour diverses raisons on peut préférer
l'un ou l'autre des 2 modes.

pour que CORS soit fonctionnel avec CSW il y'a plusieurs tests faits par
le navigateur:
- un GET est fait sur le csw lors de l'ajout du catalogue - il semble
que le serveur doit renvoyer a minimal le header
'Access-Control-Allow-Origin' sinon il ne sera pas ajouté/disponible
directement, on passera par le proxy.

- une requête 'pre-flight' OPTIONS est envoyée au serveur distant avec
le header 'Origin: https://mon.domaine.client' (ainsi que
Access-Control-Request-Method/Access-Control-Request-Header), a laquelle
le serveur doit répondre 200 avec des headers
Access-Control-Allow-Origin/Access-Control-Allow-Headers/Access-Control-Allow-Method,
sinon -> proxy

- si cette requête 'pre-flight' est ok, alors le client va directement
causer au serveur distant avec des GET/POST, toujours en envoyant ces
mêmes headers - sinon il passe par le proxy.

On peut rejouer ces tests avec curl, mais il ne faut pas oublier de
mettre les bons headers pour avoir le même comportement qu'un navigateur.

il y'a plusieurs paramètres à prendre en compte:

- côté config mapstore, on déclare la liste des domaines avec lesquels
on *sait* que CORS est fonctionnel. cf UseCORS dans
https://mapstore.readthedocs.io/en/latest/developer-guide/local-config/

- lister un domaine la dedans ne va pas magiquement faire tomber CORS en
marche. On ne le liste en prod que quand on sait que le serveur distant
est correctement configuré et qu'on l'a testé ...

- coté serveur distant, il faut se coordonner avec le responsable du
serveur distant.... dans le cas de GN 3.8, un commit a désactivé la
fonctionalité CORS (cf
https://github.com/georchestra/geonetwork/commit/7573ab69bd3e72ee04f7deee92bb0f77b7861884)
- dans GN4, par défaut on retrouve '*' - c'est ce qui gouverne l'envoi
de 'Access-Control-Allow-Origin'

- de mon expérience, remettre '*' dans la config
geonetwork/WEB-INF/web.xml me donne un CORS presque fonctionnel, sauf
pour la requête OPTIONS que 'quelque chose' dans tomcat ou le
security-proxy ne sait/veut pas gérer et renvoie un 403 quand il voit un
header Access-Control-Request-Method - quelque chose a corriger ?

- pour contourner ce problème, j'ai rajouté 5 lignes de config dans mon
nginx en amont de tomcat/security-proxy:


location ~ ^/geocat/srv/.*/csw {
if ( $request_method = OPTIONS ) {
add_header "Access-Control-Allow-Origin" "*";
add_header "Access-Control-Allow-Method" "POST, GET,
OPTIONS";
add_header "Access-Control-Allow-Headers" "Origin,
X-Requested-With, Content-Type, Accept";
return 204;
}
proxy_pass http://proxycas_backend;
}

une config 'presque équivalente' pour apache/geoserver est déjà
documentée ici:
https://github.com/georchestra/georchestra/blame/master/docs/setup/apache.md#L222

avec ça coté geonetwork/serveur web, + lister le domaine du geonetwork
dans UseCORS de la config mapstore, j'arrive à avoir du CORS fonctionnel
pour les requêtes CSW. Pour ce qui est de requêtes WMS/WFS/WMTS, le
principe est plus ou moins le même, la console réseau du navigateur aide
beaucoup à débugguer. Après, en fonction des infras, on choisit de faire
gérer CORS par les applis (geonetwork/geoserver) ou par le middleware
(nginx/apache/autre), mais dans tous les cas le gros du travail est a
faire coté serveur distant, et demande une bonne communication/coordination.

Bref, CORS c'est l'enfer. Et je ne vous parle pas de CORS + HTTP Auth ou
on ne peut pas faire '*', c'est interdit.

--
Landry Breuil
Responsable Informatique

----------------------------------------------------------------------------
Centre Régional Auvergne-Rhône-Alpes de l'Information Géographique
Hôtel de Région de Clermont-Ferrand
59 boulevard Léon Jouhaux - CS 90 706
63050 Clermont-Ferrand
04 44 05 12 42

https://www.craig.fr - @GipCraig
----------------------------------------------------------------------------
Le support est accessible tous les jours ouvrés de 8:30 à 12:30 au 09 72
62 25 31

Jean Pommier

unread,
Feb 15, 2022, 4:56:11 AM2/15/22
to georche...@googlegroups.com

Merci Landry pour ce tuto CORS.

Comme tu dis, c'est souvent l'enfer ce truc. Surtout quand des entêtes CORS sont stockés en cache, pendant qu'on met en place la config.

Je me permets une petite clarification par rapport à la fin de tes explications : faites attention, il ne doit pas y avoir à la fois une config CORS active dans l'appli (GN) et dans le middleware (nginx). Si vous choisissez de l'activer dans le middleware, il faut le désactiver dans l'appli. Les CORS ne doivent être définis qu'en un point du parcours, sinon on a aussi une erreur.

Jean

Reply all
Reply to author
Forward
0 new messages