feat: refactor REST API

This commit is contained in:
2025-05-04 16:26:04 +02:00
parent bdd5f7bea5
commit d15ec1f8cb
8 changed files with 336 additions and 229 deletions

View File

@@ -9,18 +9,19 @@ import (
)
// AddAuthorizedKey verifies and adds an SSH public key to /home/<user>/.ssh/authorized_keys
// if it doesn't already exist
func AddAuthorizedKey(user string, pubKey string) error {
// Verify the public key format
_, _, _, _, err := ssh.ParseAuthorizedKey([]byte(pubKey))
// if it doesn't already exist. Returns the key's fingerprint.
func AddAuthorizedKey(user string, pubKey string) (string, error) {
// Verify the public key format and get fingerprint
parsed, _, _, _, err := ssh.ParseAuthorizedKey([]byte(pubKey))
if err != nil {
return fmt.Errorf("invalid SSH public key: %v", err)
return "", fmt.Errorf("invalid SSH public key: %v", err)
}
fingerprint := ssh.FingerprintSHA256(parsed)
// Ensure .ssh directory exists
sshDir := fmt.Sprintf("/home/%s/.ssh", user)
if err := os.MkdirAll(sshDir, 0700); err != nil {
return fmt.Errorf("failed to create .ssh directory: %v", err)
return "", fmt.Errorf("failed to create .ssh directory: %v", err)
}
// Check if key already exists
@@ -28,43 +29,45 @@ func AddAuthorizedKey(user string, pubKey string) error {
if _, err := os.Stat(keyFile); err == nil {
existingKeys, err := os.ReadFile(keyFile)
if err != nil {
return fmt.Errorf("failed to read authorized_keys: %v", err)
return "", fmt.Errorf("failed to read authorized_keys: %v", err)
}
if string(existingKeys) != "" {
for _, line := range strings.Split(string(existingKeys), "\n") {
if line == pubKey {
// Key already exists, nothing to do
return nil
if line == "" {
continue
}
parsed, err := ssh.ParsePublicKey([]byte(line))
if err != nil {
continue
}
if ssh.FingerprintSHA256(parsed) == fingerprint {
// Key already exists, return fingerprint
return fingerprint, nil
}
}
}
} else if !os.IsNotExist(err) {
return fmt.Errorf("failed to check authorized_keys: %v", err)
return "", fmt.Errorf("failed to check authorized_keys: %v", err)
}
// Open authorized_keys file in append mode
f, err := os.OpenFile(keyFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
return fmt.Errorf("failed to open authorized_keys: %v", err)
return "", fmt.Errorf("failed to open authorized_keys: %v", err)
}
defer f.Close()
// Write the public key
if _, err := f.WriteString(pubKey + "\n"); err != nil {
return fmt.Errorf("failed to write public key: %v", err)
return "", fmt.Errorf("failed to write public key: %v", err)
}
return nil
return fingerprint, nil
}
// RemoveAuthorizedKey removes an authorized SSH key from /home/<user>/.ssh/authorized_keys
func RemoveAuthorizedKey(user string, pubKey string) error {
// Verify the public key format
_, _, _, _, err := ssh.ParseAuthorizedKey([]byte(pubKey))
if err != nil {
return fmt.Errorf("invalid SSH public key: %v", err)
}
// using the key's fingerprint to identify which key to remove
func RemoveAuthorizedKey(user string, fingerprint string) error {
// Check if authorized_keys file exists
keyFile := fmt.Sprintf("/home/%s/.ssh/authorized_keys", user)
if _, err := os.Stat(keyFile); err != nil {
@@ -80,10 +83,19 @@ func RemoveAuthorizedKey(user string, pubKey string) error {
return fmt.Errorf("failed to read authorized_keys: %v", err)
}
// Filter out the key to remove
// Filter out the key with matching fingerprint
var newLines []string
for _, line := range strings.Split(string(existingKeys), "\n") {
if line != "" && line != pubKey {
if line == "" {
continue
}
parsed, _, _, _, err := ssh.ParseAuthorizedKey([]byte(line))
if err != nil {
// Keep lines we can't parse
newLines = append(newLines, line)
continue
}
if ssh.FingerprintSHA256(parsed) != fingerprint {
newLines = append(newLines, line)
}
}