Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
194 views
in Technique[技术] by (71.8m points)

docker - How does Jenkins transfer a private key and passphrase to Git?

In other words: What to mount when running Git in Docker on a Jenkins agent?

On my Jenkins server I use the credentials system to store a private key with password to access a Git repository which has the public key. This basically works fine, and authentication is okay.

The Jenkins agent has not many packages installed but SSH, Java (to run the agent) and Docker (so the jobs can run anything). When Git is installed as a regular package then Jenkins is able to check out my repository.

My challenge is that the system is an old Red Hat 7 which I cannot update for a reason out of scope here. I am stuck with very old packages, so I try to run as many things as possible via Docker to be able to use newer versions. For example, Git in a Docker container can be run with an image like this: https://hub.docker.com/r/alpine/git

Now when I replace /usr/bin/git with a script that runs Git in Docker then it works fine on command line. But when run from Jenkins, I see that it is picked up due to the version, but then I get the error "Permission denied (publickey)" code 128.

As far as I understand, Jenkins puts the private key to a temporary file location so Git can read it. I assume that Jenkins uses a mechanism like GIT_SSH_COMMAND="ssh -i /path/to/key" to tell Git where to find the private key. But I cannot find which location Jenkins actually uses! I cannot see in the build logs what Jenkins does there. -- Investigating my workspaces and environment variables on Jenkins, I am pretty sure now that $WORKSPACE_TMP contains the key files required during build. That is in /var/jenkins in my case, so that should be enough to mount.

I tried to mount several file system locations (which I found on the web that might have to do with transporting the key file) from the Jenkins agent into the Git container... but I still get the same error. What am I missing?

The script /usr/bin/git looks like this:

#!/bin/sh
docker run --rm 
    -v ${HOME}:/root 
    -v /var/jenkins:/var/jenkins 
    -v $(pwd):/git 
    alpine/git "$@"

I also tried like -v $(pwd):$(pwd) -w $(pwd) but still the same.

The build log looks like this where XXX hides private data:

Running as SYSTEM
Building remotely on Smith (docker) in workspace /var/jenkins/workspace/test2
Selected Git installation does not exist. Using Default
The recommended git tool is: NONE
using credential xxx
 > git rev-parse --is-inside-work-tree # timeout=10
Fetching changes from the remote Git repository
 > git config remote.origin.url xxx.git # timeout=10
Fetching upstream changes from xxx.git
 > git --version # timeout=10
 > git --version # 'git version 2.30.0'
using GIT_SSH to set credentials xxx
 > git fetch --tags --force --progress -- xxx.git +refs/heads/*:refs/remotes/origin/* # timeout=10
ERROR: Error fetching remote repo 'origin'
hudson.plugins.git.GitException: Failed to fetch from xxx.git
    ...
Caused by: hudson.plugins.git.GitException: Command "git fetch --tags --force --progress -- xxx.git +refs/heads/*:refs/remotes/origin/*" returned status code 128:
stdout: 
stderr: xxx: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

Because the job fails during checkout, I cannot run any command to examine the environment for temporary files or variables.

Again, when I replace the script with a regular Git package then it all works. But this is not what I want because of very old version of Git in that case on that system I have to use.

I searched the web including SO for several hours but didn't find a clue. I still hope that there is just another location where the key is temporarily stored that I can mount. Or any hint on what Jenkins actually does there. Any help appreciated!


On the next day, I got some clues but no solution. I added above the hint about $WORKSPACE_TMP in Jenkins. I updated the title of this question to reflect it might not be primarily about the mounts but more about how to get authentication into the container.

I thought of maybe something does not come right on STDIN or something... but adding -i or -a STDIN to docker run does not help. Maybe it was not a good idea to use that wrapper script there? Maybe it would be better to use a function as described on https://hub.docker.com/r/alpine/git ? -- I tried adding that to ~/.profile which does not work, but with ~/.bashrc I see the function in Agent startup!

function git () {
    (docker run -i --rm -v ${HOME}:/root -v /var/jenkins:/var/jenkins -v $(pwd):/git alpine/git "$@")
}

Unfortunately when I run the job then Jenkins keeps telling me "Cannot run program "git" (in directory "/var/jenkins/workspace/test2"): error=2, No such file or directory". I also tried playing with the Agent's configuration like directories of programs and prefix/suffix of startup command, but without any success.

Done for today. Maybe I should instead start compiling Git from source instead of this messing around?

question from:https://stackoverflow.com/questions/65909929/how-does-jenkins-transfer-a-private-key-and-passphrase-to-git

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...