Jenkins with Git Client needs permission on Temporary directory

Issue

  • Jobs using the Git Plugin fails with the following stack trace:
  • Jobs using the Git Plugin fails with the following stack trace after the Git Client Plugin is upgraded:
hudson.plugins.git.GitException: Command "/usr/local/bin/git fetch --tags --progress https://github.com/user/repo.git +refs/heads/*:refs/remotes/origin/*" returned status code 128:
stdout:
stderr: fatal: cannot exec '/tmp/pass4619352834734512307.sh': Permission denied
fatal: could not read Username for 'https://github.com': No such device or address
    at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.launchCommandIn(CliGitAPIImpl.java:1772)
    at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.launchCommandWithCredentials(CliGitAPIImpl.java:1516)
    at org.jenkinsci.plugins.gitclient.CliGitAPIImpl.access$300(CliGitAPIImpl.java:67)
    at org.jenkinsci.plugins.gitclient.CliGitAPIImpl$1.execute(CliGitAPIImpl.java:318)
    at org.jenkinsci.plugins.gitclient.CliGitAPIImpl$2.execute(CliGitAPIImpl.java:515)
    at org.jenkinsci.plugins.gitclient.RemoteGitImpl$CommandInvocationHandler$1.call(RemoteGitImpl.java:152)
    at org.jenkinsci.plugins.gitclient.RemoteGitImpl$CommandInvocationHandler$1.call(RemoteGitImpl.java:145)
    at hudson.remoting.UserRequest.perform(UserRequest.java:153)
    at hudson.remoting.UserRequest.perform(UserRequest.java:50)
    at hudson.remoting.Request$2.run(Request.java:332)
    at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:68)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at hudson.remoting.Engine$1$1.run(Engine.java:90)
    at java.lang.Thread.run(Thread.java:745)
    at ......remote call to Channel to /172.27.166.117(Native Method)
    at hudson.remoting.Channel.attachCallSiteStackTrace(Channel.java:1537)
    at hudson.remoting.UserResponse.retrieve(UserRequest.java:253)
    at hudson.remoting.Channel.call(Channel.java:822)
    at org.jenkinsci.plugins.gitclient.RemoteGitImpl$CommandInvocationHandler.execute(RemoteGitImpl.java:145)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.jenkinsci.plugins.gitclient.RemoteGitImpl$CommandInvocationHandler.invoke(RemoteGitImpl.java:131)
    at com.sun.proxy.$Proxy97.execute(Unknown Source)
    at hudson.plugins.git.GitSCM.retrieveChanges(GitSCM.java:1054)
    at hudson.plugins.git.GitSCM.checkout(GitSCM.java:1094)
    at org.jenkinsci.plugins.workflow.steps.scm.SCMStep.checkout(SCMStep.java:109)
    at org.jenkinsci.plugins.workflow.steps.scm.SCMStep$StepExecutionImpl.run(SCMStep.java:83)
    at org.jenkinsci.plugins.workflow.steps.scm.SCMStep$StepExecutionImpl.run(SCMStep.java:73)
    at org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution$1$1.call(AbstractSynchronousNonBlockingStepExecution.java:47)
    at hudson.security.ACL.impersonate(ACL.java:221)
    at org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution$1.run(AbstractSynchronousNonBlockingStepExecution.java:44)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

Environment

  • Jenkins LTS
  • CloudBees Jenkins Enterprise
  • CloudBees Jenkins Operations Center
  • Git Client Plugin >= 2.0.0

Resolution

Most likely, you would experience this issue if:

  • You are using SSH credentials and the Jenkins user does not have required permission on the temporary directory
  • You are using Username/Password credentials, with Git Client >= 2.0.0 and the Jenkins user does not have required permission on the temporary directory

How to Fix

You need to give to the jenkins user the system permissions to read/write/execute scripts in the temporary directory - usually /tmp/ - on both the master and the agents. The git client plugin can launch command from either the master or the agent.

  • On the master, give the permissions to read/write/execute scripts in the temporary directory to the user running Jenkins
  • On the agents, give the permissions to read/write/execute scripts in the temporary directory to the user running the agent

Other Workaround

By default the temporary directory is /tmp/. This can actually be controlled by the system property java.io.tmpdir. Therefore another workaround could be to create specific directory for Jenkins temporary files where the jenkins user has the required permissions. Again this would need to be done on the master and the agents.

  • On the master, you can add the java argument -Djava.io.tmpdir=<pathToDirectory> to the startup parameters (see How to add Java arguments to Jenkins)
  • On the agent:
    • for JNLP (and agents launched via command line), you can add the java argument -Djava.io.tmpdir=<pathToDirectory> to the command used to you the agent, before the -jar argument
    • for SSH agents, you can add the java argument from the UI in the agent configuration in Manage Nodes > <agentName> > Configure and then under the advanced options:

Explanation

The Git Client plugin needs to store temporarily the Jenkins credentials so that the git client can retrieve them.

The recent version of the Git Client plugin change the approach with which Username/Password credentials are passed to git commands. It now uses the same method as for SSH credentials: GIT_ASKPASS.

Before 2.0.0

In version earlier than 2.0.0 of this plugin, the git client used to store username/password in a credentials store .gitcredentials temporarily during the build. We can see in the log:

using .gitcredentials to set credentials
 > /usr/bin/git config --local credential.username jenkinsci # timeout=10
 > /usr/bin/git config --local credential.helper store --file=/tmp/git2655316186893362980.credentials # timeout=10

After 2.0.0

Since the recent version 2.0.0 of the the Git Client Plugin, the git client uses the GIT_ASKPASS method which creates a temporary script to execute when git ask for credentials during the build (see this commit for more details). We can see in the log:

using GIT_ASKPASS to set credentials
[...]
Have more questions? Submit a request

2 Comments

  • 0
    Avatar
    Tero Pikala

    Small typo in this helpful article:

    -Djava.io.tmpDir  should be -Djava.io.tmpdir

  • 0
    Avatar
    Arnaud Heritier

    Hi Tero,

      It's not clear for me if Java System Properties are case sensitive. Strings are, and for environment variables it depends of the operating system. As it is clearly documented as `java.io.tmpdir`, and I don't want to take any risk, I pushed the change to our team and the article should be updated soon.

      Thanks for your help

    Best regards

Please sign in to leave a comment.