You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@maven.apache.org by GitBox <gi...@apache.org> on 2018/12/14 04:12:34 UTC

[GitHub] olamy closed pull request #50: [SCM-832] maven-scm-provider-jgit should support SSH public key auth

olamy closed pull request #50: [SCM-832]  maven-scm-provider-jgit should support SSH public key auth
URL: https://github.com/apache/maven-scm/pull/50
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

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 000000000..7b13af58a
--- /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 d530d9ca0..fa6659f63 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.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 @@
  */
 public class JGitUtils
 {
-    
+
     private JGitUtils()
     {
         // no op
@@ -178,6 +179,8 @@ public static CredentialsProvider getCredentials( GitScmProviderRepository repos
             return new UsernamePasswordCredentialsProvider( repository.getUser().trim(),
                                                             repository.getPassword().trim() );
         }
+
+
         return null;
     }
 
@@ -185,8 +188,10 @@ public static CredentialsProvider getCredentials( GitScmProviderRepository repos
         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 178230c47..546ce6c0b 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.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 @@ protected CheckOutScmResult executeCheckOutCommand( ScmProviderRepository repo,
                 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 @@ protected CheckOutScmResult executeCheckOutCommand( ScmProviderRepository repo,
             {
                 // 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 @@ protected CheckOutScmResult executeCheckOutCommand( ScmProviderRepository repo,
                     // 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 ef86c0964..937fa1d73 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.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 @@ protected ListScmResult executeListCommand( ScmProviderRepository repo, ScmFileS
                 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 b521b0b4f..451be0254 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.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 RemoteInfoScmResult executeRemoteInfoCommand( ScmProviderRepository repos
             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 d95a1a6fc..b64b7af4d 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://git@github.com/apache/maven-scm
+
+			<servers>
+				<server>
+				    <id>git@github.com</id>
+				    <privateKey>path/to/private/key</privateKey>
+				    <passphrase>private key passphrase</passphrase>
+				</server>
+			<server>
+
 Examples
 ____
 


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services