package actuator import ( "context" "log/slog" "github.com/dtoro/oikos/internal/db" "github.com/dtoro/oikos/internal/secrets" ) // InfisicalHostKeySource implements HostKeySource backed by Infisical. type InfisicalHostKeySource struct { sec secrets.Backend } // NewInfisicalHostKeySource creates a HostKeySource that reads/writes // SSH host public keys from Infisical under the `ssh/host-keys/` prefix. func NewInfisicalHostKeySource(sec secrets.Backend) *InfisicalHostKeySource { return &InfisicalHostKeySource{sec: sec} } func (s *InfisicalHostKeySource) GetHostKey(ctx context.Context, path string) (string, error) { val, err := s.sec.Get(ctx, path) if err != nil { return "", err } return val, nil } func (s *InfisicalHostKeySource) SetHostKey(ctx context.Context, path string, key string) error { return s.sec.Set(ctx, path, key) } // ResolveSSHHosts queries the DB for active proxmox-host and standalone-server // entities, returning their slugs as SSH host identifiers. func ResolveSSHHosts(ctx context.Context, pool *db.Pool) []string { rows, err := pool.Query(ctx, ` SELECT slug FROM entities WHERE type IN ('proxmox-host', 'standalone-server') AND state = 'active' ORDER BY slug`) if err != nil { slog.Warn("ssh: failed to list hosts", "error", err) return nil } defer rows.Close() var hosts []string for rows.Next() { var slug string if rows.Scan(&slug) == nil { hosts = append(hosts, slug) } } return hosts }