better-argo-tunnels/internal/server/keyutil.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")
}