Cannot open git-upload-pack at com.simplicite.util.tools.GitTool.pull

Request description

Demande d’aide et de support suite à une maintenance non planifiée sur nos environnements GCP.

Depuis quelques semaines, une maintenance dont nous ignorons la portée (toutes nos équipes DevOps sont sur le front) a mis en défaut la fonctionnalité “repository git” de toutes nos instances déployées sur GCP/GKE (migration en cours, uniquement du DEV actuellement). Il est désormais impossible d’initialiser les repository git depuis les instance Simplicité avec l’erreur suivante :

2023-12-14 20:59:07,798|SIMPLICITE|WARN||http://p01-74196-api-6546f87f6d-gvrsj:8080||WARN|a068181|com.simplicite.util.ModuleDB|applyConfiguration||Evénement: Warning: unable to pull from remote origin
    com.simplicite.util.exceptions.GitException: https://gitlabee.dt.renault.com/IRN-74196/simplicite/modules/renaultlogger.git: git-upload-pack not permitted on 'https://gitlabee.dt.renault.com/IRN-74196/simplicite/modules/renaultlogger.git/'
     at com.simplicite.util.tools.GitTool.pull(GitTool.java:724)
     at com.simplicite.util.ModuleDB.applyConfiguration(ModuleDB.java:835)
     at com.simplicite.objects.System.Module.postSave(Module.java:249)
...
    Caused by: org.eclipse.jgit.api.errors.TransportException: https://gitlabee.dt.renault.com/IRN-74196/simplicite/modules/renaultlogger.git: git-upload-pack not permitted on 'https://gitlabee.dt.renault.com/IRN-74196/simplicite/modules/renaultlogger.git/'
     at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:224)
     at org.eclipse.jgit.api.PullCommand.call(PullCommand.java:266)
     at com.simplicite.util.tools.GitTool.pull(GitTool.java:718)
     ... 45 more
    Caused by: org.eclipse.jgit.errors.TransportException: https://gitlabee.dt.renault.com/IRN-74196/simplicite/modules/renaultlogger.git: git-upload-pack not permitted on 'https://gitlabee.dt.renault.com/IRN-74196/simplicite/modules/renaultlogger.git/'
     at org.eclipse.jgit.transport.TransportHttp.connect(TransportHttp.java:692)
     at org.eclipse.jgit.transport.TransportHttp.openFetch(TransportHttp.java:465)
     at org.eclipse.jgit.transport.FetchProcess.executeImp(FetchProcess.java:141)
     at org.eclipse.jgit.transport.FetchProcess.execute(FetchProcess.java:93)
     at org.eclipse.jgit.transport.Transport.fetch(Transport.java:1317)
     at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:213)
     ... 47 more
2023-12-14 20:59:06,039|SIMPLICITE|INFO||http://p01-74196-api-6546f87f6d-gvrsj:8080||INFO|a068181|com.simplicite.util.ModuleDB|applyConfiguration||Evénement: Git remote origin added (URI: https://gitlabee.dt.renault.com/IRN-74196/simplicite/modules/renaultlogger.git)
2023-12-14 20:59:00,566|SIMPLICITE|INFO||http://p01-74196-api-6546f87f6d-gvrsj:80

Il me semble bien que Simplicité n’est pas en cause car les autres environnements déployés (DockerSwarm, AWS/ECS) fonctionnent normalement avec cette fonctionnalité.

Je cherche néanmoins à comprendre ce qui pourrait induire ce comportement dans le contexte particulier GCP/GKE. Une cause possible qui a été identifiée concerne le fait que les IP qui se connectent au repository git central (gitlabee.de.renault.com) doivent désormais être identifiées dans une liste blanche.

J’ai demandé l’ouverture d’un proxy identifié dans la liste pour pouvoir réactiver la fonction mais il semble que ça ne suffise pas. La configuration du proxy dans l’image est réalisée dans le Dockerfile via un RUN git config --global http.proxy http://identified.proxy.in.whitelist:port.

Est-ce qu’une reconfiguration du backend gitlabee peut être à l’origine du problème ? Si oui, pourquoi le problème ne se pose que depuis le contexte GCP/GKE ? Est-il possible que l’activation du proxy via la git config ne soit pas prise en compte et qu’il faille intervenir dans le code intégrant jgit (GitTool) ?

En cherchant sur internet, certaines personnes disent que ça semble lié à de pbs réseau et/ou de droits vs le serveur des repos Git.

D’autres (comme ici: git - JGit HTTPS cloning is not working - Stack Overflow) semblent dire qu’il y a des subtilités avec jGit quand on passe par un proxy.

Il faudrait donc peut être commencer par tester via des commandes CLI git pour voir si c’est un pb plus général de “tuyauterie” ou un pb spécifique à la lib jGit (comme celui discuté dans le post ci-dessus)

PS: à titre de contournement, serait il possible de plutôt cloner les repos Git via SSH au lieu d’HTTP ?

Bonjour David,

merci beaucoup pour ta réponse rapide.

J’ai testé le client git via une session bash ssh dans le conteneur.

  • Sans le proxy, erreur 403.
  • Avec le proxy, git fetch semble fonctionner (me demande les credentials).

J’ai essayé de mettre en œuvre une clé ssh en m’appuyant sur ce qui est décrit dans les divers supports mais j’avoue que ça dépasse pour l’instant mes compétences… Je bute sur la première étape consistant à générer une clé ssh valide.

Ah j’ai oublié de préciser que nous sommes encore engagés dans le processus de migration et que l’upgrade 5.3 doit être réalisé après avoir migré dans GCP… Du coup la plupart de nos instances sont encore en 5.2 :blush: :face_with_peeking_eye: :no_mouth: :face_in_clouds:

Pas de différence notable entre 5.2 et 5.3 dans la mécanique autour de jGit (mais une différence de version de cette lib)

Au vu de tes tests en ligne de commande je pense que le pb est au niveau d’une subtilité entre me proxy et jGit (cf. le post stackoverflow de ma réponse précédente et sa source : java - JGit proxy configuration in code - Stack Overflow). On a pas de proxy sous la main pour tester ce genre de choses, d’où ma proposition de cloner/puller/pusher plutôt en SSH plutôt qu’en dumb HTTP

Pour générer une clé SSH: ssh_keygen => tu obtiens une clé privée et une clé publique

Ensuite tu référence la clé publique dans ton serveur Git et tu mets la clé privée dans le $HOME/.ssh/ du compte qui execute Simplicité. Dans nos images Docker tu peux la mettre - par montage ou copie - dans /usr/local/tomcat/.ssh le script de démarrage la recopiera au bon endroit en fct du user qui execute Tomcat. Cf. training

Ca n’aura aucun effet sur jGit, par contre si je comprends bien il est possible de configurer le proxy par défaut utilisé par la Java (et donc par jGit) via des directives JVM -Dhttp.proxyHost=... -Dhttp.proxyPort=... Par contre ce sera utilisé pour toutes les requêtes HTTP effectuées depuis Java (à moins de passer une whilelist -Dhttp.nonProxyHosts="localhost|127.0.0.1|...")

PS: La solution à basse de code ( ProxySelector.setDefault(...)) proposée dans les posts cités précédemment fait à mon avis exactement la même chose mais peut être est il possible d’y mettre plus de logique. Je pense que ça doit pouvoir s’implémenter dans le platform hook postPlatformInit.

1 Like

j’y jardine déjà… que puis-je y ajouter ? (en espérant ne rien planter)

Quid d’abord de l’approche via les directives JVM pour positionner le proxy par défaut ?

Le bout de code proposé dans les posts stackoverflow semble adaptés à du “proxy sélectif en fct de l’URL appelée” (vs l’approche par argument JVM qui est pour toute URL appelée coté serveur).

Si c’est une bonne approche on pourrait ajouter ce genre de chose sous forme de méthode helper et/ou de paramétrage via param système mais ça ne sera pas forcément envisageable dans le cadre de la v5 car on ne travaille aujourd’hui en évolutif plus que sur la v6

Actuellement, nous utilisons un proxy par défaut pour toutes les applications hébergées dans GCP (appelons-le “app-proxy”). Comme ce proxy est partagé avec des applications partenaires, il ne sera pas whiltelisté (j’ai demandé mais ça a été refusé du fait du partage externe).

Nos devops ont proposé d’utiliser un autre proxy à usage restreint interne (appelons-le iapp-proxy). J’ai testé en configurant “iapp-proxy” à la place de “app-proxy” sans mesurer l’impact de ce changement et en concentrant mes tests sur la fonctionnalité “git repository”. En passant par “iapp-proxy”, j’ai le même problème “git-upload-pack not permitted” qui me semble être un message de plus haut niveau de jgit qui doit recevoir un 403 dans les basses couches). L’impression que j’ai est que soit le proxy configuré dans la jvm n’est pas pris en compte par jgit soit autre-chose a changé spécifiquement dans les prérequis d’usage des “bare repository / git-*-pack”. Je me renseigne en interne pour savoir comment mettre en œuvre des clés ssh certifiées.

Peux tu m’indiquer exactement comment tu le configure sur la JVM ?
Merci

Dans un contexte K8S / … / base / kustomization.yaml:
- JAVA_OPTS=-Dhttp.proxyHost=app-proxy....fr -Dhttp.proxyPort=80 -Dhttps.proxyHost=app-proxy....fr -Dhttps.proxyPort=80 -Dhttp.nonProxyHosts=169.254.169.254\|...\|localhost\|127.0.0.1

C’est la configuration “standard” recommandée par nos DevOps.
Dernièrement, pour résoudre mon pb, ils ont recommandé de passer par un autre proxy interne car le proxy standard est partagé avec des partenaires externes apparemment et il y a une procédure particulière pour autoriser les partenaires externes donc il ne veulent pas mettre le proxy standard en liste blanche.

Je viens de redéployer la conf standard “app-proxy” (paramètres jmv) + proxy interne forcé via RUN git config --global http.proxy http://iapp-proxy...:port et RUN git config --global verifySsl false.

→ init du repo git depuis la UI SImplicité en erreur git-upload-pack not permitted

2023-12-15 15:30:00,350|SIMPLICITE|WARN||http://p01-74196-api-8454558974-jd4n6:8080||WARN|a068181|com.simplicite.util.ModuleDB|applyConfiguration||Evénement: Warning: unable to pull from remote origin
    com.simplicite.util.exceptions.GitException: https://gitlabee.dt.renault.com/IRN-74196/simplicite/modules/renaultlogger.git: git-upload-pack not permitted on 'https://gitlabee.dt.renault.com/IRN-74196/simplicite/modules/renaultlogger.git/'
     at com.simplicite.util.tools.GitTool.pull(GitTool.java:724)
     at com.simplicite.util.ModuleDB.applyConfiguration(ModuleDB.java:835)
     at com.simplicite.objects.System.Module.postSave(Module.java:249)

→ git fetch en me positionnant dans le conteneur (utilise la conf local+globale spécifique au client git)

[root@p01-74196-api-8454558974-jd4n6 tomcat]# cd webapps/ROOT/WEB-INF/git/
[root@p01-74196-api-8454558974-jd4n6 git]# dir
total 16
drwxr-x--- 3 root       root       4096 Dec 15 14:30 ./
drwxrwxr-x 1 simplicite simplicite 4096 Dec 15 07:17 ../
drwxr-x--- 3 root       root       4096 Dec 15 14:30 RenaultLogger/
[root@p01-74196-api-8454558974-jd4n6 git]# cd RenaultLogger/
[root@p01-74196-api-8454558974-jd4n6 RenaultLogger]# git config -l
http.proxy=http://iapp-proxy...:80
http.verifyssl=false
core.repositoryformatversion=0
core.filemode=true
core.logallrefupdates=true
core.autocrlf=false
core.eol=lf
http.uploadpack=true
http.receivepack=true
remote.origin.url=https://gitlabee.dt.renault.com/IRN-74196/simplicite/modules/renaultlogger.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
[root@p01-74196-api-8454558974-jd4n6 RenaultLogger]# git config --global -l
http.proxy=http://iapp-proxy....:80
http.verifyssl=false
[root@p01-74196-api-8454558974-jd4n6 RenaultLogger]# pwd
/usr/local/tomcat/webapps/ROOT/WEB-INF/git/RenaultLogger
[root@p01-74196-api-8454558974-jd4n6 RenaultLogger]# git fetch
Username for 'https://gitlabee.dt.renault.com':

→ le même test en mettant app-proxy dans la conf globale git:

[root@p01-74196-api-8454558974-jd4n6 RenaultLogger]# git fetch
fatal: unable to access 'https://gitlabee.dt.renault.com/IRN-74196/simplicite/modules/renaultlogger.git/': The requested URL returned error: 403

→ le même test en retirant le proxy de la conf globale git

[root@p01-74196-api-8454558974-jd4n6 RenaultLogger]# git config --global -l
http.verifyssl=false
[root@p01-74196-api-8454558974-jd4n6 RenaultLogger]# git fetch
fatal: unable to access 'https://gitlabee.dt.renault.com/IRN-74196/simplicite/modules/renaultlogger.git/': The requested URL returned error: 403

En conclusion,

  • gitlabee refuse la connexion si je n’utilise pas le proxy interne mis en liste blanche (que j’utilise le proxy standard partagé ou pas de proxy du tout)
  • gitlabee refuse la connexion via jgit (GitTool) quel que soit le proxy configuré dans la jvm
  • gitlabee accepte la connexion via git cli si je configure spécifiquement le proxy interne (déclaré en liste blanche) dans ~/.gitconfig

Du coup, comment je peux faire pour configurer jgit pour qu’il passe par le proxy interne ?

Ok pour les arguments JVM.

Comme dit plus haut la config git config n’a aucun effet sur ce qu’il se passe niveau Java (la lib jGit ne tient aucun compte de la config Git niveau OS) mais tes tests en CLI montrent qu’il faut passer par le proxy iapp pour pouvoir clone/pull/fetch/push

Comme ce proxy iapp n’est pas celui configuré par défaut sur la JVM, je ne vois donc pas d’autre solution que d’en passer par un mécanisme d’utilisation de proxy par défaut plus “malin”, tel que celui décrit dans les posts stackoverflow (ProxySelector.setDefault(...)). Je n’ai aucune experience de l’utilisation de ce genre de choses en Java mais les exemples semblent conceptuellement assez simples (si telle URL alors tel proxy sinon le proxy par défaut).

Le bon endroit pour mettre ça dans le contexte Simplicité est, à priori, au niveau du platform hook postPlatformInit = au démarrage de la webapp avant de faire des appels HTTP serveur.

C’est toi qui est le mieux placé pour tester ça. Ensuite, si cette approche est la bonne, on pourra envisager d’intégrer ça à la plateforme via une config ad hoc dans un param système indiquant les URLs nécessitant de passer par un proxy qui n’est pas le proxy par défaut de la JVM.

Alors je me suis lancé avec le sentiment d’être le prof de sport dans “prof” qui plonge dans le bassin à poil…

package com.simplicite.commons.Application;

import java.util.*;
import java.net.ProxySelector;
import java.net.URI;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.net.ProxySelector;
import java.net.SocketAddress;
import java.net.InetSocketAddress;
// import org.eclipse.jgit.transport.*;

import com.simplicite.util.*;
import com.simplicite.bpm.*;
import com.simplicite.util.exceptions.*;
import com.simplicite.util.tools.*;

/**
 * Platform Hooks
 */
public class PlatformHooks extends com.simplicite.util.engine.PlatformHooksInterface {
	/*
	** Specialize platform init
	*/
	@Override
	public String postPlatformInit(Grant sys) {
		try {
			ProxySelector.setDefault(new ProxySelector() {
				final ProxySelector delegate = ProxySelector.getDefault();
			
				// @Override
				public List<Proxy> select(URI uri) {
					// Filter the URIs to be proxied
					if (uri.toString().contains("gitlabee.dt")&& uri.toString().contains("https")) {
						return Arrays.asList(new Proxy(Type.HTTP, InetSocketAddress.createUnresolved("iapp-proxy....", 80)));
					}
					if (uri.toString().contains("gitlabee.dt") && uri.toString().contains("http")) {
						return Arrays.asList(new Proxy(Type.HTTP, InetSocketAddress.createUnresolved("iapp-proxy....", 80)));
					}
					// revert to the default behaviour
					return delegate == null ? Arrays.asList(Proxy.NO_PROXY) : delegate.select(uri);
				}
				@Override
				public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
					if (uri == null || sa == null || ioe == null) {
						throw new IllegalArgumentException("Arguments can't be null.");
					}
				}
			});
		} catch(Exception e) {
			AppLog.error("EXCEPTION CAUGHT/postPlatformInit", e, sys);
		} finally {
			return super.postPlatformInit(sys);
		}
	}
	/**/
}

Sauf que ça compile pas… :sob:

Class compilation error (status 1)
/usr/local/tomcat/webapps/ROOT/WEB-INF/src/com/simplicite/commons/Application/PlatformHooks.java:28: error: <anonymous com.simplicite.commons.Application.PlatformHooks$1> is not abstract and does not override abstract method connectFailed(URI,SocketAddress,IOException) in ProxySelector
			ProxySelector.setDefault(new ProxySelector() {
			                                             ^
/usr/local/tomcat/webapps/ROOT/WEB-INF/src/com/simplicite/commons/Application/PlatformHooks.java:43: error: method does not override or implement a method from a supertype
				@Override
				^
2 errors
#ERROR

OK je regarde ça et je te tiens au courant.

Cette classe de test unitaire là compile…

J’ai testé sur une 6.0 donc sur un JDK 21 et sur une 5.3 donc sur un JDK 17, quelle version exacte utilises-tu ?

package com.simplicite.tests.Application;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.net.ProxySelector;
import java.net.SocketAddress;
import java.net.URI;
import java.util.Arrays;
import java.util.List;

import org.junit.Test;
import static org.junit.Assert.fail;

/**
 * Proxy selector test
 */
public class TestProxy {
	@Test
	public void test() {
		try {
			ProxySelector.setDefault(
				new ProxySelector() {
					final ProxySelector delegate = ProxySelector.getDefault();

					@Override
					public List<Proxy> select(URI uri) {
						if (uri.toString().contains("gitlabee.dt")&& uri.toString().contains("https"))
							return Arrays.asList(new Proxy(Type.HTTP, InetSocketAddress.createUnresolved("iapp-proxy....", 80)));

						return delegate == null ? Arrays.asList(Proxy.NO_PROXY) : delegate.select(uri);
					}

					@Override
					public void connectFailed(URI uri, SocketAddress sa, IOException e) {
						// Do something...
					}
				}
			);
		} catch (Exception e) {
			fail(e.getMessage());
		}
	}
}

PS: quand on la lance ça ne fait pas d’erreur mais je ne peux pas tester si ça fait ce que c’est sensé faire…

1 Like

Super merci bcp.
Je sors juste de réunion.
Nous sommes en 5.2.48 + JDK 17.

Je récupère ça.
Si je suis ton idée, il s’agit d’intégrer la redéfinition du proxy selector dans un cas test qui pourrait être instancié depuis le postPlatformInit c’est bien ça ? Si oui, comment je la lance ?

C’est magique :slight_smile:

package com.simplicite.tests.Application;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.net.ProxySelector;
import java.net.SocketAddress;
import java.net.URI;
import java.util.Arrays;
import java.util.List;

import org.junit.Test;
import static org.junit.Assert.fail;

import com.simplicite.util.*;

/**
 * Unit tests IacProxySelector
 */
public class IacProxySelector {
	@Test
	public void test() {
		try {
			ProxySelector.setDefault(
				new ProxySelector() {
					final ProxySelector delegate = ProxySelector.getDefault();
					@Override
					public List<Proxy> select(URI uri) {
						if (System.getProperty("https.altProxyHost") != null && System.getProperty("https.altProxyPort") != null) {
							if (uri.toString().contains("gitlabee.dt") && uri.toString().contains("https://")) {
								AppLog.warning("Override default https proxy for gitlabee.dt destination", null, Grant.getSystemAdmin());
								return Arrays.asList(new Proxy(Type.HTTP, InetSocketAddress.createUnresolved(
									System.getProperty("https.altProxyHost"), 
									Integer.parseInt(System.getProperty("https.altProxyPort"))
								)));
							}
						}
						if (System.getProperty("http.altProxyHost") != null && System.getProperty("http.altProxyPort") != null) {
							if (uri.toString().contains("gitlabee.dt") && uri.toString().contains("http://")) {
								AppLog.warning("Override default http proxy for gitlabee.dt destination", null, Grant.getSystemAdmin());
								return Arrays.asList(new Proxy(Type.HTTP, InetSocketAddress.createUnresolved(
									System.getProperty("http.altProxyHost"), 
									Integer.parseInt(System.getProperty("http.altProxyPort"))
								)));
							}
						}
						return delegate == null ? Arrays.asList(Proxy.NO_PROXY) : delegate.select(uri);
					}
					@Override
					public void connectFailed(URI uri, SocketAddress sa, IOException e) {
						if (uri == null || sa == null || e == null) throw new IllegalArgumentException("Arguments can not be null.");
					}
				}
			);
			AppLog.warning("Override default proxy selector", null, Grant.getSystemAdmin());
		} catch (Exception e) {
			fail(e.getMessage());
		}
	}
}
2023-12-15 19:40:27,164|SIMPLICITE|INFO||http://p01-74196-api-8454558974-jd4n6:8080||INFO|a068181|com.simplicite.util.ModuleDB|applyConfiguration||Evénement: Pulled from remote origin
2023-12-15 19:40:27,164|SIMPLICITE|INFO||http://p01-74196-api-8454558974-jd4n6:8080||INFO|system|com.simplicite.util.tools.GitTool|pull||Event: Pull fetch result:
2023-12-15 19:40:26,664|SIMPLICITE|WARN||http://p01-74196-api-8454558974-jd4n6:8080||WARN|system|com.simplicite.tests.Application.IacProxySelector$1|select||Event: Override default https proxy for gitlabee.dt destination
2023-12-15 19:40:26,581|SIMPLICITE|WARN||http://p01-74196-api-8454558974-jd4n6:8080||WARN|system|com.simplicite.tests.Application.IacProxySelector$1|select||Event: Override default https proxy for gitlabee.dt destination
2023-12-15 19:40:26,503|SIMPLICITE|WARN||http://p01-74196-api-8454558974-jd4n6:8080||WARN|system|com.simplicite.tests.Application.IacProxySelector$1|select||Event: Override default https proxy for gitlabee.dt destination
2023-12-15 19:40:26,424|SIMPLICITE|WARN||http://p01-74196-api-8454558974-jd4n6:8080||WARN|system|com.simplicite.tests.Application.IacProxySelector$1|select||Event: Override default https proxy for gitlabee.dt destination
2023-12-15 19:40:26,422|SIMPLICITE|INFO||http://p01-74196-api-8454558974-jd4n6:8080||INFO|a068181|com.simplicite.util.ModuleDB|applyConfiguration||Evénement: Git remote origin added (URI: https://gitlabee.dt.renault.com/IRN-74196/simplicite/modules/renaultapi.git)
...
2023-12-15 19:39:10,638|SIMPLICITE|WARN||http://p01-74196-api-8454558974-jd4n6:8080||WARN|system|com.simplicite.tests.Application.IacProxySelector|test||Event: Override default proxy selector

Il en me reste plus qu’à exécuter le test automatiquement via le platform init…
L’équivalent en code de ça :

Cool ! Poste nous une feature request pour qu’on intègre ça en standard avec config via param système. Merci