如何在 Spring Cloud Config 中使用自定义 ssh 密钥位置

Posted

技术标签:

【中文标题】如何在 Spring Cloud Config 中使用自定义 ssh 密钥位置【英文标题】:How to use a custom ssh key location with Spring Cloud Config 【发布时间】:2016-02-21 05:57:54 【问题描述】:

我正在尝试设置一个Spring Cloud Config 服务器,该服务器使用自定义位置作为 ssh 私钥。 我需要为密钥指定自定义位置的原因是因为运行应用程序的用户没有主目录..所以我无法为我的密钥使用默认的~/.ssh 目录。 我知道可以选择创建只读帐户并在配置中提供用户/密码,但 ssh 方式接缝更干净。有什么方法可以设置吗?

【问题讨论】:

【参考方案1】:

@Jeffrey Zampieron 的FixedSshSessionFactory 解决方案很好。但是,如果将 spring boot 应用程序打包为 fat jar,它将不起作用。

稍微打磨一下,以便使用胖罐,

/**
 * @file FixedSshSessionFactory.java
 * @date Aug 23, 2016 2:16:11 PM
 * @author jzampieron
 */

import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.jgit.transport.JschConfigSessionFactory;
import org.eclipse.jgit.transport.OpenSshConfig.Host;
import org.eclipse.jgit.util.FS;
import org.springframework.util.StreamUtils;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

/**
 * Short Desc Here.
 *
 * @author jzampieron
 */
@Slf4j
public class FixedSshSessionFactory extends JschConfigSessionFactory 

    protected URL[] identityKeyURLs;

    /**
     * @param url
     */
    public FixedSshSessionFactory(URL... identityKeyURLs) 
        this.identityKeyURLs = identityKeyURLs;
    

    /* (non-Javadoc)
     * @see org.eclipse.jgit.transport.JschConfigSessionFactory#configure(org.eclipse.jgit.transport.OpenSshConfig.Host, com.jcraft.jsch.Session)
     */
    @Override
    protected void configure(Host hc, Session session) 
        // nothing special needed here.
    

    /* (non-Javadoc)
     * @see org.eclipse.jgit.transport.JschConfigSessionFactory#getJSch(org.eclipse.jgit.transport.OpenSshConfig.Host, org.eclipse.jgit.util.FS)
     */
    @Override
    protected JSch getJSch(Host hc, FS fs) throws JSchException 
        JSch jsch = super.getJSch(hc, fs);
        // Clean out anything 'default' - any encrypted keys
        // that are loaded by default before this will break.
        jsch.removeAllIdentity();
        int count = 0;
        for (final URL identityKey : identityKeyURLs) 
            try (InputStream stream = identityKey.openStream()) 
                jsch.addIdentity("key" + ++count, StreamUtils.copyToByteArray(stream), null, null);
             catch (IOException e) 
                logger.error("Failed to load identity " + identityKey.getPath());
            
        
        return jsch;
    



【讨论】:

【参考方案2】:

阅读更多代码后...我发现了一个相对简单的解决方法,允许您设置所需的任何 SSH 密钥。

首先:创建一个类,如下:

/**
 * @file FixedSshSessionFactory.java 
 * 
 * @date Aug 23, 2016 2:16:11 PM 
 * @author jzampieron
 */

import org.eclipse.jgit.transport.JschConfigSessionFactory;
import org.eclipse.jgit.transport.OpenSshConfig.Host;
import org.eclipse.jgit.util.FS;

import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

/**
 * Short Desc Here.
 * 
 * @author jzampieron
 *
 */
public class FixedSshSessionFactory extends JschConfigSessionFactory


   protected String[] identityKeyPaths;

   /**
    * @param string
    */
   public FixedSshSessionFactory( String... identityKeyPaths )
   
      this.identityKeyPaths = identityKeyPaths;
   

   /* (non-Javadoc)
    * @see org.eclipse.jgit.transport.JschConfigSessionFactory#configure(org.eclipse.jgit.transport.OpenSshConfig.Host, com.jcraft.jsch.Session)
    */
   @Override
   protected void configure( Host hc, Session session )
   
      // nothing special needed here.
   

   /* (non-Javadoc)
    * @see org.eclipse.jgit.transport.JschConfigSessionFactory#getJSch(org.eclipse.jgit.transport.OpenSshConfig.Host, org.eclipse.jgit.util.FS)
    */
   @Override
   protected JSch getJSch( Host hc, FS fs ) throws JSchException
   
      JSch jsch = super.getJSch( hc, fs );
      // Clean out anything 'default' - any encrypted keys
      // that are loaded by default before this will break.
      jsch.removeAllIdentity();
      for( final String identKeyPath : identityKeyPaths )
      
         jsch.addIdentity( identKeyPath );
      
      return jsch;
   



然后用jgit注册:

...
import org.eclipse.jgit.transport.SshSessionFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;

@SpringBootApplication
@EnableConfigServer
public class ConfigserverApplication 


    public static void main(String[] args) 
       URL res = ConfigserverApplication.class.getClassLoader().getResource( "keys/id_rsa" );
       String path = res.getPath();
       SshSessionFactory.setInstance( new FixedSshSessionFactory( path ) );

       SpringApplication.run(ConfigserverApplication.class, args);
    


对于这个示例,我将密钥存储在 src/main/resources/keys 文件夹中,并且 我正在使用类加载器来获取它们。

removeAllIdentities 很重要 b/c JSch 在我指定的密钥之前加载了我的默认 ssh 密钥,然后 Spring Cloud 崩溃了 b/c 它的加密。

这使我能够成功地使用 bitbucket 进行身份验证。

【讨论】:

谢谢。希望SB以后加个配置。【参考方案3】:

我遇到了类似的问题,因为我的默认 SSH 密钥是用密码加密的,因此不能“正常工作”,这是有道理的,因为这是一个无头设置。

我在 Spring Cloud Config org.eclipse.jgit 中进行了源代码研究,最终进入了 com.jcraft.jsch。简短的回答是 JGit 和 Spring Cloud 都没有公开明显的方法来做到这一点。

JSch 显然在 JSch() 实例中支持此功能,但您无法从 Spring Cloud 级别获得它。至少不是一个小时左右就能找到的。

【讨论】:

以上是关于如何在 Spring Cloud Config 中使用自定义 ssh 密钥位置的主要内容,如果未能解决你的问题,请参考以下文章

如何获取 Spring-Cloud-Config-Server 管理的文件列表

如何在 Spring Cloud Config 中使用自定义 ssh 密钥位置

如何使用 spring-cloud-starter-config 传递 X-Config-Token

如何从 Spring Cloud Config Server 读取多个配置文件

spring cloud config如何使用本地属性覆盖远程属性

Spring Boot + Spring Cloud Config - 如何从 Git 外部配置添加更多配置文件