Improve ssh handling (#277)

checkout: use configured protocol for PR checkout

instead of defaulting to ssh if that is enabled
this might fix #262

login add: try to find a matching ssh key & store it in config

possibly expensive operation should be done once

pr checkout: don't fetch ssh keys

As a result, we don't try to pull via ssh, if no privkey was configured.
This increases chances of a using ssh only on a working ssh setup.

fix import order

remove debug print statement

improve ssh-key value docs

rm named return & fix pwCallback nil check

Co-authored-by: Norwin Roosen <git@nroo.de>
Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://gitea.com/gitea/tea/pulls/277
Reviewed-by: khmarbaise <khmarbaise@noreply.gitea.io>
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Reviewed-by: 6543 <6543@obermui.de>
Co-Authored-By: Norwin <noerw@noreply.gitea.io>
Co-Committed-By: Norwin <noerw@noreply.gitea.io>
This commit is contained in:
Norwin
2020-12-11 21:42:41 +08:00
committed by 6543
parent 7e191eb18b
commit 0f38da068c
6 changed files with 93 additions and 24 deletions

View File

@ -6,16 +6,21 @@ package config
import (
"crypto/tls"
"encoding/base64"
"errors"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/http/cookiejar"
"net/url"
"path/filepath"
"strings"
"code.gitea.io/tea/modules/utils"
"code.gitea.io/sdk/gitea"
"golang.org/x/crypto/ssh"
)
// Login represents a login to a gitea server, you even could add multiple logins for one gitea server
@ -133,3 +138,65 @@ func (l *Login) GetSSHHost() string {
return u.Hostname()
}
// FindSSHKey retrieves the ssh keys registered in gitea, and tries to find
// a matching private key in ~/.ssh/. If no match is found, path is empty.
func (l *Login) FindSSHKey() (string, error) {
// get keys registered on gitea instance
keys, _, err := l.Client().ListMyPublicKeys(gitea.ListPublicKeysOptions{})
if err != nil || len(keys) == 0 {
return "", err
}
// enumerate ~/.ssh/*.pub files
glob, err := utils.AbsPathWithExpansion("~/.ssh/*.pub")
if err != nil {
return "", err
}
localPubkeyPaths, err := filepath.Glob(glob)
if err != nil {
return "", err
}
// parse each local key with present privkey & compare fingerprints to online keys
for _, pubkeyPath := range localPubkeyPaths {
var pubkeyFile []byte
pubkeyFile, err = ioutil.ReadFile(pubkeyPath)
if err != nil {
continue
}
fields := strings.Split(string(pubkeyFile), " ")
if len(fields) < 2 { // first word is key type, second word is key material
continue
}
var keymaterial []byte
keymaterial, err = base64.StdEncoding.DecodeString(fields[1])
if err != nil {
continue
}
var pubkey ssh.PublicKey
pubkey, err = ssh.ParsePublicKey(keymaterial)
if err != nil {
continue
}
privkeyPath := strings.TrimSuffix(pubkeyPath, ".pub")
var exists bool
exists, err = utils.FileExist(privkeyPath)
if err != nil || !exists {
continue
}
// if pubkey fingerprints match, return path to corresponding privkey.
fingerprint := ssh.FingerprintSHA256(pubkey)
for _, key := range keys {
if fingerprint == key.Fingerprint {
return privkeyPath, nil
}
}
}
return "", err
}

View File

@ -89,6 +89,13 @@ func AddLogin(name, token, user, passwd, sshKey, giteaURL string, insecure bool)
// so we just use the hostname
login.SSHHost = serverURL.Hostname()
if len(sshKey) == 0 {
login.SSHKey, err = login.FindSSHKey()
if err != nil {
fmt.Printf("Warning: problem while finding a SSH key: %s\n", err)
}
}
// save login to global var
Config.Logins = append(Config.Logins, login)