Jenkins git plugin SSL验证修复

最近在将Jenkins内部使用的git和git client两个plugin分别升级到2.2(from 1.4), 1.9.1以后,git plugin 用https访问 git repo报错:

> git --version
using GIT_SSH to set credentials 
ERROR: Error cloning remote repo 'origin'
hudson.plugins.git.GitException: com.ibm.jsse2.util.j: PKIX path building failed: java.security.cert.CertPathBuilderException: PKIXCertPathBuilderImpl could not build a valid CertPath.; internal cause is: 
	java.security.cert.CertPathValidatorException: The certificate issued by CN=IBM Internal Root CA, O=International Business Machines Corporation, C=US is not trusted; internal cause is: 
	java.security.cert.CertPathValidatorException: Certificate chaining error
	at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.checkCredentials(CliGitAPIImpl.java:1982)
	at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.launchCommandWithCredentials(CliGitAPIImpl.java:1143)
	at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.access$200(CliGitAPIImpl.java:87)
	at org.jenkinsci.plugins.gitclient.CliGitAPIImpl$1.execute(CliGitAPIImpl.java:257)
	at org.jenkinsci.plugins.gitclient.CliGitAPIImpl$2.execute(CliGitAPIImpl.java:413)
	at org.jenkinsci.plugins.gitclient.RemoteGitImpl$CommandInvocationHandler$1.call(RemoteGitImpl.java:153)
	at org.jenkinsci.plugins.gitclient.RemoteGitImpl$CommandInvocationHandler$1.call(RemoteGitImpl.java:146)
	at hudson.remoting.UserRequest.perform(UserRequest.java:118)
	at hudson.remoting.UserRequest.perform(UserRequest.java:48)
	at hudson.remoting.Request$2.run(Request.java:326)
	at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:72)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:314)
	at java.util.concurrent.FutureTask.run(FutureTask.java:149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:906)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:929)
	at java.lang.Thread.run(Thread.java:761)

研究以后有以下发现:
1. Jenkins git plugin依赖git client plugin做git clone等操作,git clent plugin也提供给gerrit plugin有关git操作。
2. git client对git的操作有两种类型,一种是所谓的command line(cli),会依赖jenkins机器上安装的git客户端程序(至少是1.7.9.0);另外一种是JGit,是用Java实现了所有git的操作。默认为cli方式,也可以配置成JGit方式。
3. 目前访问的git server repo提供的证书为自签名的(self certificate),以上报错来自java ssl验证。如果要解决ssl验证问题,需要将证书导入到 jre/lib/serurity/cacerts中,具体命令为
keytool –import –keystore jre/lib/security/cacerts –alias “my github” –file mygithub.cert
4. git client提供了untrusted ssl (ignore ssl check)的方式,即在启动jenkins时候传入-Dorg.jenkinsci.plugins.gitclient.GitClient.untrustedSSL=true,具体做法为

1) vi /etc/default/Jenkins; 

Jenkins git plugin SSL验证修复_第1张图片

2) /etc/init.d/Jenkins restart,记住对采用master-slave结构的jenkins cluster环境Jenkins slave也需要加入该选项支持

Jenkins git plugin SSL验证修复_第2张图片

5. 发现即使enable untrustedSSL还是报错,研究后发现这是jenkins client的一个bug(见https://issues.jenkins-ci.org/browse/JENKINS-22675 )
修复之前

if(acceptSelfSignedCertificates && "https".equalsIgnoreCase(u.getScheme())) {           
 final SSLContextBuilder contextBuilder = SSLContexts.custom();
            try {
                contextBuilder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
            } catch (NoSuchAlgorithmException e) {
                throw new GitException(e.getLocalizedMessage(), e);
            } catch (KeyStoreException e) {
                throw new GitException(e.getLocalizedMessage(), e);
            }
            SSLContext sslContext = null;
            try {
                sslContext = contextBuilder.build();
            } catch (KeyManagementException e) {
                throw new GitException(e.getLocalizedMessage(), e);
            } catch (NoSuchAlgorithmException e) {
                throw new GitException(e.getLocalizedMessage(), e);
            }
            clientBuilder.setSslcontext(sslContext);
        }
修复之后:

if(acceptSelfSignedCertificates && "https".equalsIgnoreCase(u.getScheme())) {           
 final SSLContextBuilder contextBuilder = SSLContexts.custom();
            try {
                contextBuilder.loadTrustMaterial(null, new TrustStrategy() {
				@Override
				public boolean isTrusted(X509Certificate[] chain, String authType)
						throws CertificateException {
					return true;
				}
			}););
            } catch (NoSuchAlgorithmException e) {
                throw new GitException(e.getLocalizedMessage(), e);
            } catch (KeyStoreException e) {
                throw new GitException(e.getLocalizedMessage(), e);
            }
            SSLContext sslContext = null;
            try {
                sslContext = contextBuilder.build();
            } catch (KeyManagementException e) {
                throw new GitException(e.getLocalizedMessage(), e);
            } catch (NoSuchAlgorithmException e) {
                throw new GitException(e.getLocalizedMessage(), e);
            }
            clientBuilder.setSslcontext(sslContext);
        }

/**
 * A trust strategy that accepts self-signed certificates as trusted. Verification of all other
 * certificates is done by the trust manager configured in the SSL context.
 *
 * @since 4.1
 */
public class TrustSelfSignedStrategy implements TrustStrategy {

    public boolean isTrusted(
            final X509Certificate[] chain, final String authType) throws CertificateException {
        return chain.length == 1;
    }

}

下来git client plugin是host在github上的一个按照maven组织的项目,以下是重新build出来hpi(jpi)的过程

git clone htpps://github.com/jenkinsci/git-client-plugin
git checkout git-client-1.9.1 
mvn compile
mvn package


总结下来,如果想继续使用 https访问github,要不将ssl certificate加入java keystore,要不enbale unstrust ssl 并修掉该bug.
另一种方式是改为用 ssh协议(对于有写操作要求的job,例如自动打tag这是首选)

下面是配置ssh方式的步骤:

1.新建credential并填入private key

Jenkins git plugin SSL验证修复_第3张图片

2.在需要访问的git project中enble jenknis_deploy的deployment key.(实际上是public key)

Jenkins git plugin SSL验证修复_第4张图片

3.配置jenkins job 中的git plugin使用该pirvate key和ssh协议

Jenkins git plugin SSL验证修复_第5张图片

你可能感兴趣的:(devops)