spring-cloud-config
spring-cloud-config copied to clipboard
Key authentication fails for default SSH repository when using multiple repositories with pattern matching
When using Pattern Matching and Multiple Repositories, the server doesn't seem to complete authentication with the SSH server, resulting in the repository not being found.
I have the following configuration:
spring:
cloud:
config:
server:
git:
uri: [email protected]:evpaassen/scc-config-a.git
ignore-local-ssh-settings: true
private-key: |
-----BEGIN RSA PRIVATE KEY-----
MIIJJwIBAAKCAgEArxgcYggvomWVg/Q0yOd/ykdreoDyyPgeO3mnqoiCBOPYAqu7
(...)
KZHY2Ty2t4JlfkmilzugFR7ADaXvO1++xyEMx4t9RzClbJSukG60fSPRew==
-----END RSA PRIVATE KEY-----
repos:
repo-b:
pattern: b/*
uri: [email protected]:evpaassen/scc-config-b.git
ignore-local-ssh-settings: true
private-key: |
-----BEGIN RSA PRIVATE KEY-----
MIIJKQIBAAKCAgEA1MyJU9FV3f0UqiAcax88VVZMkE6APbJ0XJParx3RtjpLlE1h
(...)
QRA+zPJMseOp2u9ch2eiODzpKyzuqmHpNwpivi8XZZIftF5no8sOIRh8po8a
-----END RSA PRIVATE KEY-----
Repository scc-config-b
connects fine, while the default one, scc-config-a
does not. This exception shows up in the log:
2020-09-02 10:43:44.072 WARN 17812 --- [-192.168.99.119] .c.s.e.MultipleJGitEnvironmentRepository : Error occured cloning to base directory.
org.eclipse.jgit.api.errors.InvalidRemoteException: Invalid remote: origin
at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:251) ~[org.eclipse.jgit-5.1.3.201810200350-r.jar:5.1.3.201810200350-r]
at org.eclipse.jgit.api.CloneCommand.fetch(CloneCommand.java:306) ~[org.eclipse.jgit-5.1.3.201810200350-r.jar:5.1.3.201810200350-r]
at org.eclipse.jgit.api.CloneCommand.call(CloneCommand.java:200) ~[org.eclipse.jgit-5.1.3.201810200350-r.jar:5.1.3.201810200350-r]
at org.springframework.cloud.config.server.environment.JGitEnvironmentRepository.cloneToBasedir(JGitEnvironmentRepository.java:589) ~[spring-cloud-config-server-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.cloud.config.server.environment.JGitEnvironmentRepository.copyRepository(JGitEnvironmentRepository.java:564) ~[spring-cloud-config-server-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.cloud.config.server.environment.JGitEnvironmentRepository.createGitClient(JGitEnvironmentRepository.java:547) ~[spring-cloud-config-server-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.cloud.config.server.environment.JGitEnvironmentRepository.refresh(JGitEnvironmentRepository.java:268) ~[spring-cloud-config-server-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.cloud.config.server.environment.JGitEnvironmentRepository.getLocations(JGitEnvironmentRepository.java:246) ~[spring-cloud-config-server-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentRepository.getLocations(MultipleJGitEnvironmentRepository.java:146) ~[spring-cloud-config-server-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.cloud.config.server.environment.AbstractScmEnvironmentRepository.findOne(AbstractScmEnvironmentRepository.java:57) ~[spring-cloud-config-server-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentRepository.findOne(MultipleJGitEnvironmentRepository.java:187) ~[spring-cloud-config-server-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.cloud.config.server.environment.CompositeEnvironmentRepository.findOne(CompositeEnvironmentRepository.java:58) ~[spring-cloud-config-server-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.cloud.config.server.config.ConfigServerHealthIndicator.doHealthCheck(ConfigServerHealthIndicator.java:73) ~[spring-cloud-config-server-2.2.5.RELEASE.jar:2.2.5.RELEASE]
at org.springframework.boot.actuate.health.AbstractHealthIndicator.health(AbstractHealthIndicator.java:82) ~[spring-boot-actuator-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at org.springframework.boot.actuate.health.HealthIndicator.getHealth(HealthIndicator.java:37) ~[spring-boot-actuator-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at org.springframework.boot.actuate.health.HealthEndpoint.getHealth(HealthEndpoint.java:71) ~[spring-boot-actuator-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at org.springframework.boot.actuate.health.HealthEndpoint.getHealth(HealthEndpoint.java:39) ~[spring-boot-actuator-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at org.springframework.boot.actuate.health.HealthEndpointSupport.getContribution(HealthEndpointSupport.java:99) ~[spring-boot-actuator-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at org.springframework.boot.actuate.health.HealthEndpointSupport.getAggregateHealth(HealthEndpointSupport.java:110) ~[spring-boot-actuator-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at org.springframework.boot.actuate.health.HealthEndpointSupport.getContribution(HealthEndpointSupport.java:96) ~[spring-boot-actuator-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at org.springframework.boot.actuate.health.HealthEndpointSupport.getHealth(HealthEndpointSupport.java:74) ~[spring-boot-actuator-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at org.springframework.boot.actuate.health.HealthEndpointSupport.getHealth(HealthEndpointSupport.java:61) ~[spring-boot-actuator-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at org.springframework.boot.actuate.health.HealthEndpoint.health(HealthEndpoint.java:65) ~[spring-boot-actuator-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at org.springframework.boot.actuate.health.HealthEndpoint.health(HealthEndpoint.java:55) ~[spring-boot-actuator-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:282) ~[spring-core-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.boot.actuate.endpoint.invoke.reflect.ReflectiveOperationInvoker.invoke(ReflectiveOperationInvoker.java:77) ~[spring-boot-actuator-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at org.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredOperation.invoke(AbstractDiscoveredOperation.java:60) ~[spring-boot-actuator-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at org.springframework.boot.actuate.endpoint.jmx.EndpointMBean.invoke(EndpointMBean.java:121) ~[spring-boot-actuator-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at org.springframework.boot.actuate.endpoint.jmx.EndpointMBean.invoke(EndpointMBean.java:96) ~[spring-boot-actuator-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:809) ~[na:na]
at java.management/com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801) ~[na:na]
at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1466) ~[na:na]
at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1307) ~[na:na]
at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1399) ~[na:na]
at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:827) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:359) ~[na:na]
at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) ~[na:na]
at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) ~[na:na]
at java.base/java.security.AccessController.doPrivileged(Native Method) ~[na:na]
at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) ~[na:na]
at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:562) ~[na:na]
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:796) ~[na:na]
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:677) ~[na:na]
at java.base/java.security.AccessController.doPrivileged(Native Method) ~[na:na]
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:676) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
Caused by: org.eclipse.jgit.errors.NoRemoteRepositoryException: [email protected]:evpaassen/scc-config-a.git: ERROR: Repository not found.
at org.eclipse.jgit.transport.TransportGitSsh.cleanNotFound(TransportGitSsh.java:218) ~[org.eclipse.jgit-5.1.3.201810200350-r.jar:5.1.3.201810200350-r]
at org.eclipse.jgit.transport.TransportGitSsh$SshFetchConnection.<init>(TransportGitSsh.java:306) ~[org.eclipse.jgit-5.1.3.201810200350-r.jar:5.1.3.201810200350-r]
at org.eclipse.jgit.transport.TransportGitSsh.openFetch(TransportGitSsh.java:170) ~[org.eclipse.jgit-5.1.3.201810200350-r.jar:5.1.3.201810200350-r]
at org.eclipse.jgit.transport.FetchProcess.executeImp(FetchProcess.java:137) ~[org.eclipse.jgit-5.1.3.201810200350-r.jar:5.1.3.201810200350-r]
at org.eclipse.jgit.transport.FetchProcess.execute(FetchProcess.java:123) ~[org.eclipse.jgit-5.1.3.201810200350-r.jar:5.1.3.201810200350-r]
at org.eclipse.jgit.transport.Transport.fetch(Transport.java:1271) ~[org.eclipse.jgit-5.1.3.201810200350-r.jar:5.1.3.201810200350-r]
at org.eclipse.jgit.api.FetchCommand.call(FetchCommand.java:243) ~[org.eclipse.jgit-5.1.3.201810200350-r.jar:5.1.3.201810200350-r]
... 55 common frames omitted
Observations
- When using only one repository, it works fine.
- When I set both config repositories to public on Github, it works fine, because they don't need key authentication.
- ~~When I change the configuration to the following, it works fine, even for the default repo (but that doesn't make sense to me, because SCC requires me to configure the
uri
for the default repository):~~ This is actually not true.spring: cloud: config: server: git: uri: [email protected]:evpaassen/scc-config-a.git ignore-local-ssh-settings: true private-key: | -----BEGIN RSA PRIVATE KEY----- MIIJJwIBAAKCAgEArxgcYggvomWVg/Q0yOd/ykdreoDyyPgeO3mnqoiCBOPYAqu7 (...) KZHY2Ty2t4JlfkmilzugFR7ADaXvO1++xyEMx4t9RzClbJSukG60fSPRew== -----END RSA PRIVATE KEY----- repos: repo-b: pattern: b/* uri: [email protected]:evpaassen/scc-config-b.git ignore-local-ssh-settings: true private-key: | -----BEGIN RSA PRIVATE KEY----- MIIJKQIBAAKCAgEA1MyJU9FV3f0UqiAcax88VVZMkE6APbJ0XJParx3RtjpLlE1h (...) QRA+zPJMseOp2u9ch2eiODzpKyzuqmHpNwpivi8XZZIftF5no8sOIRh8po8a -----END RSA PRIVATE KEY----- repo-a: pattern: a/* uri: [email protected]:evpaassen/scc-config-a.git ignore-local-ssh-settings: true private-key: | -----BEGIN RSA PRIVATE KEY----- MIIJJwIBAAKCAgEArxgcYggvomWVg/Q0yOd/ykdreoDyyPgeO3mnqoiCBOPYAqu7 (...) KZHY2Ty2t4JlfkmilzugFR7ADaXvO1++xyEMx4t9RzClbJSukG60fSPRew== -----END RSA PRIVATE KEY-----
Sample project
I have created a sample project which demonstrates the issue: https://github.com/evpaassen/scc-server. The application connects to to two private repositories, for which I included the deploy keys in the project. The issue should be easily reproducable by just running the ConfigServerApplication
.
Sorry for the delay. Looking at this, it seems that ssh authentication is by host only right now. I don't see anthing in the parameters of PropertyBasedSshSessionFactory.createSession()
that would allow us to choose by repo. There may be a way to plugin via TransportConfigCallback
but I'm not sure. Maybe @dyroberts or @ojhughes might know.