converge/cmd/agent/sshauthorizedkeys.go
Erik Brakkee 9b8023496c Some cleanup in the agent code.
Now supporting authorized SSH keys in the
.authorized_keys file.
2024-09-08 11:16:48 +02:00

82 lines
2.0 KiB
Go

package main
import (
"bufio"
"fmt"
"github.com/gliderlabs/ssh"
gossh "golang.org/x/crypto/ssh"
"log"
"os"
"strings"
)
func publicKeyHandler(ctx ssh.Context, key gossh.PublicKey, authorizedKey gossh.PublicKey) bool {
providedKey := gossh.MarshalAuthorizedKey(key)
if ssh.KeysEqual(key, authorizedKey) {
log.Printf("Successful login from %s", ctx.RemoteAddr())
return true
}
log.Printf("Failed login attempt from %s with key: %s", ctx.RemoteAddr(), strings.TrimSpace(string(providedKey)))
return false
}
func readSshPublicKeys(fileName string) ([]ssh.PublicKey, error) {
file, err := os.Open(fileName)
if err != nil {
return nil, fmt.Errorf("Failed to open file: '%s': %s", fileName, err)
}
defer file.Close()
res := make([]ssh.PublicKey, 10)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
lineText := scanner.Text()
ind := strings.Index(lineText, "#")
if ind >= 0 {
lineText = lineText[:ind]
}
lineText = strings.Trim(lineText, "")
if lineText == "" {
continue
}
line := []byte(lineText)
parsedKey, _, _, _, err := ssh.ParseAuthorizedKey(line)
if err != nil {
log.Printf("Failed to parse authorized key: %v", lineText)
} else {
res = append(res, parsedKey)
}
}
return res, nil
}
type AuthorizedPublicKeys struct {
keys []ssh.PublicKey
}
func ParseOpenSSHAuthorizedKeysFile(authorizedKeysFile string) AuthorizedPublicKeys {
if authorizedKeysFile == "" {
return AuthorizedPublicKeys{}
}
keys, err := readSshPublicKeys(authorizedKeysFile)
if os.IsNotExist(err) {
log.Printf("Authorized keys file '%s' not found.", authorizedKeysFile)
return AuthorizedPublicKeys{}
}
if err != nil {
log.Println("Public key authentication will not work since no public keys were found.")
}
return AuthorizedPublicKeys{keys: keys}
}
func (key AuthorizedPublicKeys) authorize(ctx ssh.Context, userProvidedKey ssh.PublicKey) bool {
for _, key := range key.keys {
if publicKeyHandler(ctx, userProvidedKey, key) {
return true
}
}
return false
}