spring-cloud-config: Bitbucket V2 Git Protocol Not Working
We’re trying to upgrade Spring Cloud Server app from Spring Cloud 2020.0.4 to 2021.0.0, corresponding upgrade for Spring Boot: 2.5.7 -> 2.6.1 We’re using git SSH configuration using properties, repo is hosted on bitbucket. When running with 2020.0.4 everything works fine, no exceptions, config server starts as expected. We use this config server app for a while.
Our configuration in application.yaml:
spring:
cloud:
config:
server:
git:
uri: git@bitbucket.org:my-repo-name.git
skipSslValidation: true
timeout: 10
search-paths: '{profile}'
cloneOnStart: true
ignoreLocalSshSettings: true
privateKey: |
-----BEGIN RSA PRIVATE KEY-----
....
-----END RSA PRIVATE KEY-----
After changing version to 2021.0.0 and starting the app, different behaviour is observed (not seen in 2020.0.4) re ssh when running locally. Somehow this line is printed now, requiring to enter passphrase:
Enter passphrase for /Users/my-user-name/.ssh/my-user-Bitbucket:
After entering valid password , or just pressing Enter following exception is thrown and app is aborting:
2021-12-17 17:59:18.308 WARN 18400 — [ main] .c.s.e.MultipleJGitEnvironmentRepository : Error occured cloning to base directory.
org.eclipse.jgit.api.errors.TransportException: git@bitbucket.org:my-repo-name.git: failed to send channel request at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:224) at org.eclipse.jgit.api.CloneCommand.fetch(CloneCommand.java:303) at org.eclipse.jgit.api.CloneCommand.call(CloneCommand.java:178) at org.springframework.cloud.config.server.environment.JGitEnvironmentRepository.cloneToBasedir(JGitEnvironmentRepository.java:658) at org.springframework.cloud.config.server.environment.JGitEnvironmentRepository.initClonedRepository(JGitEnvironmentRepository.java:363) at org.springframework.cloud.config.server.environment.JGitEnvironmentRepository.afterPropertiesSet(JGitEnvironmentRepository.java:284) at org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentRepository.afterPropertiesSet(MultipleJGitEnvironmentRepository.java:66) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:412) at org.springframework.boot.SpringApplication.run(SpringApplication.java:302) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1290) at com.healthyinteractions.configserver.ConfigServerApplication.main(ConfigServerApplication.java:12) Caused by: org.eclipse.jgit.errors.TransportException: git@bitbucket.org:my-repo-name.git: failed to send channel request at org.eclipse.jgit.transport.JschSession$JschProcess.(JschSession.java:167) at org.eclipse.jgit.transport.JschSession.exec(JschSession.java:77) at org.eclipse.jgit.transport.TransportGitSsh$SshFetchConnection.(TransportGitSsh.java:289) at org.eclipse.jgit.transport.TransportGitSsh.openFetch(TransportGitSsh.java:153) at org.eclipse.jgit.transport.FetchProcess.executeImp(FetchProcess.java:142) at org.eclipse.jgit.transport.FetchProcess.execute(FetchProcess.java:94) at org.eclipse.jgit.transport.Transport.fetch(Transport.java:1309) at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:213) … 24 common frames omitted Caused by: com.jcraft.jsch.JSchException: failed to send channel request at com.jcraft.jsch.Request.write(Request.java:65) at com.jcraft.jsch.RequestEnv.request(RequestEnv.java:52) at com.jcraft.jsch.ChannelSession.sendRequests(ChannelSession.java:222) at com.jcraft.jsch.ChannelExec.start(ChannelExec.java:41) at com.jcraft.jsch.Channel.connect(Channel.java:152) at org.eclipse.jgit.transport.JschSession$JschProcess.(JschSession.java:159) … 31 common frames omitted
Same exception is thrown when trying to run the app in the cloud.
I didn’t find any breaking changes mentioned in the documentation re Spring Cloud Config Server due to 2021.0.0/2.6.x release. Am I missing something here? Please advise.
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 1
- Comments: 16 (2 by maintainers)
Bad Hack: git config file, created by jgit can be tweaked using next code (can be placed into main method before spring application run)
I think the problem occurs when the remote git repository doesn’t support git protocol version V2. Starting from version 5.11 JGit uses protocol V2 by default (release notes: https://wiki.eclipse.org/JGit/New_and_Noteworthy/5.11). According to the documentation, JGit should fall back to older protocol, but I did some debugging and it looks like it doesn’t. Spring-cloud-config uses JGit version 5.12.0.202106070339-r (change: https://github.com/spring-cloud/spring-cloud-config/commit/8d8451b694f22cebb64781b412fa78c45da0db97).
I was able to configure the gitlab instance to use protocol V2, which fixed the issue. Before that I tried to override the JGit version to the older one in maven dependencyManagement which also worked fine - the config server was running without any issues.
This is a bug in JSch. The bitbucket.org server does not allow setting environment variables, and with protocol V2, one needs to set the environment variable GIT_PROTOCOL to “version=2”. JSch sends the request to set this environment variable in the SSH channel session with a flag indicating that it wants a reply, so the server sends back an error reply, and JSch terminates the SSH connection.
This behavior in JSch is wrong. OpenSSH and also Apache MINA sshd send this SSH request with a flag indicating that they don’t want a reply, so the server just silently doesn’t set that environment variable, and protocol V0/V1 is used.
Compare Eclipse bug 576922.
JGit does no longer support JSch. Spring Cloud should migrate to the newer supported transport using Apache MINA sshd (bundle
org.eclipse.jgit.ssh.apache).(Or migrate to using https://github.com/mwiede/jsch instead, but the JGit team cannot give any support for the combination of that JSch fork and JGit. See also mwiede/jsch#93.)
@j0rzsh I’m glad I could help!
I found out an alternative workaround, which doesn’t require switching the JGit dependency in runtime - you can configure git client to always use protocol version 1. This works, event if you have
ignoreLocalSshSettings: truein config-server configuration.Just put the following section into the global git config file (default location is
~/.gitconfig):There are cases when one can’t or don’t want to modify the global git config, so I think there should be an option to specify protocol version in
org.springframework.cloud.config.server.environment.JGitEnvironmentPropertiesto keep all the config in a single spring configuration file.Happening the same for me with a passwordless privateKey and these versions:
Spring boot: 2.6.2 Spring-cloud: 2021.0.0
The exact same configuration works on this setup:
Spring boot: 2.5.4 Spring-cloud: 2020.0.5
In my case the configuration is:
Application.yml:
And environment variable set
SPRING_CLOUD_CONFIG_SERVER_GIT_PRIVATEKEYwith the content of the private key with access to that private repositoryCompiled using
maven:3.8.4-openjdk-17from docker hub and run usingopenjdk:17-jdk