Reputation: 18809
I am trying to a clone of a Git Repository via the CloneCommand
.
With this piece of code
`Git.cloneRepository().setDirectory(new File(path)).setURI(url).call();`
The remote repository is on a GitBlit Instance which uses self signed certificates. Because of these self signed certificates I get the below exception when the Fetch Part of the Clone is executing:
Caused by: java.security.cert.CertificateException: No name matching <hostName> found
at sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:221)
at sun.security.util.HostnameChecker.match(HostnameChecker.java:95)
While I could create a new TrustManager
, register a dummy HostnameVerifier
and create and init a SSLContext
that uses this dummy TrustManager
.
And after the clone is done revert all of this.
However this would mean that any other SSL connection that is initiated during the same time would expose them to unsecured connections.
On a already cloned repo you can set the http.sslVerify to false and JGit works perfectly fine.
Is there a cleaner way in which I could tell JGit to set this http.sslVerify to false for Clone action, like I can do for a already cloned repo.
Upvotes: 13
Views: 12795
Reputation: 51
This is an example of implementing manual steps to clone repository from this answer by Rüdiger Herrmann
Git git = Git.init()
.setDirectory(new File(localRepoFullPath))
.setBare(false)
.call();
git.remoteAdd()
.setUri(new URIish(repoRemotePath)).setName("origin")
.call();
StoredConfig config = git.getRepository().getConfig();
// here set sslVerify = false
config.setBoolean( "http", null, "sslVerify", false );
// http.sslCAInfo,sslCAPath,sslCert,sslKey sections are not parsed by JGit
// more details here - https://stackoverflow.com/questions/75951655/mtls-mutual-tls-with-jgit
config.setString("http",null,"sslCAInfo" , gitMTLSProperties.getServerCertificatePath());
config.setString("http",null,"sslCAPath" , gitMTLSProperties.getServerCertificatePath());
config.setString("http",null,"sslCert" , gitMTLSProperties.getClientCertificatePath());
config.setString("http",null,"sslKey" , gitMTLSProperties.getClientKeyPath());
config.save();
git.checkout()
.setCredentialsProvider(new UsernamePasswordCredentialsProvider("token", pat))
.setCreateBranch(true)
.setName("master")
.setUpstreamMode(CreateBranchCommand.SetupUpstreamMode.TRACK)
.setStartPoint("origin/master")
.call();
There is another way.
This is an alternative implementation example of disabling SSL verification
through own CredentialsProvider
from this answer
by Milinda Kasun
public class MyOwnCredentialsProvider extends CredentialsProvider {
@SneakyThrows
public String getLogin() {
// getting your login
return myLogin;
}
@SneakyThrows
private String getPass() {
// getting your pass
return myPass;
}
@Override
public boolean isInteractive() {
return false;
}
@Override
public boolean supports(CredentialItem... items) {
JGitText jGitText = JGitText.get();
for (CredentialItem i : items) {
if (i instanceof CredentialItem.Username)
continue;
else if (i instanceof CredentialItem.Password)
continue;
else {
if (i instanceof CredentialItem.InformationalMessage &&
i.getPromptText().contains(jGitText.sslFailureTrustExplanation)) {
continue;
} else if (i instanceof CredentialItem.YesNoType
&& (i.getPromptText().contains(jGitText.sslTrustNow)
|| i.getPromptText().contains(jGitText.sslTrustForRepo.substring(0, jGitText.sslTrustForRepo.length()-3))
|| i.getPromptText().contains(jGitText.sslTrustAlways)))
continue;
else
return false;
}
}
return true;
}
@Override
public boolean get(URIish uri, CredentialItem... items)
throws UnsupportedCredentialItem {
JGitText jGitText = JGitText.get();
for (CredentialItem i : items) {
if (i instanceof CredentialItem.Username) {
((CredentialItem.Username) i).setValue(getLogin());
continue;
}
if (i instanceof CredentialItem.Password) {
((CredentialItem.Password) i).setValue(getPass().toCharArray());
continue;
}
if (i instanceof CredentialItem.StringType) {
if (i.getPromptText().equals("Password: ")) {
((CredentialItem.StringType) i).setValue(getPass());
continue;
}
}
if (i instanceof CredentialItem.InformationalMessage &&
i.getPromptText().contains(jGitText.sslFailureTrustExplanation))
continue;
if (i instanceof CredentialItem.YesNoType) {
if (i.getPromptText().contains(jGitText.sslTrustNow)) {
//set "true" for "Skip SSL verification for this single git operation".
//You can set "true" to any of the questions:
// * "Do you want to skip SSL verification for this server?"
// * "Skip SSL verification for git operations for repository {0}"
// * "Always skip SSL verification for this server from now on"
//see file JGitText.properties
((CredentialItem.YesNoType) i).setValue(true);
continue;
} else if (i.getPromptText().contains(jGitText.sslTrustForRepo.substring(0, jGitText.sslTrustForRepo.length()-3))
|| i.getPromptText().contains(jGitText.sslTrustAlways))
continue;
}
throw new UnsupportedCredentialItem(uri, i.getClass().getName()
+ ":" + i.getPromptText());
}
return true;
}
}
And in the step of cloning the repository, add your provider MyOwnCredentialsProvider
Git git = Git.cloneRepository()
.setURI(repoRemotePath)
.setDirectory(new File(localRepoFullPath))
.setCloneAllBranches(true)
.setBranch("master")
.setCredentialsProvider(new MyOwnCredentialsProvider())
.call();
Upvotes: 2
Reputation: 75
I have come across with the same problem and I used ChainingCredentialsProvider
class to create a credential provider, I did my implementation as bellow,
Please note that this is an implementation of a previously given answer.
CredentialsProvider token = new UsernamePasswordCredentialsProvider("PRIVATE-TOKEN", token);
CredentialsProvider ssl = new CredentialsProvider() {
@Override
public boolean supports(CredentialItem... items) {
for ( CredentialItem item : items ) {
if ( (item instanceof CredentialItem.YesNoType) ) {
return true;
}
}
return false;
}
@Override
public boolean get(URIish uri, CredentialItem... items) throws UnsupportedCredentialItem {
for ( CredentialItem item : items ) {
if ( item instanceof CredentialItem.YesNoType ) {
(( CredentialItem.YesNoType ) item).setValue(true);
return true;
}
}
return false;
}
@Override
public boolean isInteractive() {
return false;
}
};
CredentialsProvider cp = new ChainingCredentialsProvider(ssl, token);
Git result = Git.cloneRepository()
.setURI(gitProjectUrl)
.setDirectory(localPath)
.setCredentialsProvider(cp)
.call();
Upvotes: 1
Reputation: 20985
With version 4.9, JGit will handle SSL verification more gracefully. If the SSL
handshake was unsuccessful, JGit will ask the CredentialsProvider
whether SSL verification should be skipped or not.
In this process, the CredentialsProvider
is given an InformationalMessage
describing the issue textually and up to three YesNoType
CredentialItem
s to decide whether to skip SSL verification for this operation, for the current repository, and/or always.
It seems that the change was made with an interactive UI in mind and it might be hard to answer these 'credential requests' programmatically. The commit message of this change describes the behavior in more detail.
If you are certain that SSL verification is the only InformationalMessage
that will be sent, you can apply the technique used in this test that accompanies the change and blindly answer 'yes' to all such questions.
For earlier versions of JGit, or if the CredentialsProvider
model does not fit your needs, there are two workarounds described below.
To work around this limitation, you can execute the specific clone steps manually as suggested in the comments below:
StoredConfig config = git.getRepository().getConfig();
config.setBoolean( "http", null, "sslVerify", false );
config.save();
Another way to work around the issue is to provide an HttpConnectionFactory
that returns HttpConnection
s with dummy host name and certificate verifiers. For example:
class InsecureHttpConnectionFactory implements HttpConnectionFactory {
@Override
public HttpConnection create( URL url ) throws IOException {
return create( url, null );
}
@Override
public HttpConnection create( URL url, Proxy proxy ) throws IOException {
HttpConnection connection = new JDKHttpConnectionFactory().create( url, proxy );
HttpSupport.disableSslVerify( connection );
return connection;
}
}
HttpConnection
is in package org.eclipse.jgit.transport.http
and is a JGit abstraction for HTTP connections. While the example uses the default implementation (backed by JDK http code), you are free to use your own implementation or the one provided by the org.eclipse.jgit.transport.http.apache
package that uses Apache http components.
The currently used connection factory can be changed with HttpTransport::setConnectionFactory()
:
HttpConnectionFactory preservedConnectionFactory = HttpTransport.getConnectionFactory();
HttpTransport.setConnectionFactory( new InsecureHttpConnectionFactory() );
// clone repository
HttpTransport.setConnectionFactory( preservedConnectionFactory );
Unfortunately, the connection factory is a singleton so that this trick needs extra work (e.g. a thread local variable to control if sslVerify is on or off) when JGit commands are executed concurrently.
Upvotes: 9
Reputation: 637
I have inferred from all answers above for the snippet below;
private void disableSSLVerify(URI gitServer) throws Exception {
if (gitServer.getScheme().equals("https")) {
FileBasedConfig config = SystemReader.getInstance().openUserConfig(null, FS.DETECTED);
synchronized (config) {
config.load();
config.setBoolean(
"http",
"https://" + gitServer.getHost() + ':' + (gitServer.getPort() == -1 ? 443 : gitServer.getPort()),
"sslVerify", false);
config.save();
}
}
}
This option is safer because it allows sslVerify to false for the gitServer
alone.
Please take a look at this link which shares other options.
Upvotes: 1
Reputation: 319
Another workaround is to create a .gitconfig
file in the home of the current user before calling Git.cloneRepository()
:
File file = new File(System.getProperty("user.home")+"/.gitconfig");
if(!file.exists()) {
PrintWriter writer = new PrintWriter(file);
writer.println("[http]");
writer.println("sslverify = false");
writer.close();
}
This will make JGit skip SSL certificate verification.
Upvotes: 8