2

I'm trying to do something similar to what was done in here but I'm running Jenkins on a Windows server and am trying to pass in credentials from Jenkins' credentials store, it warrants a different post.

In the comments for the post above, I've looked at this post and now have this in my pipeline:

withCredentials([sshUserPrivateKey(credentialsId:'ci', keyFileVariable:'GITHUB_KEY')]){
  withEnv(["GIT_SSH_COMMAND=ssh -i $GIHUB_KEY -o StrictHostKeyChecking=no]){
    bat script: 'git submodule update --init --recursive'
  }
}

However, when the build runs, it get an error due to login failure:

using GIT_SSH to set credentials <credentials_description>
> C:\<git_install_path>\git.exe submodule update --init --recursive <submodule_name> # timeout=10
...
...
hudson.plugins.git.GitException: Command "C:\<git_install_path>\git.exe submodule update --init --recursive <submodule_name>" returned status code 1:
stdout:
stderr: Cloning into '<Jenkins job folder>'
Logon failed, use ctrl+c to cancel basic credential prompt
bash: /dev/tty: No such device or address
error: failed to execute prompt script (exit code 1)
fatal: could not read Username for '<git url>': No such file or directory
fatal: clone of '<submodule url>' into submodule path '<local submodule path>' failed
Failed to clone '<submodule>'. Retry scheduled
...

Is there a way to pass in these credentials from Jenkins when calling the git submodule command? Or do I need to set the GIT_SSH_COMMAND in the environment block like in the first linked post and have the private key stored on the build box somewhere?

EDIT: I've also tried using the checkout syntax but I get the same login failure error

checkout([
  $class: 'GitSCM',
  branches: [[name '*/<branch_name'>]],
  doGenerateSubmoduleConfigurations: false,
  extensions: [[
    $class: 'SubmoduleOption', 
    disableSubmodules: false, 
    parentCredentials: true, 
    recursiveSubmodules: true,
    reference: '',
    trackingSubmodules: false
  ]],
  submoduleCfg: [],
  userRemoteConfigs: [[credentialsId:'ci', url:'<git_url>']]
])
daitienshi
  • 181
  • 1
  • 3
  • 11
  • What is odd is that if I use the checkout command, the initial pull of the code works fine, but it's on the submodules (which the credentials are valid for) where the login failure is happening. – daitienshi May 01 '20 at 19:51

1 Answers1

0

Given that your checkout also fails I suspect your submodules may be https. If so, your GIT_SSH_COMMAND isn't even getting invoked for your submodules because they're not using SSH.

You can confirm this by looking in the .gitmodules file in your repo. If you see url = https:// it's a http submodule. If your submodules are on the same server your best bet may be a relative path. That will let users use the same protocol on your submodules and your parent repo automatically. I think most people would incorrectly assume that was the default behavior of submodules.

Once you resolve that, your code above looks like it's also going to run into this issue:

On Windows it seems that keyFileVariable returns a windows style path with backslash separators. You can verify by using dummy credentials and dumping the value of the variable to a file that you then archive as part of your build. I wasn't really sure what to expect, but it seems to be an absolute path including the drive letter.

What I found a little more surprising is that ssh -i expects a path with forward slashes. I guess it's a unix utility on windows so we're kind of asking for this kind of confusion (luckily it seems okay with the drive letter).

I had to add a section where I subsitute the path seperators: env.GITHUB_KEY.replaceAll("\\\\","/")

So in the end something like this:

withCredentials([sshUserPrivateKey(credentialsId:'ci', keyFileVariable:'GITHUB_KEY')]){
  script {
    def KEY_UNIX_STYLE_PATH = env.GITHUB_KEY.replaceAll("\\\\","/")
    withEnv(["GIT_SSH_COMMAND=ssh -i $KEY_UNIX_STYLE_PATH -o StrictHostKeyChecking=no]){
      bat script: 'git submodule update --init --recursive'
    }
  }
}

WARNING: this now makes it trivial to accidently expose this path unmasked in the logs. I actually don't think this matters much though, because it's the file's contents (the private key) that are the real secret. See the official docs on Handling Credentials for more details.

Lockyer
  • 1,311
  • 1
  • 13
  • 30