Utiliser nginx comme proxy authentifiant vers une ressource protégée

De façon à ce que les requêtes vers le proxy ne soient *pas* authentifiées

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

Bonsoir,

Pour le contexte, j’utilise GitHub Packages pour héberger des dépôts Maven — j’ai déjà donné le fait de gérer ça à la main et très peu pour moi merci, tellement il ne semble pas y avoir de solution simple pour les projets qui ne demandent pas d’authentification (open source).

Mais ! Justement, là est le problème, si GitHub Package fait très bien le boulot, en s’intégrant très bien avec GitHub Actions pour construire automatiquement tout ce beau monde, il y a un problème qui le rend très peu pratique à utiliser : actuellement, les requêtes pour récupérer les ressources doivent être authentifiées (même pour les paquets publics !). Compréhensible pour un projet privé ; inutile et casse pieds pour un paquet open source.

D’où ma question. J’aimerais pouvoir mettre en place un proxy qu’on puisse contacter sans authentification, et qui puisse transmette la requête authentifiée (avec un jeton d’accès de GitHub que j’aurais généré et qui ne permettrait que l’accès aux paquets) à GitHub, qui répondrait à mon proxy, qui répondrait à l’utilisateur initial. De cette façon, on aurait le meilleur des deux mondes : pas besoin de s’authentifier mais on profite de l’hébergement de de GH Packages.

On aurait donc quelque chose dans cet esprit.

Utilisateur
    |
    |
    |  Non-authentifié
    |
    |
    v
https://maven.example.org/<repo>
    |
    |
    |  Authentifié avec un PAT
    |
    |
    v
https://maven.pkg.github.com/mon-orga/<repo>

Est-ce qu’il est possible de faire ceci avec uniquement nginx ? Faire un proxy de ce genre en Python ou autres serait simple, mais si je peux éviter de faire tourner un service juste pour ça, c’est d’autant mieux, ayant déjà un serveur nginx actif. Je n’ai pas trouvé quelque chose qui puisse me convenir, mais j’ai peur de ne pas utiliser de bons termes de recherche.

Une idée ?

P.-S. — Le but n’est pas de faire un proxy ouvert vers tout GitHub Packages : s’ils l’ont mis sous authentification, et même s’ils annoncent qu’ils travaillent à la lever, c’est pour une bonne raison. Il ne s’agirait d’avoir un proxy que vers mon organisation et pas le reste — proxy me permettant aussi de ne pas dépendre des URLs de GitHub Packages, ce qui permet de changer plus facilement de fournisseur.

+0 -0

actuellement, les requêtes pour récupérer les ressources doivent être authentifiées (même pour les paquets publics !).

Sous quelle forme exactement ? Si c’est un Basic Auth, un Bearer ou n’importe quoi à usage multiple qui peut juste se faire avec les headers HTTP, alors je suppose qu’on peut ajouter en dur le header adéquat en tapant l’upstream :

location /foo/bar {
   proxy_pass https://github.packages.example.com;
   proxy_set_header Authorization "Basic <Mon_Token_GitHub>";
}

Est-ce qu’il est possible de faire ceci avec uniquement nginx ?

Avec la configuration Nginx pure, je ne pense pas que tu puisses faire plus évolué. Si ton token change souvent, par exemple, il faut mettre à jour et recharger la config Nginx à chaque fois. En revanche il y a peut-être moyen avec nginx-lua : tu peux scripter des bouts de conf en Lua inline dans la config ou dans des fichiers .lua séparés si c’est plus commode. Dès lors ta config peut être dynamique : le code Lua va chopper le bon token en vigueur pour qu’il soit utilisé dans le proxy_set_header Authorization "Basic <Mon_Token_GitHub>"; (ou autre header adequat pour Github Packages).

Évidemment, cela implique que ta configuration Nginx comportant en dur le token devient alors un fichier sensible. C’est à prendre en compte si tu veux envisager cette solution.

+1 -0

Oui pardon, j’aurais dû le préciser : c’est une autorisation par jeton via une en-tête HTTP (Authorization: Token <jeton>).

Mais en fait, cette proposition me convient : le jeton n’est pas amené à évoluer, c’est un Personal Access Token de GitHub qui ne change jamais (sauf si je décide de le faire moi-même). Et de toute façon ce jeton ne permet que d’accéder en lectures aux paquets publiés, paquets qui sont tous publics, donc pas de souci de sécurité ici (je pourrais même le poster ici, en fait).

Cela dit, merci pour l’info sur l’existence de nginx-lua ! Ça pourrait me servir pour d’autres projets non-liés :) .

+0 -0

Ok, cette solution fonctionne, merci beaucoup @sgble !

Pour d’éventuelles personnes qui auraient le même souci, je mets ici la configuration nginx finale que j’ai utilisée avec quelques commentaires.

# Redirection HTTP → HTTPS, rien de particulier ici
server {
    listen 80;
    listen [::]:80;
    server_name maven.example.fr;

    return 301 https://$host$request_uri;
}

server {
    listen 443 http2 ssl;
    listen [::]:443 http2 ssl;
    server_name maven.example.fr;

    include ssl_params;

    # On doit utiliser une regex pour pouvoir passer le chemin
    # complet à proxy_pass (voir plus bas).
    location ~ ^/(.+)$ {
        # Si on ne spécifie pas de résolveur DNS, nginx n'arrive pas à passer
        # la requête et échoue sur une erreur.
        # « maven.pkg.github.com could not be resolved (5: Operation refused) »
        # Ici j'utilise le DNS de CloudFlare, mais ça peut être n'importe quel autre.
        resolver 1.1.1.1 1.0.0.1 [2606:4700:4700::1111] [2606:4700:4700::1001];

        # Quand on proxifie vers quelque chose qui n'est pas juste un nom de
        # domaine (car ici je veux proxifier vers un sous-dossier), il faut absolument
        # préciser le chemin *complet* (d'où la regex plus haut).
        proxy_pass https://maven.pkg.github.com/votre-organisation/$1;

        # L'authentification, donc.
        proxy_set_header Authorization "Token ***************";
    }
}

Bien sûr ça fonctionnerait pareil pour les autres types dé dépôt de GitHub Package (nuget, npm, …) ou pour n’importe quelle ressource authentifiée par en-tête HTTP.

+2 -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