I've set up Git with SSH following https://docs.github.com/en/authentication/connecting-to-github-with-ssh; specifically, I've added my key to the SSH agent following https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent#adding-your-ssh-key-to-the-ssh-agent. I'd like to use go-git
and have tried the following example (following this comment):
package main
import (
"log"
"os"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/transport/ssh"
)
func main() {
authMethod, err := ssh.DefaultAuthBuilder("keymaster")
if err != nil {
log.Fatalf("default auth builder: %v", err)
}
if _, err := git.PlainClone("/tmp/foo", false, &git.CloneOptions{
URL: "git@github.com:org/repo.git",
Progress: os.Stdout,
Auth: authMethod,
}); err != nil {
log.Fatalf("plain clone: %v", err)
}
}
However, when I run it I get the following error:
> go run main.go
2023/02/20 06:55:25 plain clone: ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey], no supported methods remain
exit status 1
It would appear from https://github.com/go-git/go-git/blob/c35b8082c863f2106de1c3c95ba9ed21d30f9371/plumbing/transport/ssh/common.go#L37-L39 that DefaultAuthBuilder
is just an alias for NewSSHAgentAuth
, but it is unclear to me how to provide the correct username to obtain the auth method. Does anyone know how to do this?
It looks like the simplest way to get go-git
to authenticate using your agent is to let it pick an authentication method by itself. The following seems to work perfectly:
package main
import (
"log"
"os"
"github.com/go-git/go-git/v5"
)
func main() {
repo := os.Args[1]
dir := os.Args[2]
if _, err := git.PlainClone(dir, false, &git.CloneOptions{
URL: repo,
Progress: os.Stdout,
}); err != nil {
log.Fatalf("plain clone: %v", err)
}
}
If I point this at a private repository (./gg git@github.com/larsks/somepriverepo myrepo
), it successfully authenticates using a key from my agent and produces a local clone of the repository.
It looks like the username
argument to ssh.DefaultAuthBuilder
needs to be the target username on the remote system...which in this case is git
; so this also works, as long as you're fetching a git@...
URL:
package main
import (
"log"
"os"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing/transport/ssh"
)
func main() {
repo := os.Args[1]
dir := os.Args[2]
authMethod, err := ssh.DefaultAuthBuilder("git")
if err != nil {
log.Fatalf("default auth builder: %v", err)
}
if _, err := git.PlainClone(dir, false, &git.CloneOptions{
URL: repo,
Progress: os.Stdout,
Auth: authMethod,
}); err != nil {
log.Fatalf("plain clone: %v", err)
}
}
For a more general solution you would need to parse the username from the repository URL.