Class: GDKBox::SSHKey

Inherits:
Object
  • Object
show all
Defined in:
lib/gdkbox/ssh_key.rb

Overview

Manages a dedicated ed25519 keypair used to authenticate into boxes.

gdkbox keeps its own key under the gdkbox home rather than touching the user's personal keys. The public half is installed into each box; the private half is referenced from the generated SSH config.

Instance Method Summary collapse

Constructor Details

#initialize(config:, shell: Shell.new) ⇒ SSHKey

Returns a new instance of SSHKey.



10
11
12
13
# File 'lib/gdkbox/ssh_key.rb', line 10

def initialize(config:, shell: Shell.new)
  @config = config
  @shell = shell
end

Instance Method Details

#ensure!Object

Generate the keypair if it does not yet exist, returning the public key. Serialized under the create lock: concurrent up runs on a fresh home would otherwise all see the key missing and race ssh-keygen for the same path (the losers crash). First one in generates; the rest re-check under the lock and just read it.



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/gdkbox/ssh_key.rb', line 20

def ensure!
  return public_key if File.exist?(@config.public_key_path)

  @config.ensure_dirs!
  File.open(@config.lock_path, File::RDWR | File::CREAT, 0o644) do |lock|
    lock.flock(File::LOCK_EX)
    break if File.exist?(@config.public_key_path) # a sibling won the race

    unless @shell.which("ssh-keygen")
      raise Error, "ssh-keygen not found on PATH; cannot generate an SSH key"
    end

    @shell.run!(
      "ssh-keygen", "-t", "ed25519",
      "-N", "", "-C", "gdkbox",
      "-f", @config.private_key_path
    )
  end
  public_key
end

#public_keyObject



41
42
43
# File 'lib/gdkbox/ssh_key.rb', line 41

def public_key
  File.read(@config.public_key_path).strip
end