Can't git clone by adding ssh-key in Node.js

Problem

  # Write the SSH-KEY to the disk
  fs.writeFile "/cgrepos/.ssh/#{repo.id}.pub", repo.public_key, (err) ->
    throw err if err

    fs.writeFile "/cgrepos/.ssh/#{repo.id}", repo.private_key, (err) ->
      throw err if err

      exec "chmod 400 /cgrepos/.ssh/#{repo.id} && eval `ssh-agent -s` && ssh-add /cgrepos/.ssh/#{repo.id}", (error) ->
        throw error if error
        # First, delete the git repo on the hard drive, if it exists
        exec "rm -rf #{git_location}", options, (error) ->
          throw error if error
          # Second, clone the repo into the location
          console.log "Cloning repo #{repo.id}: #{repo.repo_name} into #{git_location}. This could take a minute"
          exec "git clone #{repo.url} #{git_location}", options, (error) ->
            throw error if error

I'm trying that in node (using coffee for those that are awesome). But for some reason, when it runs, it gives me an error: Error: Command failed: conq: repository access denied. deployment key is not associated with the requested repository.

Not sure what I'm doing wrong. If I run those commands from command line directly, everything seems to work fine. Any ideas?

Problem courtesy of: Shamoon

Solution

When you try to execute git clone process from node.js, it runs in different environment.

When you use git clone on protected (on ssh protocol) repository, ssh-agent first tries to authenticate you with provided public key. Since exec use different runtime environment for each call, even if you're adding your private key explicitly, it won't work because of different runtime environment.

When authenticating in ssh, git clone looks for SSH_AUTH_SOCK. Generally this env variable has the path of your password keyring service like (gnome-keyring or kde-wallet).

Try this to check it first.

env | grep -i ssh

It should list SSH_AGENT_PID and SSH_AUTH_SOCK. The problem is when running git clone these environ variables aren't set. So you can set them (just SSH_AUTH_SOCK is enough) as options in exec function call. Look here on how to pass env key-pairs to exec.

var exec = require('child_process').exec,
    child;

child = exec('git clone cloneurl', {
  cwd: cwdhere,      // working dir path for git clone
  env: {
           envVar1: envVarValue1,
           SSH_AUTH_SOCK: socketPathHere
       } 
}, callback);

If this doesn't work, try to execute ssh -vvv user@git-repo-host in exec function. See output of this process, you'll find error.

If the error says debug1: No more authentication methods to try. Permission denied (publickey)., then add a host alias to $HOME/.ssh/config file like this.

Host hostalias
 Hostname git-repo-host
 IdentityFile ~/.ssh/your_private_key_path

This will use provided private key to all authntication requests to specified host. In this option, you can also change your origin's url to use hostalias configured in file above. reporoot/.git/config file will look like this.

[remote "origin"]
    url = user@hostalias:repo.git
Solution courtesy of: smitrp

Discussion

There is currently no discussion for this recipe.

This recipe can be found in it's original form on Stack Over Flow.