core

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 17, 2026 License: MIT Imports: 23 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BackupKeys

func BackupKeys(keysDir, destPath, passphrase string) (int, error)

BackupKeys creates an AES-256-GCM encrypted archive of all key files in keysDir and writes it to destPath. Returns the number of key files included.

func DefaultSSHDir

func DefaultSSHDir() (string, error)

DefaultSSHDir returns the standard ~/.ssh path.

func DefaultVaultPath

func DefaultVaultPath(configDir string) string

DefaultVaultPath returns a timestamped vault filename in the sshelf config dir.

func EnsureSSHDir

func EnsureSSHDir() error

EnsureSSHDir ensures ~/.ssh exists with the correct permissions.

func RestoreKeys

func RestoreKeys(vaultPath, destDir, passphrase string, force bool) (int, error)

RestoreKeys decrypts a vault file created by BackupKeys and extracts the key files into destDir. Existing files are skipped unless force is true. Returns the number of files restored.

Types

type AgentInfo

type AgentInfo struct {
	PID        int
	SocketPath string
	Running    bool
}

AgentInfo represents the observable state of an ssh-agent process.

func (*AgentInfo) EnvLines

func (info *AgentInfo) EnvLines() []string

EnvLines returns shell export statements suitable for eval.

type AgentManager

type AgentManager struct {
	// contains filtered or unexported fields
}

AgentManager manages the lifecycle of a single ssh-agent process. State (PID + socket path) is persisted to an env file for cross-session access.

func NewAgentManager

func NewAgentManager(envPath string) *AgentManager

NewAgentManager returns a manager that persists agent state at envPath.

func (*AgentManager) ListKeys

func (m *AgentManager) ListKeys(socketPath string) ([]string, error)

ListKeys returns the lines output by "ssh-add -l" for the given socket. Returns nil (not an error) when the agent is running but has no keys loaded.

func (*AgentManager) LoadKey

func (m *AgentManager) LoadKey(keyPath, socketPath string) error

LoadKey adds a key to the running agent identified by socketPath.

func (*AgentManager) Reload

func (m *AgentManager) Reload(keysDir string) (*AgentInfo, error)

Reload stops the current agent (if running) and starts a fresh one, then loads all keys from keysDir. Returns the new AgentInfo.

func (*AgentManager) Start

func (m *AgentManager) Start() (*AgentInfo, error)

Start spawns a new ssh-agent and writes its socket/PID to the env file. Returns ErrAlreadyExists if an agent is already running.

func (*AgentManager) Status

func (m *AgentManager) Status() (*AgentInfo, error)

Status reads the env file and checks whether the agent process is alive.

func (*AgentManager) Stop

func (m *AgentManager) Stop() error

Stop terminates the running agent and removes the env file.

type CheckResult

type CheckResult struct {
	Name    string
	Status  CheckStatus
	Message string
	Fixable bool
	Fix     func() error // non-nil only when Fixable is true
}

CheckResult is the result of a single doctor check.

type CheckStatus

type CheckStatus int

CheckStatus is the severity level of a single doctor check.

const (
	CheckPass CheckStatus = iota
	CheckWarn
	CheckFail
)

func (CheckStatus) String

func (s CheckStatus) String() string

type DoctorRunner

type DoctorRunner struct {
	// contains filtered or unexported fields
}

DoctorRunner runs all health checks against the sshelf environment.

func NewDoctorRunner

func NewDoctorRunner(
	store *Store,
	profiles *ProfileStore,
	hosts *HostStore,
	keys *KeyManager,
	agent *AgentManager,
) *DoctorRunner

NewDoctorRunner creates a runner with references to all required services.

func (*DoctorRunner) Run

func (r *DoctorRunner) Run(name string) (*CheckResult, error)

Run executes the single named check. Returns ErrNotFound for unknown names.

func (*DoctorRunner) RunAll

func (r *DoctorRunner) RunAll() []*CheckResult

RunAll executes every check and returns results in a stable order.

type Host

type Host struct {
	// Name is the SSH Host alias and the TOML map key. Never written to the file.
	Name        string `toml:"-"`
	Hostname    string `toml:"hostname"`
	User        string `toml:"user"`
	Port        int    `toml:"port,omitempty"`
	IdentityKey string `toml:"identity_key"`
	ProfileName string `toml:"profile,omitempty"`
	JumpHost    string `toml:"jump_host,omitempty"`
}

Host represents a named SSH host alias written into the sshelf-managed block of ~/.ssh/config.

func (*Host) SSHPort

func (h *Host) SSHPort() int

SSHPort returns the effective SSH port, falling back to DefaultSSHPort when none is explicitly set.

func (*Host) Validate

func (h *Host) Validate() error

Validate checks that all required fields are present and contain valid values.

type HostStore

type HostStore struct {
	// contains filtered or unexported fields
}

HostStore manages CRUD operations on hosts.toml.

func NewHostStore

func NewHostStore(path string) *HostStore

NewHostStore returns a HostStore backed by the file at path.

func (*HostStore) Create

func (s *HostStore) Create(h *Host) error

Create writes a new host alias to disk. Returns ErrAlreadyExists if the name is taken, or ErrInvalidInput if validation fails.

func (*HostStore) Delete

func (s *HostStore) Delete(name string) error

Delete removes a host by name. Returns ErrNotFound if it does not exist.

func (*HostStore) Get

func (s *HostStore) Get(name string) (*Host, error)

Get returns the host with the given name, or ErrNotFound.

func (*HostStore) List

func (s *HostStore) List() ([]*Host, error)

List returns all hosts sorted alphabetically by name.

func (*HostStore) ListByProfile

func (s *HostStore) ListByProfile(profileName string) ([]*Host, error)

ListByProfile returns all hosts associated with the given profile name, sorted alphabetically.

func (*HostStore) Update

func (s *HostStore) Update(h *Host) error

Update overwrites an existing host. Returns ErrNotFound if the host does not exist, or ErrInvalidInput if validation fails.

type ImportCandidate

type ImportCandidate struct {
	// For host blocks:
	Host *ParsedHost
	// For key files:
	KeyPath string
	KeyName string
}

ImportCandidate is a host block or key file that can be imported.

type ImportScanner

type ImportScanner struct {
	// contains filtered or unexported fields
}

ImportScanner discovers existing SSH host blocks and key files that are not yet managed by sshelf.

func NewImportScanner

func NewImportScanner(sshDir string, hosts *HostStore, keys *KeyManager, writer *SSHConfigWriter) *ImportScanner

NewImportScanner returns a scanner for the given SSH directory.

func (*ImportScanner) ImportHost

func (s *ImportScanner) ImportHost(ph *ParsedHost, profileName, keyName string, profiles []*Profile) error

ImportHost creates a Host record from a ParsedHost and updates the SSH config.

func (*ImportScanner) ImportKey

func (s *ImportScanner) ImportKey(srcPath string) (*KeyInfo, error)

ImportKey copies a key file into the managed keys directory and fixes permissions.

func (*ImportScanner) ScanHosts

func (s *ImportScanner) ScanHosts() ([]*ParsedHost, error)

ScanHosts reads ~/.ssh/config and returns Host blocks not already tracked.

func (*ImportScanner) ScanKeys

func (s *ImportScanner) ScanKeys() ([]ImportCandidate, error)

ScanKeys returns key files in sshDir that are not yet in the managed keys directory.

type KeyInfo

type KeyInfo struct {
	Name      string    // base filename without extension
	Type      string    // "ed25519" or "rsa"
	Comment   string    // comment embedded in the public key
	CreatedAt time.Time // derived from file mtime
	Path      string    // absolute path to the private key file
}

KeyInfo holds metadata about a managed SSH key pair.

func (*KeyInfo) Age

func (k *KeyInfo) Age() time.Duration

Age returns the duration elapsed since the key was created.

func (*KeyInfo) PublicKeyPath

func (k *KeyInfo) PublicKeyPath() string

PublicKeyPath returns the path to the corresponding .pub file.

type KeyManager

type KeyManager struct {
	// contains filtered or unexported fields
}

KeyManager manages SSH key pairs stored under the sshelf keys directory.

func NewKeyManager

func NewKeyManager(keysDir string) *KeyManager

NewKeyManager returns a KeyManager pointing at keysDir.

func (*KeyManager) Add

func (m *KeyManager) Add(srcPath string) (*KeyInfo, error)

Add imports an existing key pair by copying it into the managed keys directory. The public key is expected at srcPath+".pub"; missing .pub is tolerated.

func (*KeyManager) CheckPermissions

func (m *KeyManager) CheckPermissions(name string) error

CheckPermissions returns an error if the key permissions are not 0600/0644.

func (*KeyManager) FixPermissions

func (m *KeyManager) FixPermissions(name string) error

FixPermissions enforces 0600 on the private key and 0644 on the public key.

func (*KeyManager) Generate

func (m *KeyManager) Generate(name, keyType, comment string) (*KeyInfo, error)

Generate creates a new key pair in the keys directory. keyType must be config.KeyTypeED25519 or config.KeyTypeRSA. An empty passphrase is used (keys protected by filesystem permissions).

func (*KeyManager) Get

func (m *KeyManager) Get(name string) (*KeyInfo, error)

Get returns the KeyInfo for the named key, or ErrNotFound.

func (*KeyManager) KeysDir

func (m *KeyManager) KeysDir() string

KeysDir returns the managed keys directory path.

func (*KeyManager) List

func (m *KeyManager) List() ([]*KeyInfo, error)

List returns metadata for all managed key pairs sorted alphabetically. .pub and .bak files are excluded — only private key entries are returned.

func (*KeyManager) ReadPublicKey

func (m *KeyManager) ReadPublicKey(name string) (string, error)

ReadPublicKey returns the trimmed contents of <name>.pub.

func (*KeyManager) Remove

func (m *KeyManager) Remove(name string) error

Remove deletes the named private key and its public key.

func (*KeyManager) Rotate

func (m *KeyManager) Rotate(name, keyType, comment string) (*KeyInfo, error)

Rotate generates a new key pair, backs up the old one as <name>.bak, then renames the new pair to <name>. Returns the new KeyInfo.

type ParsedHost

type ParsedHost struct {
	Alias    string
	Hostname string
	User     string
	Port     string
	KeyFile  string
	Options  map[string]string // all other key-value pairs
}

ParsedHost represents a Host block found in an existing SSH config file.

type Profile

type Profile struct {
	// Name is the profile identifier. It is derived from the TOML map key
	// and is never written to the file itself.
	Name      string    `toml:"-"`
	Type      string    `toml:"type"`
	Platform  string    `toml:"platform,omitempty"`
	Email     string    `toml:"email"`
	Username  string    `toml:"username"`
	KeyName   string    `toml:"key_name"`
	Active    bool      `toml:"active"`
	CreatedAt time.Time `toml:"created_at"`
}

Profile represents a named SSH identity configuration.

func (*Profile) Validate

func (p *Profile) Validate() error

Validate checks that all required fields are present and contain valid values.

type ProfileStore

type ProfileStore struct {
	// contains filtered or unexported fields
}

ProfileStore manages CRUD operations on profiles.toml.

func NewProfileStore

func NewProfileStore(path string) *ProfileStore

NewProfileStore returns a ProfileStore backed by the file at path.

func (*ProfileStore) ActiveProfile

func (s *ProfileStore) ActiveProfile() (*Profile, error)

ActiveProfile returns the currently active profile. Returns ErrNotFound (with an empty Name) if no profile is active.

func (*ProfileStore) Create

func (s *ProfileStore) Create(p *Profile) error

Create writes a new profile to disk. Returns ErrAlreadyExists if the name is already taken, or ErrInvalidInput if validation fails.

func (*ProfileStore) Delete

func (s *ProfileStore) Delete(name string) error

Delete removes a profile by name. Returns ErrNotFound if it does not exist.

func (*ProfileStore) Get

func (s *ProfileStore) Get(name string) (*Profile, error)

Get returns the profile with the given name, or ErrNotFound.

func (*ProfileStore) List

func (s *ProfileStore) List() ([]*Profile, error)

List returns all profiles sorted alphabetically by name.

func (*ProfileStore) SetActive

func (s *ProfileStore) SetActive(name string) error

SetActive marks the named profile as active and deactivates all others. Returns ErrNotFound if the profile does not exist.

func (*ProfileStore) Update

func (s *ProfileStore) Update(p *Profile) error

Update overwrites an existing profile. Returns ErrNotFound if the profile does not exist, or ErrInvalidInput if validation fails.

type SSHConfigWriter

type SSHConfigWriter struct {
	// contains filtered or unexported fields
}

SSHConfigWriter manages the sshelf-owned block inside ~/.ssh/config. Content outside the managed block is never modified.

func NewSSHConfigWriter

func NewSSHConfigWriter(path string) *SSHConfigWriter

NewSSHConfigWriter returns a writer targeting the SSH config at path.

func (*SSHConfigWriter) ParseExisting

func (w *SSHConfigWriter) ParseExisting() ([]*ParsedHost, error)

ParseExisting reads the SSH config at the writer's path and returns all Host blocks that are NOT inside the sshelf-managed block.

func (*SSHConfigWriter) Remove

func (w *SSHConfigWriter) Remove() error

Remove strips the sshelf-managed block from the SSH config, leaving all other content intact.

func (*SSHConfigWriter) Sync

func (w *SSHConfigWriter) Sync(profiles []*Profile, hosts []*Host, keysDir string) error

Sync regenerates the sshelf-managed block from the given profiles and hosts, then atomically writes the result. Content outside the managed block is preserved verbatim. Calling Sync twice with the same input is idempotent.

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store holds the resolved path to the sshelf config directory and exposes path helpers for all sub-resources. It is initialized once at startup via NewStore and shared across all command handlers.

func NewStore

func NewStore(dir string) (*Store, error)

NewStore ensures the config directory and all required subdirectories exist with the correct permissions, then returns a ready-to-use Store. Safe to call on every startup — existing directories are not modified.

func (*Store) AgentEnvPath

func (s *Store) AgentEnvPath() string

func (*Store) Dir

func (s *Store) Dir() string

func (*Store) HostsPath

func (s *Store) HostsPath() string

func (*Store) KeysDir

func (s *Store) KeysDir() string

func (*Store) ProfilesPath

func (s *Store) ProfilesPath() string

func (*Store) VaultPath

func (s *Store) VaultPath() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL