Akeneo 6.0.33 Community Edition Events API: "The url is not allowed" (route Laravel)

Le problème exposé dans ce sujet a été résolu.

Salut,

Vous connaissez peut-être Akeneo, c’est un PIM que j’ai eu l’occasion d’utiliser massivement dans ma dernière boîte et qui gagne en popularité. Il en existe une version gratuite qui s’appelle "Community Edition". Je rappelle au passage qu’un PIM permet aux commerçants de gérer leurs catalogues de produits, sans pouvoir gérer de données amenées à fréquemment changer comme les stocks, les prix, etc.

J’ai besoin de connecter Akeneo à une application Laravel : à la création/suppression d’un produit Akeneo, ce dernier doit en notifier par message Laravel. J’ai donc lu la doc suivante, qui porte sur la souscription aux événements (en particulier : https://help.akeneo.com/pim/serenity/articles/manage-event-subscription.html mais aussi https://api.akeneo.com/events-documentation/subscription.html).

Ainsi, dans Akeneo j’ai créé une connexion de type "Destination", de test, puis j’ai activé "Events subscription" (bouton-switch cliqué !). Ensuite je dois taper l’URL Laravel destinée à recevoir les données de créaton/suppression de produits qui seront envoyées par Akeneo dans le champ Akeneo prévu à cet effet. Ensuite je clique sur le bouton "TEST" / "SAVE" et normalement Akeneo est censé accepter l’URL que j’ai tapée et afficher les credentials du genre le secret.

Sauf que quand je fais ça, j’ai le message d’erreur suivant (et aucun credential ne s’affiche bien sûr) : "The url is not allowed". Notez bien que ce n’est pas "The HTTP method is not allowed", non.

Les URL Laravel que j’ai testées engendrent toutes ce même comportement d’Akeneo, elles sont associées à la route Laravel receive_akeneo_events, qui est de type POST. Les voici :

Je précise bien sûr que je lance les containers Docker d’Akeneo et ceux de Laravel en parallèle donc la route est appelable/utilisable/atteignable par Akeneo !

Et en effet Laravel est lancé dans son propre ensemble de containers Docker, Akeneo dans son propre ensemble de containers Dockers également. Laravel et Akeneo sont donc présents sur deux réseaux Docker différents, distincts. Je ne sais pas si mon problème vient de là ?…

Question

Du coup voilà, j’avoue que je sèche beaucoup, je ne trouve aucune information sur Stackoverflow ni sur le GitHub d’Akeneo Community Edition, j’ai posté des "topics" si l’on peut dire là-bas mais ça n’avance pas non plus…

De plus, aucune documentation d’Akeneo ne parle de ce souci… Qui pourtant est de taille, puisqu’il s’agit d’être en mesure d’utiliser Akeneo en local, à des fins de tests et de dev ! >_< >_< >_<

Si quelqu’un a une bonne connaissance d’Akeneo voire éventuellement, dans l’idéal, a lui-même/elle-même rencontré ce problème, lui serait-il possible de m’aider s’il vous plaît ?

Voilà voilà, merci à tous pour votre aide !

Belle journée tout le monde :ange: ,

Dans ce genre de cas, le plus simple est souvent de coller un point d’arrêter d’exception (si le langage de permet) et/ou de fouiller dans le code pour comprendre ce qui se passe.

Ça sera sans doute plus rapide que d’espérer qu’un hypothétique expert passe par ici avec une solution toute prête.

Et en effet Laravel est lancé dans son propre ensemble de containers Docker, Akeneo dans son propre ensemble de containers Dockers également. Laravel et Akeneo sont donc présents sur deux réseaux Docker différents, distincts. Je ne sais pas si mon problème vient de là ?…

Euh … Ben oui le problème vient de là. J’ai jamais codé en PHP et je fais pas de Web je n’utilise que très peu Docker mais ça me semble être très probable que le problème vienne de là.

http://127.0.0.1:80/receive_akeneo_events

Ça l’est l’IP de ta machine. Si Lavarel et Akeneo ne sont pas sur la même machine (dans le même conteneur si tu préfères) alors ça n’a aucune chance de marcher. 127.0.0.1 ayant un sens différent pour chacune des machines, comme tout le bloc 127/8 d’ailleurs, elle désigne sa propre machine.

http://0.0.0.0:80/receive_akeneo_events

0.0.0.0 n’est jamais une addresse IP valide. Elle a un sens particulier quand on écoute sur cette adresse et également une utilité en DHCP mais sinon, c’est une adresse tout à fait invalide. (Comme tout le block 0/8 d’ailleurs, la première IP routable est 1.0.0.0).

http://laravel.test:80/receive_akeneo_events (j’ai bien mis à jour correctement mon /etc/hosts)

Qu’entends tu par correctement ?

Pour communiquer il faut que les deux containers soient sur le même réseau déjà. Ensuite il faut mettre l’IP de l’autre machine. Tu sais le faire ? Je sais vraiment utiliser Docker. Bref, joue avec la config Docker et les adresse, c’est là la solution.

+2 -0

Merci pour votre retour, effectivement je vais aller voir le code je pense.

La piste des containers dockers sur des réseaux différents, je l’ai émise sans trop y croire car… Le message est "URL not allowed", pas un message d’erreur type réseau du genre Laravel ne répond pas.

Mais effectivement c’est peut-être juste ça, je vais explorer cette piste dès demain matin.

Je note que plusieurs containers Akeneo et plusieurs containers Laravel sont lancés (respectivement sur le réseau docker d’Akeneo et le réseau docker de Laravel). Du coup je vais devoir tous les mettre sur un seul et même réseau Docker.

Oui je sais le faire. Par contre j’espère ne pas créer de bugs dans Akeneo ou Laravel du coup !

Je me demande par ailleurs si je peux faire cette modification sans changer leur fichier de configuration Docker, lequel sera amené à être écrasé si jamais une mise à jour d’au moins un de ces deux programmes Akeneo et Laravel avait lieu.

Je me demande par ailleurs si je peux faire cette modification sans changer leur fichier de configuration Docker, lequel sera amené à être écrasé si jamais une mise à jour d’au moins un de ces deux programmes Akeneo et Laravel avait lieu.

Herbe

Oui tu peux.

+1 -0

Je reviens vers vous !

J’ai donc créé mon réseau Docker avec docker network create my_test, puis j’ai listé l’ensemble des containers en cours d’exécution (Laravel + Docker) avec docker container ps, et a la mano j’ai utilisé sur l’ID de chacun d’eux la commande : docker network connect my_test <ID du container>, enfin j’ai vérifié avec docker inspect my_test que ce réseau a bien été rempli, ce qui semble être le cas (et j’ai également récupéré l’adresse IP du serveur Laravel de ce réseau my_test : http://172.21.0.2 - j’ai vérifié et le GET retourne bien ce qu’il faut donc c’est la bonne IP).

Dans Akeneo j’ai mis : http://172.21.0.2/receive_akeneo_events, mais toujours :

The url is not allowed

:pirate:

Je vais donc voir le code d’Akeneo et peut-être lancer un "bounty" très alléchant sur Stackoverflow en parallèle (à voir).

Suite à des grep, je vois :

akeneo/pim/node_modules/pim-community-dev/src/Akeneo/Connectivity/Connection/back/Application/Webhook/Validation/ExternalUrlValidator.php

(nb : ce fichier existe aussi sous le répertoire akeneo/pim/vendor/[... etc. ...] au lieu de akeneo/pim/node_modules/[... etc. ...])

 private const DOMAIN_BLACKLIST = [
        'localhost',
        'elasticsearch',
        'memcached',
        'object-storage',
        'mysql',
    ];

Pourquoi exclure localhost … Comment je fais moi si j’ai envie de faire tout ça en local pour développer mon projet et tester… pfff

PS : de plus ils excluent même les IP privées, d’où le fait que l’IP 172.machin que je vous ai montrée est elle aussi refusée, cf. leur fonction function isInPrivateRange(string $ip): bool et surtout l’appel qui en est fait (même fichier que précédemment).

Je ne comprends pas leurs motivations ! Il y a peut-être de bonnes raisons à cela que je n’ai pas encore identifiées mais pour le moment tout ça me paraît abusif de leur part, j’espère que ce n’est pas une question d’argent derrière…

+0 -0

Si tu as accès au code source. Tu peux pas juste virer le blacklistage des IP privés ?

+1 -0

Si tu as accès au code source. Tu peux pas juste virer le blacklistage des IP privés ?

ache

Oui tout à fait j’y ai accès.

Oui je peux le faire mais j’aimerais surcharger soit le validateur (Symfony visiblement), soit le fichier qui fait appel à lui (ou qui interagit avec lui). En tout cas je n’ai pas de connaissance en Symfony…

C’est trivial de rajouter un nom de domaine à usage interne dans Docker, non ? Ça devrait résoudre ton problème sans casser le code.

SpaceFox

Je me trompe peut-être mais j’ai déjà essayé de mettre un nom de domaine sur mon IP privée Docker dans le fichiers hosts de mon Ubuntu, et Akeneo arrive quand même à deviner que c’est une IP privée (enfin je pense. En tout cas il affiche tjrs le même message d’erreur)

Si je souhaitais bloquer les IP privées. Je l’aurais fais après l’étape de résolution d’adresse.

+1 -0

Mais je ne comprends pas ce que tu utilises comme adresse @Herbe. Ton réseau Docker génère des adresses en 127.20.x.y ou 127.21.x.y en général ; c’est celles-là que tu dois utiliser pour faire parler tes containers entre eux – d’ailleurs tu dis plus haut que tu utilises http://172.21.0.2. Qu’est-ce que les adresses ou domaines locaux viennent faire là-dedans ?

Je ne connais pas docker mais d’après cet article :

https://en.wikipedia.org/wiki/Private_network

Il me semble que 172.21.0.2 est bien une adresse privée.

127.20.x.y ça me semble surtout pas échangeable sur un réseau ça normalement. Je peux me planter hein mais il me semble que ça ne devrait pas marcher. Où alors Docker fait un truc que je ne comprend pas (ce qui ne m’étonnerait pas).

+1 -0

Une fois que j’ai créé mon réseau my_test décrit au-dessus, et une fois que j’y ai placé mes containers, ceux-ci se sont vus attribuer une adresse IPv4 privée (172.21.x.z/16). C’est pourquoi, pour vous répondre @SpaceFox et @ache, je n’ai plus recourt à l’adresse locale 127.0.0.1 ni aux autres adresses débutant par 127..


Je vais finalement essayer de virer la blacklist des IP locales ET privées du code d’Akeneo tout simplement, puis relancer le make et très probablement refaire des docker nerwork connect sur chacun des containers Akeneo (très enquiquinant ça, y en a 6 ou 7, ça me prend trop de temps je trouve). Puis, réessayer, voir si j’ai réussi à faire sauter cette "protection"…

J’espère juste qu’Akeneo ne se mettra pas à jour tout seul, sinon adieu cette modif (je ne sais pas overrider en Symfony et j’ai pas envie d’apprendre Symfony là tout de suite).

+0 -0

Je vais passer le sujet en résolu, car dans le fichier akeneo/pim/node_modules/pim-community-dev/src/Akeneo/Connectivity/Connection/back/Application/Webhook/Validation/ExternalUrlValidator.php :

  1. J’ai commenté l’entrée localhost de l’array DOMAIN_BLACKLIST

  2. J’ai commenté l’appel à isInPrivateRange

  3. J’ai remarqué que ce changement a aussi eu lieu dans le fichier de même nom situé sous le répertoire vendor au lieu de node_modules, tant mieux

  4. J’ai fait un make down puis un make dev comme indiqués dans la documentation d’Akeneo avec Docker (https://docs.akeneo.com/6.0/install_pim/docker/installation_docker.html)

  5. Dans Laravel j’ai laissé la route (que doit appelée Akeneo, bien sûr, pour rappel) dans le middleware web et j’ai ajouté une partie de son URL (la chaîne : akeneo_receive_events) dans le tableau $except du middleware VerifyCsrfToken, comme indiqué dans la doc Laravel : https://laravel.com/docs/9.x/csrf#csrf-excluding-uris . En effet, Akeneo ne parvenait pas à appeler l’URL car il n’envoyait pas le token CSRF exigé par Laravel pour comparaion & vérification de sécurité.

Akeneo étant du Symfony visiblement, le seul truc qui m’embête c’est que : je n’ai pas les connaissances suffisantes en Symfony pour faire en sorte que les 2 modifs que j’ai faites dans les puces 1. et 2. soient indépendantes des mises à jour d’Akeneo.

Mais bon tant pis, un jour peut-être j’aurais le courage de lire la doc de 10000000km de long de Symfony :B Pour l’instant je préfère Laravel (qui me semble-t-il est aussi du Symfony arg :pirate: ).

Merci pour votre aide les amis, maintenant ça marche !

Edit important

J’ai mené par curiosité quelques tests :

  • Que tous les containers Docker d’Akeneo et ceux de Laravel soient ou non sur un même réseau Docker, l’URL Laravel "http://localhost:80/receive_akeneo_events" (avec ou sans le port 80 bien sûr) est refusée par Akeneo avec le message d’erreur : "Failed to connect to server". Je précise que ce n’est pas "The url is not allowed", donc ma modification consistant à retirer localhost de l’array de la blacklist dans le code d’Akeneo fonctionne bien. Reste que ce comportement est étrange, particulièrement dans le cas où tous ces containers sont situés sur le même réseau Docker.

  • Si je mets l’IP Privée http://172.20.0.9/receive_akeneo_events là ça marche, comme annoncé au-dessus. Cette IP Privée étant générée vraisemblablement par Docker lors de la connexion du container correspondant au réseau Docker que je viens de créer.

Conclusion : j’aimerais bien investiguer pour mieux comprendre le traitement localhost cf. puce N°1 mais pas ma priorité !

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte