Skip to content

sshconfig

import "github.com/linuskendall/cosmonaut/internal/sshconfig"

Package sshconfig manages the local SSH configuration for codespace connections. It writes per-codespace config files into \~/.ssh/cosmonaut/ and ensures the main \~/.ssh/config includes them.

Index

Constants

HostStarScopedLine is the form a bare `Host *` is rewritten to when the user accepts the scoping fix. The negation patterns prevent the catch-all block from contributing IdentityFile / IdentityAgent / etc. to codespace hosts (gh emits both `cs-*` and `cs.*` aliases).

const HostStarScopedLine = "Host * !cs-* !cs.*"

MainConfigBackupSuffix is appended to the main ssh config path for the one-shot backup written before ScopeHostStarBlocks first modifies it.

const MainConfigBackupSuffix = ".cosmonaut.bak"

const (
    SSHIncludeLine = "Include ~/.ssh/cosmonaut/*.conf"
)

func BuildManagedExtras

func BuildManagedExtras(opts ManagedExtrasOptions) string

BuildManagedExtras returns the sentinel-bracketed managed block for the given options. Exposed so callers can preview what will be written.

func EnsureConfigIncludesGenerated

func EnsureConfigIncludesGenerated(mainConfigPath string) error

EnsureConfigIncludesGenerated ensures the main SSH config includes the generated configs.

func EnsureIncludeLine

func EnsureIncludeLine(configText string) string

EnsureIncludeLine ensures the SSH include line is at the top of the config. It removes any existing copy and prepends it.

func EnsureMainConfigIncludesGenerated

func EnsureMainConfigIncludesGenerated(mainConfigPath string) error

func EnsureWorkspaceConfig

func EnsureWorkspaceConfig(paths SSHPaths, provider, workspaceName, content string, opts ManagedExtrasOptions) error

func NeedsHostStarScoping

func NeedsHostStarScoping(mainConfigPath string) bool

NeedsHostStarScoping reports whether mainConfigPath contains any bare `Host *` lines that should be narrowed so the catch-all block doesn't apply to codespace hosts. Returns false on read errors or missing file (the GUI banner shouldn't pester users without an actionable fix).

func ParsePrimaryHostAlias

func ParsePrimaryHostAlias(sshConfig string) (string, error)

ParsePrimaryHostAlias extracts the first concrete Host entry from SSH config text.

func ProviderAndNameFromFilename

func ProviderAndNameFromFilename(filename string) (provider, name string)

ProviderAndNameFromFilename reverses WorkspaceConfigPath's naming so a caller walking IncludeDir can map a *.conf back to the (provider, name) pair that produced it. The mapping mirrors WorkspaceConfigPath:

  • "coder.conf" -> ("coder", "") // shared Coder file
  • "\<name>.conf" -> ("github", "\<name>") // GitHub codespace

Today GitHub is the only provider that writes per-workspace files (Coder shares coder.conf), so every non-"coder.conf" filename maps to a GitHub workspace whose name may itself contain "-" (e.g. "cs-abc-123"). If a future provider adds "\<provider>-\<name>.conf" filenames, extend this function to recognize the prefix.

func ReadExistingAlias

func ReadExistingAlias(includeDir, codespaceName string) (string, bool)

ReadExistingAlias reads the SSH alias from an existing codespace config file. Returns the alias and true if the file exists and contains a valid Host entry, or empty string and false otherwise.

func ReadExistingWorkspaceAlias

func ReadExistingWorkspaceAlias(paths SSHPaths, provider, workspaceName string) (string, bool)

func RefreshAllManagedExtras

func RefreshAllManagedExtras(includeDir string, optsFor func(filename string) ManagedExtrasOptions) (int, error)

RefreshAllManagedExtras walks includeDir and refreshes the managed block in every *.conf file. optsFor maps a conf filename (e.g. "cs-abc.conf") to the options for that file; if nil, every file gets the zero options (no ControlMaster). Returns the number of files updated. Safe to call on every applet startup: idempotent and cheap.

func RefreshManagedExtras

func RefreshManagedExtras(path string, opts ManagedExtrasOptions) (bool, error)

RefreshManagedExtras rewrites the managed block in path so it matches the current version and the given opts. Returns true if the file was changed. No-op if already current or if the file doesn't exist.

func ScopeHostStarBlocks

func ScopeHostStarBlocks(mainConfigPath string) (bool, error)

ScopeHostStarBlocks rewrites bare `Host *` lines in mainConfigPath to `Host * !cs-* !cs.*` so codespace hosts skip catch-all auth rules (e.g. an IdentityFile pointing at a YubiKey-resident SK key that blocks ssh when the device isn't plugged in). Idempotent.

Writes a one-shot backup to mainConfigPath+MainConfigBackupSuffix before the first modification, so the user can recover the original if the rewrite breaks something else for them. Subsequent runs leave the existing backup untouched.

func WriteCodespaceConfig

func WriteCodespaceConfig(includeDir, codespaceName, content string, opts ManagedExtrasOptions) error

WriteCodespaceConfig writes the SSH config for a codespace, replacing any prior cosmonaut-managed tail with one built from opts.

func WriteWorkspaceConfig

func WriteWorkspaceConfig(includeDir, provider, workspaceName, content string, opts ManagedExtrasOptions) error

type ManagedExtrasOptions

ManagedExtrasOptions toggles optional pieces of the managed block. Defaults (zero value) keep only the keepalive/identity lines.

type ManagedExtrasOptions struct {
    // ControlMaster enables ControlMaster auto + ControlPersist 10m so
    // subsequent sessions reuse one TCP connection.
    ControlMaster bool
}

type SSHPaths

SSHPaths holds the resolved SSH directory paths.

type SSHPaths struct {
    MainConfigPath string
    IncludeDir     string
}

func ResolvePaths

func ResolvePaths() SSHPaths

ResolvePaths returns the SSH paths for the current platform.

func (SSHPaths) CodespaceConfigPath

func (p SSHPaths) CodespaceConfigPath(codespaceName string) string

CodespaceConfigPath returns the path for a codespace-specific SSH config.

func (SSHPaths) WorkspaceConfigPath

func (p SSHPaths) WorkspaceConfigPath(provider, workspaceName string) string

Generated by gomarkdoc