Spring-cloud-config: Git SSH Deployment keys as alternative to username/password

Created on 5 Jan 2015  路  23Comments  路  Source: spring-cloud/spring-cloud-config

username/password has the drawback that they a tied to a human or a technical user.
There is also the possibility to access the repository not only with username/password but also with ssh keys.
Does spring-cloud-config support ssh keys?

closable question

Most helpful comment

Personal Token approach

I'm using docker to deploy and a Personal Access Token. The advantage over the git@ URLs are:

  • I was using the git@ URL but I would also need to provide the ~/.ssh directory as a volume to the keys;

    • OPS still need to provide the key in the host;

  • The first time your config server tries to contact your Github Server (say an Enterprise) in a new host, you need to update the ~/.ssh/known_hosts file

    • As described by @joshwand above, the file needs to be updated following the pattern.

Token in URL fails

As @ccit-spence described above, the TOKEN in the URL fails with the Transport Exception.

2016-06-03 06:25:49.867 ERROR 7 --- [nio-8888-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : 
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request 
processing failed; nested exception is java.lang.IllegalStateException: Cannot clone or checkout 
repository] with root cause
org.eclipse.jgit.errors.TransportException: 
https://[email protected]/servicesplatform-tools/ctg-config.git: 
Authentication is required but no CredentialsProvider has been registered

TOKEN in Properties: A cleaner approach

You must use the properties as follows, having the password as an empty string.

  • SPRING_CLOUD_CONFIG_SERVER_GIT_USERNAME = TOKEN
  • SPRING_CLOUD_CONFIG_SERVER_GIT_PASSWORD =

For the JGit to work, you need to provide both the Personal Token and the Password (empty). According to https://github.com/blog/1270-easier-builds-and-deployments-using-git-over-https-and-oauth, the username is the TOKEN and the password can be an empty string.

You can start your own config server using the Java samples or a Docker Container, which is shown below. I'm using the environment variables setup here, which you could do using regular shell and Java combo:

docker run -it -p 8888:8888 
  -e SPRING_CLOUD_CONFIG_SERVER_GIT_URI=https://github.mycompany.com/servicesplatform-tools/config.git
  -e SPRING_CLOUD_CONFIG_SERVER_GIT_USERNAME=389e3f300c9972d704b418c2310410ffc9f1499e 
  -e SPRING_CLOUD_CONFIG_SERVER_GIT_PASSWORD=  hyness/spring-cloud-config-server

NPE when password is not provided

Running without the Empty Password as string Fails the server with a NPE the first time it tries to clone the repo.

2016-06-03 06:32:39.388 ERROR 6 --- [nio-8888-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : 
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request 
processing failed; nested exception is java.lang.IllegalStateException: Cannot load environment] 
with root cause

java.lang.NullPointerException: null
    at org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider.<init>
(UsernamePasswordCredentialsProvider.java:65) ~[org.eclipse.jgit-3.5.3.201412180710-
r.jar!/:3.5.3.201412180710-r]
    at org.springframework.cloud.config.server.environment.JGitEnvironmentRepository.
setCredentialsProvider(JGitEnvironmentRepository.java:310) ~[spring-cloud-config-server-
1.1.0.RELEASE.jar!/:1.1.0.RELEASE]

Cheers 馃嵑 !

All 23 comments

See also discussion in #34: my impression from there was since github uses HTTP basic for token authentication it would work anyway with no changes.

@btiernay said in #34 that he was going to open a new ticket and contribute something. So far nothing happened. What would you propose?

Thank you Dave. Advantage of SSH Keys vs. OAuth is that this is git standard. I will try out the suggestions mentioned #34 and see how far we get.

@dsyer Sorry for the delay. I got pulled in a different direction and haven't had a chance to tackle this. I plan on coming back to #34 eventually if no one takes it in the meantime. Cheers.

Is username/password still working with bitbucket? Using 'git.uri' https://uname:[email protected]/etc...

It would work if bitbucket supports HTTP basic authentication (JGit handles it AFAIK). Why would it not?

I have used it before with Bitbucket, started working on setting up a config server and now getting this error: Authentication is required but no CredentialsProvider has been registered

To clarify using YAML
Spring: cloud: config: server: git: uri: URL HERE

OK, I guess JGit handles it if you register a handler. I think it's a static method call so you can do it anywhere (from memory). Check the JGit documentation / forums and if you get something working that we can incorporate into this project that's great.

Not sure exactly where yet, but I did have it working in 1.0.0.M2 Something must have changed since then.

I have verified with M2 it worked. M3 up to RC2 it fails. RC1 has the error that I am seeing now.

Figured it out. Nothing needed to change. I was not injecting the properties the way the environment properties were being read into the JGitEnvironmentRepository.java class.

Before:

spring:
    cloud:
        config:
            server:
                git:
                    uri: https://username:[email protected]/xxx/repo.git

After:

spring:
    cloud:
        config:
            server:
                git:
                    uri: https://bitbucket.org/xxx/repo.git
                    username: someuser
                    password: strongpassword

+1 for ssh key support. We host our own git repo which only support username / ssh-keys

I don't think that should be a problem (you just have to set the identity up as normal I think - just look it up in the JGit docs/forum).

Thanks, works like a charm!

@kumlien can you provide your sample configuration?

@Vad1mo I didn't have to configure anything special, it just worked out of the box. Our keys are stored in default directories (~/.ssh) and the spring.cloud.config.server.git.uri is pointing to our internal git repo like ssh://git@git/configuration/cloud-configuration.

You don't need any special configuration if you don't have a passphrase on your key, in which case you need to do something similar to what btiernay did in #34 by following this Stackoverflow answer and adding the passphrase via the addIdentity method.

For future reference, jsch/jgit does not accept a known_hosts file in the hashed format-- it expects it to conform to the output of:

ssh-keyscan -t rsa hostname

Personal Token approach

I'm using docker to deploy and a Personal Access Token. The advantage over the git@ URLs are:

  • I was using the git@ URL but I would also need to provide the ~/.ssh directory as a volume to the keys;

    • OPS still need to provide the key in the host;

  • The first time your config server tries to contact your Github Server (say an Enterprise) in a new host, you need to update the ~/.ssh/known_hosts file

    • As described by @joshwand above, the file needs to be updated following the pattern.

Token in URL fails

As @ccit-spence described above, the TOKEN in the URL fails with the Transport Exception.

2016-06-03 06:25:49.867 ERROR 7 --- [nio-8888-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : 
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request 
processing failed; nested exception is java.lang.IllegalStateException: Cannot clone or checkout 
repository] with root cause
org.eclipse.jgit.errors.TransportException: 
https://[email protected]/servicesplatform-tools/ctg-config.git: 
Authentication is required but no CredentialsProvider has been registered

TOKEN in Properties: A cleaner approach

You must use the properties as follows, having the password as an empty string.

  • SPRING_CLOUD_CONFIG_SERVER_GIT_USERNAME = TOKEN
  • SPRING_CLOUD_CONFIG_SERVER_GIT_PASSWORD =

For the JGit to work, you need to provide both the Personal Token and the Password (empty). According to https://github.com/blog/1270-easier-builds-and-deployments-using-git-over-https-and-oauth, the username is the TOKEN and the password can be an empty string.

You can start your own config server using the Java samples or a Docker Container, which is shown below. I'm using the environment variables setup here, which you could do using regular shell and Java combo:

docker run -it -p 8888:8888 
  -e SPRING_CLOUD_CONFIG_SERVER_GIT_URI=https://github.mycompany.com/servicesplatform-tools/config.git
  -e SPRING_CLOUD_CONFIG_SERVER_GIT_USERNAME=389e3f300c9972d704b418c2310410ffc9f1499e 
  -e SPRING_CLOUD_CONFIG_SERVER_GIT_PASSWORD=  hyness/spring-cloud-config-server

NPE when password is not provided

Running without the Empty Password as string Fails the server with a NPE the first time it tries to clone the repo.

2016-06-03 06:32:39.388 ERROR 6 --- [nio-8888-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : 
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request 
processing failed; nested exception is java.lang.IllegalStateException: Cannot load environment] 
with root cause

java.lang.NullPointerException: null
    at org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider.<init>
(UsernamePasswordCredentialsProvider.java:65) ~[org.eclipse.jgit-3.5.3.201412180710-
r.jar!/:3.5.3.201412180710-r]
    at org.springframework.cloud.config.server.environment.JGitEnvironmentRepository.
setCredentialsProvider(JGitEnvironmentRepository.java:310) ~[spring-cloud-config-server-
1.1.0.RELEASE.jar!/:1.1.0.RELEASE]

Cheers 馃嵑 !

For those who are using config server inside a container.
Adding a:
ssh-keyscan -t rsa "git-address" >> ~/.ssh/known_hosts && to the beginning of your ENTRYPOINT solves the problem as it generates the know-hosts file in the expected format.

@fvztdk could you please elaborate a bit more?

ENTRYPOINT ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts
CMD ["java", "-jar", "config-server-0.0.1-SNAPSHOT.jar"]

leaves me with:
java: line 1: can't create /root/.ssh/known_hosts: nonexistent directory
java: line 1: ssh-keyscan: not found

@mahorad I assume your base image doesn't have ssh installed. If you are on debian based image (openjdk is) add:
RUN apt-get update && apt-get install -y ssh

Closing due to age of the question. If you would like us to look at this issue, please comment and we will look at re-opening the issue.

Was this page helpful?
0 / 5 - 0 ratings