Files
move-data-nas/internal/models/sshkey.go
T
darroyo 8d0117399c Fix SSH public key format: use ssh.MarshalAuthorizedKey
Bug: raw ed25519.PublicKey bytes were stored directly instead of
OpenSSH authorized-key format (ssh-ed25519 AAAA... label).

Fixes:
- internal/sshmanager/fingerprint.go: GenerateKeyPair now uses
  ssh.NewPublicKey + ssh.MarshalAuthorizedKey
- internal/sshmanager/keys.go: EnsureServerKey uses same fix; also
  regenerates .pub file from private key if stored value is corrupt
- internal/sshmanager/fingerprint.go: add MarshalED25519PublicKey,
  PublicKeyFromPrivateKeyFile, RegeneratePublicKeyFromPrivateKeyFile
- internal/models/sshkey.go: add UpdatePublicKey
- internal/api/handlers_sshkeys.go: List+Get recover existing DB
  records with corrupt public keys by regenerating from private key
  file and updating the DB

Also adds golang.org/x/crypto/ssh dependency via go mod tidy.
2026-07-08 00:30:57 -04:00

86 lines
2.2 KiB
Go

package models
import (
"database/sql"
"time"
)
type SSHKey struct {
ID int64 `db:"id" json:"id"`
Label string `db:"label" json:"label"`
PrivateKeyPath string `db:"private_key_path" json:"-"`
PublicKey string `db:"public_key" json:"public_key"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
}
type SSHKeyRepository struct {
db *sql.DB
}
func NewSSHKeyRepository(db *sql.DB) *SSHKeyRepository {
return &SSHKeyRepository{db: db}
}
func (r *SSHKeyRepository) Create(label, privPath, pubKey string) (int64, error) {
res, err := r.db.Exec(
"INSERT INTO ssh_keys (label, private_key_path, public_key) VALUES (?, ?, ?)",
label, privPath, pubKey,
)
if err != nil {
return 0, err
}
return res.LastInsertId()
}
func (r *SSHKeyRepository) GetByID(id int64) (*SSHKey, error) {
var k SSHKey
err := r.db.QueryRow(
"SELECT id, label, private_key_path, public_key, created_at FROM ssh_keys WHERE id = ?",
id,
).Scan(&k.ID, &k.Label, &k.PrivateKeyPath, &k.PublicKey, &k.CreatedAt)
if err != nil {
return nil, err
}
return &k, nil
}
func (r *SSHKeyRepository) GetAll() ([]SSHKey, error) {
rows, err := r.db.Query(
"SELECT id, label, private_key_path, public_key, created_at FROM ssh_keys ORDER BY label")
if err != nil {
return nil, err
}
defer rows.Close()
var keys []SSHKey
for rows.Next() {
var k SSHKey
if err := rows.Scan(&k.ID, &k.Label, &k.PrivateKeyPath, &k.PublicKey, &k.CreatedAt); err != nil {
return nil, err
}
keys = append(keys, k)
}
return keys, rows.Err()
}
func (r *SSHKeyRepository) Delete(id int64) error {
_, err := r.db.Exec("DELETE FROM ssh_keys WHERE id = ?", id)
return err
}
func (r *SSHKeyRepository) UpdatePublicKey(id int64, pubKey string) error {
_, err := r.db.Exec("UPDATE ssh_keys SET public_key = ? WHERE id = ?", pubKey, id)
return err
}
func (r *SSHKeyRepository) GetServerKey() (*SSHKey, error) {
var k SSHKey
err := r.db.QueryRow(
"SELECT id, label, private_key_path, public_key, created_at FROM ssh_keys WHERE label = 'server' LIMIT 1",
).Scan(&k.ID, &k.Label, &k.PrivateKeyPath, &k.PublicKey, &k.CreatedAt)
if err != nil {
return nil, err
}
return &k, nil
}