Below is a Ruby program that is supposed to verify a connection with my GitHub repos, private and public.
The ssh
key is the correct one, and it has no passphrase. However, ssh is apparently not used, as shown near the end of this question.
require 'pathname'
require 'rugged'
base = ARGV[0] || '.'
base_fq = Pathname.new(base).realpath.to_s
repo = Rugged::Repository.new base_fq
puts repo.inspect
remote = repo.remotes['origin']
puts "remote.name=#{remote.name}, remote.url=#{remote.url}, remote.fetch_refspecs=#{remote.fetch_refspecs}"
credentials = Rugged::Credentials::SshKey.new(
username: 'git',
passphrase: nil,
privatekey: File.expand_path('~/.ssh/id_rsa'),
publickey: File.expand_path('~/.ssh/id_rsa.pub')
)
puts credentials.inspect
success = remote.check_connection(:fetch, credentials: credentials)
puts "remote.check_connection(:fetch, credentials: credentials) returned #{success}"
success = remote.fetch(credentials: credentials)
puts "remote.fetch(credentials: credentials) returned #{success}"
Output is:
#<Rugged::Repository:60 {path: "/mnt/c/work/ruby/update/.git/"}>
remote.name=origin, remote.url=git@github.com:mslinn/update.git, remote.fetch_refspecs=["+refs/heads/*:refs/remotes/origin/*"]#<Rugged::Credentials::SshKey:0x00007fee350db648 @username="git", @publickey="/home/mslinn/.ssh/id_rsa.pub", @privatekey="/home/mslinn/.ssh/id_rsa", @passphrase=nil>
remote.check_connection(:fetch, credentials: credentials) returned false
lib/check_connection.rb:21:in `fetch': unsupported URL protocol (Rugged::NetworkError)
from lib/check_connection.rb:21:in `<main>'```
Why does check_connection
always return false
? Presumably that is also the reason the fetch
raises an exception.
Connecting Via ssh
I can connect via ssh
:
$ ssh github.com
Warning: No xauth data; using fake authentication data for X11 forwarding.
X11 forwarding request failed on channel 0
PTY allocation request failed on channel 0
Hi mslinn! You've successfully authenticated, but GitHub does not provide shell access.
Connection to github.com closed.
My ~/.ssh/config
file contains:
Compression yes
ForwardX11 yes
ForwardX11Trusted yes
XAuthLocation /usr/bin/xauth
Host github.com
User git
PreferredAuthentications publickey
I discovered that libgit2
uses libssh2
for ssh
support.
However, libssh2
does not read config settings from ~/.ssh/config
, so libgit2
does not support that either.
libssh2 Limitation
I found this on the GitHub blog:
If you’re using libgit2 or another piece of code using libssh2, we recommend you use libssh2 1.9.0 or newer and an ECDSA key, since it does not yet support RSA with SHA-2. Similarly, the Go SSH client also doesn’t yet support RSA with SHA-2, so we recommend using an Ed25519 key there.
I am using an RSA with SHA-2 key, which might be the problem:
$ ssh-keygen -l -f ~/.ssh/id_rsa
1024 SHA256:Xdv1AE4QTd0NfrwOGVTamF/wxnvFufCtsOIoOXtX5Mw Administrator@CHLOE (RSA)
Missing libgit2 ssh Feature
Here is how to discover the features that libgit2
was built with:
$ irb
irb(main):001:0> require 'rugged'
=> true
irb(main):002:0> Rugged.libgit2_version
=> [1, 6, 3]
irb(main):003:0> Rugged.features
=> [:threads, :https]
The above output shows the library is up-to-date (version 1.6.3), but it was not built with :ssh
, so that is definitely a problem. I'll have to build the library to include that feature.
$ gem install rugged -- --with-ssh
Building native extensions with: '--with-ssh'
This could take a while...
Successfully installed rugged-1.6.3
$ irb
irb(main):001:0> require 'rugged'
=> true
irb(main):002:0> Rugged.features
=> [:threads, :https, :ssh]
ssh Not Used
I configured the git
ssh
command to increase verbosity:
$ git config core.sshCommand "ssh -vi ~/.ssh/id_rsa"
Now when I type git pull
, the expected ssh debug information is displayed. However, this does not affect the output of my test program.
Two possibilities:
Perhaps
libgit2
(and hencerugged
) does not use the systemssh
? After digging around on the Interwebs I believe this is true.Perhaps
libgit2
(and hencerugged
) does not support thecore.sshCommand
setting?
ssh-agent
No agent is required for git
, it is optional, and I was not using one:
$ ssh-add -L
Could not open a connection to your authentication agent.
I set up ssh-agent and tried again:
$ eval $(ssh-agent) > /dev/null
$ ssh-add
Identity added: /home/mslinn/.ssh/id_rsa (/home/mslinn/.ssh/id_rsa)
$ ssh-add -l
1024 SHA256:Xdv1AE4QTd0NfrwOGVTamF/wxnvFufCtsOIoOXtX5Mw
/home/mslinn/.ssh/id_rsa (RSA)
$ echo $SSH_AGENT_PID
2196
Then I changed the Ruby program to compute credentials
using ssh-agent
:
credentials = Rugged::Credentials::SshKeyFromAgent.new(username: 'git')
However, the Ruby program failed as before. Here is the output:
#<Rugged::Repository:60 {path: "/var/work/ruby/update/.git/"}>
remote.name=origin, remote.url=git@github.com:mslinn/update.git, remote.fetch_refspecs=["+refs/heads/*:refs/remotes/origin/*"]
#<Rugged::Credentials::SshKeyFromAgent:0x00007fa290d169d0 @username="git">
remote.check_connection(:fetch, credentials: credentials) returned false