Jenkins git plugin self signed certificate

2020-07-24 10:33发布

问题:

I'm currently trying to get Jenkins to build projects hosted in a GitHub enterprise repository. We are using a self signed certificate for the GitHub server which leads to some problems.

Most of those problems I was able to solve:

git command line:
Get the certificate in PEM format and teach git to look for information using the .config file:

[http "https://github.*******************.com"]
    sslCAInfo = "path\\to\\selvSignedCerts\\fileName.pem"
    sslCAPath = "path\\to\\selvSignedCerts\\"
    sslVerify = true

Jenkins GitHub plugin:
Add the certificate information to the java cacerts keystore:

keytool -import -trustcacerts -alias myAlias 
   -keystore "%JenkinsInstallDir\jre\lib\security\cacerts"
   -file "myCertsInfo.pem"

Restarting Jenkins after importing the information to the keystore finally did the trick so I was able to configure the GitHub Enterprise server in
Manage Jenkins -> Configure System -> GitHub Enterprise Servers -> API Endpoint

This configuration formerly was not possible due to:

SSL certificate problem: self signed certificate in certificate chain

Now, my git command-line is happy, the GitHub plugin in Jenkins is happy, which means Jenkins itself is happy but the git-client plugin is obviously not.

I've created a GitHub Organizations job in jenkins, specifying the link to the organization on the enterprise server. The configuration uses the API endpoint configured in the global jenkins settings, using configured credentials and looking for a pipeline file with the default name Jenkinsfile

The job is able to perform a checkout, it recognizes two branches, and in each branch finds the corresponding Jenkinsfile. It also automatically created a new job for each branch using the Jenkinsfile config.

The jenkinsfile currently looks like this:

#!/usr/bin/env groovy

pipeline {
  agent any
  stages {
    stage('Scan for new jobs') {
      steps {
        echo 'Scanning...'
      }
    }
    stage('Build') {
      steps {
        echo 'Build'
      }
    }
  }
}

Now the first step in the pipeline is an implicit scm checkout. This fails and the output looks like this:

14:01:27 Connecting to https://github.*********.com/api/v3 using <userId>/******
Obtained Jenkinsfile from <commitHash>
[Pipeline] node
Running on Jenkins in D:\****\Jenkins\****\workspace\****
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Declarative: Checkout SCM)
[Pipeline] checkout
 > C:\Program Files\Git\bin\git.exe rev-parse --is-inside-work-tree # timeout=10
Fetching changes from the remote Git repository
 > C:\Program Files\Git\bin\git.exe config remote.origin.url https://github.****.com/***/***.git # timeout=10
Fetching without tags
Fetching upstream changes from https://github.****.com/***/***.git
 > C:\Program Files\Git\bin\git.exe --version # timeout=10
using GIT_ASKPASS to set credentials 
 > C:\Program Files\Git\bin\git.exe fetch --no-tags --progress https://github.****.com/***/***.git +refs/heads/develop:refs/remotes/origin/develop
ERROR: Error fetching remote repo 'origin'
hudson.plugins.git.GitException: Failed to fetch from https://github.****.com/***/***.git
    at hudson.plugins.git.GitSCM.fetchFrom(GitSCM.java:825)
    at hudson.plugins.git.GitSCM.retrieveChanges(GitSCM.java:1092)
    at hudson.plugins.git.GitSCM.checkout(GitSCM.java:1123)
    at org.jenkinsci.plugins.workflow.steps.scm.SCMStep.checkout(SCMStep.java:113)
    at org.jenkinsci.plugins.workflow.steps.scm.SCMStep$StepExecutionImpl.run(SCMStep.java:85)
    at org.jenkinsci.plugins.workflow.steps.scm.SCMStep$StepExecutionImpl.run(SCMStep.java:75)
    at org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution$1$1.call(AbstractSynchronousNonBlockingStepExecution.java:47)
    at hudson.security.ACL.impersonate(ACL.java:260)
    at org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution$1.run(AbstractSynchronousNonBlockingStepExecution.java:44)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: hudson.plugins.git.GitException: Command "C:\Program Files\Git\bin\git.exe fetch --no-tags --progress https://github.****.com/***/***.git +refs/heads/develop:refs/remotes/origin/develop" returned status code 128:
stdout: 
stderr: fatal: unable to access 'https://github.****.com/***/***.git/': SSL certificate problem: self signed certificate in certificate chain

    at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.launchCommandIn(CliGitAPIImpl.java:1970)
    at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.launchCommandWithCredentials(CliGitAPIImpl.java:1689)
    at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.access$300(CliGitAPIImpl.java:71)
    at org.jenkinsci.plugins.gitclient.CliGitAPIImpl$1.execute(CliGitAPIImpl.java:380)
    at hudson.plugins.git.GitSCM.fetchFrom(GitSCM.java:823)
    ... 13 more
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline

So the error is again:

stderr: fatal: unable to access 'https://github.****.com/***/***.git/': SSL certificate problem: self signed certificate in certificate chain

Now it seems, that the git-client plugin (or the git plugin?) seem to look somewhere else than to the keystore at lib\security\cacerts and also don't seem to care about the .gitconfig file.

Now my question is, where will this plugin look for valid certificates? or is there anything else I didn't get?

All research for this, or similar issues, all leads to adding the certificate to the java keystore, which I already did. I didn't find any other information pointing to the right direction. And mostly I'm wondering, why the GitHub Organizations job can handle the repository well, detect all branches, checkout and handle the Jenkinsfile and the other jobs (I've also manually created a freestyle job to check if it can checkout the repo - with the same negative outcome) can still not access the repo due to the self-signed certificate issue...

Environment: (Jenkins is running on)
Windows 7 x64
git version 1.9.4.msysgit.0
Jenkins Version: 2.73.2
Java JRE: 1.8.0_144-b01
Plugins:
git 3.6.3
git-client 2.6.0
git-server 1.7
github 1.28.1
github-api 1.90

回答1:

Ok, I found the answer. Process Monitor to the rescue!

Using Process Monitor I could see, that the git.exe was reading a gitconfig file while building my small freestyle project.
Now, to my surprise, it was not reading the .gitconfig in the users directory (aka the global config) nor the one under system (aka the system config) but was reading a .gitconfig file located at:

C:\Program Files\Git\mingw64\etc\.gitconfig

The original content of this file was like this:

[http]
    sslCAInfo = C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt
    sslBackend = openssl
[diff "astextplain"]
    textconv = astextplain
[credential]
    helper = manager

After adding the information regarding my self-signed certificate information as shown above the content is now:

[http]
    sslCAInfo = C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt
    sslBackend = openssl
##################################
# Self Signed Server Certificate
[http "https://github.****.com"]
    sslCAInfo = "path\\to\\selvSignedCerts\\fileName.pem"
    sslCAPath = "path\\to\\selvSignedCerts\\"
    sslVerify = true
[diff "astextplain"]
    textconv = astextplain
[credential]
    helper = manager

And voila - The freestyle job, and the automatically generated jobs defined by the Jenkinsfile succeed to checkout the repo and build successfully.

Hope this helps anyone else going through such a pain with self signed certificates.
But the main tip: Stop using self-signed certificates! Buying an official one will be cheaper! (will have to talk to our IT department...)