This is an automated email from the ASF dual-hosted git repository. olamy pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/maven-scm.git
The following commit(s) were added to refs/heads/master by this push: new 9a3daee [SCM-832] maven-scm-provider-jgit should support SSH public key auth (#50) 9a3daee is described below commit 9a3daeeac48a4bf24df73627bc56c45071629834 Author: Martin Kutter <martin.kut...@fen-net.de> AuthorDate: Fri Dec 14 05:12:32 2018 +0100 [SCM-832] maven-scm-provider-jgit should support SSH public key auth (#50) * Support public key auth for SSH #SCM-832 Adds a TransportConfigCallback to all remote commands, which adds a public/private key based identity for repositories with ssh URLs if configured. * Updated documentation for #SCM-832 * [SCM-832] Updated documentation * [SCM-832] Added debug logging maven-scm-provider-jgit now outputs the private key used when run as mvn -X --- .../jgit/command/JGitTransportConfigCallback.java | 106 +++++++++++++++++++++ .../scm/provider/git/jgit/command/JGitUtils.java | 11 ++- .../jgit/command/checkout/JGitCheckOutCommand.java | 21 +++- .../git/jgit/command/list/JGitListCommand.java | 6 +- .../command/remoteinfo/JGitRemoteInfoCommand.java | 4 +- .../src/site/markdown/index.md.vm | 17 +++- 6 files changed, 153 insertions(+), 12 deletions(-) diff --git a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/JGitTransportConfigCallback.java b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/JGitTransportConfigCallback.java new file mode 100644 index 0000000..7b13af5 --- /dev/null +++ b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/JGitTransportConfigCallback.java @@ -0,0 +1,106 @@ +package org.apache.maven.scm.provider.git.jgit.command; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import com.jcraft.jsch.JSch; +import com.jcraft.jsch.JSchException; +import com.jcraft.jsch.Session; +import org.apache.maven.scm.log.ScmLogger; +import org.apache.maven.scm.provider.git.repository.GitScmProviderRepository; +import org.eclipse.jgit.api.TransportConfigCallback; +import org.eclipse.jgit.transport.*; +import org.eclipse.jgit.util.FS; +import org.eclipse.jgit.util.StringUtils; + +/** + * Implementation of {@link TransportConfigCallback} which adds + * a public/private key identity to ssh URLs if configured. + */ +public class JGitTransportConfigCallback implements TransportConfigCallback { + private SshSessionFactory sshSessionFactory = null; + + public JGitTransportConfigCallback(GitScmProviderRepository repo, ScmLogger logger) { + if (repo.getFetchInfo().getProtocol().equals("ssh")) { + if (!StringUtils.isEmptyOrNull(repo.getPrivateKey()) && repo.getPassphrase() == null) { + logger.debug("using private key with passphrase: " + repo.getPrivateKey()); + sshSessionFactory = new UnprotectedPrivateKeySessionFactory(repo); + } else if (!StringUtils.isEmptyOrNull(repo.getPrivateKey()) && repo.getPassphrase() != null) { + logger.debug("using private key: " + repo.getPrivateKey()); + sshSessionFactory = new ProtectedPrivateKeyFileSessionFactory(repo); + } else { + sshSessionFactory = new SimpleSessionFactory(); + } + } + } + + @Override + public void configure(Transport transport) { + if (transport instanceof SshTransport) { + SshTransport sshTransport = (SshTransport) transport; + sshTransport.setSshSessionFactory(sshSessionFactory); + } + } + + static private class SimpleSessionFactory extends JschConfigSessionFactory { + @Override + protected void configure(OpenSshConfig.Host host, Session session) { + } + } + + static private abstract class PrivateKeySessionFactory extends SimpleSessionFactory { + private final GitScmProviderRepository repo; + + public GitScmProviderRepository getRepo() { + return repo; + } + + public PrivateKeySessionFactory(GitScmProviderRepository repo) { + this.repo = repo; + } + } + + static private class UnprotectedPrivateKeySessionFactory extends PrivateKeySessionFactory { + + public UnprotectedPrivateKeySessionFactory(GitScmProviderRepository repo) { + super(repo); + } + + @Override + protected JSch createDefaultJSch(FS fs) throws JSchException { + JSch defaultJSch = super.createDefaultJSch(fs); + defaultJSch.addIdentity(getRepo().getPrivateKey()); + return defaultJSch; + } + } + + static private class ProtectedPrivateKeyFileSessionFactory extends PrivateKeySessionFactory { + + public ProtectedPrivateKeyFileSessionFactory(GitScmProviderRepository repo) { + super(repo); + } + + @Override + protected JSch createDefaultJSch(FS fs) throws JSchException { + JSch defaultJSch = super.createDefaultJSch(fs); + defaultJSch.addIdentity(getRepo().getPrivateKey(), getRepo().getPassphrase()); + return defaultJSch; + } + } +} diff --git a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/JGitUtils.java b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/JGitUtils.java index b6900b4..3e3a4f4 100644 --- a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/JGitUtils.java +++ b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/JGitUtils.java @@ -28,6 +28,7 @@ import org.apache.maven.scm.util.FilenameUtils; import org.codehaus.plexus.util.StringUtils; import org.eclipse.jgit.api.AddCommand; import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.PushCommand; import org.eclipse.jgit.api.Status; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.InvalidRemoteException; @@ -83,7 +84,7 @@ import java.util.Set; */ public class JGitUtils { - + private JGitUtils() { // no op @@ -178,6 +179,8 @@ public class JGitUtils return new UsernamePasswordCredentialsProvider( repository.getUser().trim(), repository.getPassword().trim() ); } + + return null; } @@ -185,8 +188,10 @@ public class JGitUtils throws GitAPIException, InvalidRemoteException, TransportException { CredentialsProvider credentials = JGitUtils.prepareSession( logger, git, repo ); - Iterable<PushResult> pushResultList = - git.push().setCredentialsProvider( credentials ).setRefSpecs( refSpec ).call(); + PushCommand command = git.push().setRefSpecs(refSpec).setCredentialsProvider(credentials) + .setTransportConfigCallback(new JGitTransportConfigCallback(repo, logger)); + + Iterable<PushResult> pushResultList = command.call(); for ( PushResult pushResult : pushResultList ) { Collection<RemoteRefUpdate> ru = pushResult.getRemoteUpdates(); diff --git a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/checkout/JGitCheckOutCommand.java b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/checkout/JGitCheckOutCommand.java index b89299a..ea1f1dd 100644 --- a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/checkout/JGitCheckOutCommand.java +++ b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/checkout/JGitCheckOutCommand.java @@ -30,13 +30,13 @@ import org.apache.maven.scm.command.checkout.CheckOutScmResult; import org.apache.maven.scm.command.remoteinfo.RemoteInfoScmResult; import org.apache.maven.scm.provider.ScmProviderRepository; import org.apache.maven.scm.provider.git.command.GitCommand; +import org.apache.maven.scm.provider.git.jgit.command.JGitTransportConfigCallback; import org.apache.maven.scm.provider.git.jgit.command.JGitUtils; import org.apache.maven.scm.provider.git.jgit.command.branch.JGitBranchCommand; import org.apache.maven.scm.provider.git.jgit.command.remoteinfo.JGitRemoteInfoCommand; import org.apache.maven.scm.provider.git.repository.GitScmProviderRepository; import org.codehaus.plexus.util.StringUtils; -import org.eclipse.jgit.api.CloneCommand; -import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.*; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ProgressMonitor; import org.eclipse.jgit.revwalk.RevCommit; @@ -109,7 +109,13 @@ public class JGitCheckOutCommand CredentialsProvider credentials = JGitUtils.getCredentials( (GitScmProviderRepository) repo ); getLogger().info( "cloning [" + branch + "] to " + fileSet.getBasedir() ); CloneCommand command = Git.cloneRepository().setURI( repository.getFetchUrl() ); + command.setCredentialsProvider( credentials ).setBranch( branch ).setDirectory( fileSet.getBasedir() ); + + TransportConfigCallback transportConfigCallback = new JGitTransportConfigCallback( + (GitScmProviderRepository) repo, getLogger()); + command.setTransportConfigCallback(transportConfigCallback); + command.setProgressMonitor( monitor ); git = command.call(); } @@ -129,6 +135,8 @@ public class JGitCheckOutCommand { // git repo exists, so we must git-pull the changes CredentialsProvider credentials = JGitUtils.prepareSession( getLogger(), git, repository ); + TransportConfigCallback transportConfigCallback = new JGitTransportConfigCallback( + (GitScmProviderRepository) repo, getLogger()); if ( version != null && StringUtils.isNotEmpty( version.getName() ) && ( version instanceof ScmTag ) ) { @@ -138,12 +146,17 @@ public class JGitCheckOutCommand // In fact, a tag in git may be in multiple branches. This occurs if // you create a branch after the tag has been created getLogger().debug( "fetch..." ); - git.fetch().setCredentialsProvider( credentials ).setProgressMonitor( monitor ).call(); + FetchCommand command = git.fetch().setCredentialsProvider(credentials).setProgressMonitor(monitor); + command.setTransportConfigCallback(transportConfigCallback); + command.call(); + } else { getLogger().debug( "pull..." ); - git.pull().setCredentialsProvider( credentials ).setProgressMonitor( monitor ).call(); + PullCommand command = git.pull().setCredentialsProvider(credentials).setProgressMonitor(monitor); + command.setTransportConfigCallback(transportConfigCallback); + command.call(); } } diff --git a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/list/JGitListCommand.java b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/list/JGitListCommand.java index ef86c09..937fa1d 100644 --- a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/list/JGitListCommand.java +++ b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/list/JGitListCommand.java @@ -28,6 +28,7 @@ import org.apache.maven.scm.command.list.AbstractListCommand; import org.apache.maven.scm.command.list.ListScmResult; import org.apache.maven.scm.provider.ScmProviderRepository; import org.apache.maven.scm.provider.git.command.GitCommand; +import org.apache.maven.scm.provider.git.jgit.command.JGitTransportConfigCallback; import org.apache.maven.scm.provider.git.jgit.command.JGitUtils; import org.apache.maven.scm.provider.git.repository.GitScmProviderRepository; import org.eclipse.jgit.api.Git; @@ -61,7 +62,10 @@ public class JGitListCommand JGitUtils.prepareSession( getLogger(), git, (GitScmProviderRepository) repo ); List<ScmFile> list = new ArrayList<ScmFile>(); - Collection<Ref> lsResult = git.lsRemote().setCredentialsProvider( credentials ).call(); + Collection<Ref> lsResult = git.lsRemote().setCredentialsProvider( credentials ) + .setTransportConfigCallback( + new JGitTransportConfigCallback((GitScmProviderRepository) repo, getLogger())) + .call(); for ( Ref ref : lsResult ) { getLogger().debug( ref.getObjectId().getName() + " " + ref.getTarget().getName() ); diff --git a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/remoteinfo/JGitRemoteInfoCommand.java b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/remoteinfo/JGitRemoteInfoCommand.java index b521b0b..451be02 100644 --- a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/remoteinfo/JGitRemoteInfoCommand.java +++ b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/remoteinfo/JGitRemoteInfoCommand.java @@ -26,6 +26,7 @@ import org.apache.maven.scm.command.remoteinfo.AbstractRemoteInfoCommand; import org.apache.maven.scm.command.remoteinfo.RemoteInfoScmResult; import org.apache.maven.scm.provider.ScmProviderRepository; import org.apache.maven.scm.provider.git.command.GitCommand; +import org.apache.maven.scm.provider.git.jgit.command.JGitTransportConfigCallback; import org.apache.maven.scm.provider.git.jgit.command.JGitUtils; import org.apache.maven.scm.provider.git.repository.GitScmProviderRepository; import org.eclipse.jgit.api.Git; @@ -61,7 +62,8 @@ public class JGitRemoteInfoCommand CredentialsProvider credentials = JGitUtils.getCredentials( repo ); LsRemoteCommand lsCommand = - git.lsRemote().setRemote( repo.getPushUrl() ).setCredentialsProvider( credentials ); + git.lsRemote().setRemote( repo.getPushUrl() ).setCredentialsProvider( credentials ) + .setTransportConfigCallback(new JGitTransportConfigCallback(repo, getLogger())); Map<String, String> tag = new HashMap<String, String>(); Collection<Ref> allTags = lsCommand.setHeads( false ).setTags( true ).call(); diff --git a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/site/markdown/index.md.vm b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/site/markdown/index.md.vm index d95a1a6..b64b7af 100644 --- a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/site/markdown/index.md.vm +++ b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/site/markdown/index.md.vm @@ -20,8 +20,9 @@ under the License. maven-scm-provider-jgit === -This scm provider implementation allows the usage of git with the release and scm plugin without having to install a nativ git client. -This implementation uses username and password instead of a public/private keys to authenticate the requests to a remote repository like GitHub. +This scm provider implementation allows the usage of git with the release and scm plugin without having to install a native git client. +This implementation can use both username and password, or public/private keys to authenticate the requests to a remote +repository like GitHub. At the moment, public/private keys are only supported for SSH access. Configuration --- @@ -65,7 +66,17 @@ Usage with the `maven-scm-plugin` </dependency> </dependencies> </plugin> - + +Public/private key configuration in settings.xml - for use with ssh URLs like ssh://g...@github.com/apache/maven-scm + + <servers> + <server> + <id>g...@github.com</id> + <privateKey>path/to/private/key</privateKey> + <passphrase>private key passphrase</passphrase> + </server> + <server> + Examples ____