57 lines
1.3 KiB
Go
57 lines
1.3 KiB
Go
package server
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"strings"
|
|
|
|
"golang.org/x/crypto/ssh"
|
|
)
|
|
|
|
// LoadSigner loads an SSH private key from a file path or raw PEM content.
|
|
// If <path>-cert.pub exists alongside the key, openssh-style cert auth is used.
|
|
func LoadSigner(keyOrPath string) (ssh.Signer, error) {
|
|
var keyBytes []byte
|
|
|
|
if isFilePath(keyOrPath) {
|
|
data, err := os.ReadFile(keyOrPath)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("read key file %s: %w", keyOrPath, err)
|
|
}
|
|
keyBytes = data
|
|
} else {
|
|
keyBytes = []byte(keyOrPath)
|
|
}
|
|
|
|
signer, err := ssh.ParsePrivateKey(keyBytes)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("parse private key: %w", err)
|
|
}
|
|
|
|
// If a companion -cert.pub exists, use it (same as openssh auto-loading).
|
|
if isFilePath(keyOrPath) {
|
|
certPath := keyOrPath + "-cert.pub"
|
|
if certData, err := os.ReadFile(certPath); err == nil {
|
|
pub, _, _, _, err := ssh.ParseAuthorizedKey(certData)
|
|
if err == nil {
|
|
if cert, ok := pub.(*ssh.Certificate); ok {
|
|
if cs, err := ssh.NewCertSigner(cert, signer); err == nil {
|
|
log.Printf("Auto-loaded %s", certPath)
|
|
return cs, nil
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return signer, nil
|
|
}
|
|
|
|
func isFilePath(v string) bool {
|
|
if strings.HasPrefix(v, "/") || strings.HasPrefix(v, "./") || strings.HasPrefix(v, "~") {
|
|
return true
|
|
}
|
|
return !strings.Contains(v, "-----BEGIN")
|
|
}
|