Class: RightScraper::Processes::SSHAgent

Inherits:
Object
  • Object
show all
Defined in:
lib/right_scraper/processes/ssh_agent.rb

Overview

Manage a dedicated SSH agent.

Defined Under Namespace

Classes: SSHAgentError

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSSHAgent

Returns a new instance of SSHAgent.



40
41
42
43
44
45
46
# File 'lib/right_scraper/processes/ssh_agent.rb', line 40

def initialize
  @display = ENV['DISPLAY']
  @askpass = ENV['SSH_ASKPASS']
  @sshauth = ENV['SSH_AUTH_SOCK']
  @agentpid = ENV['SSH_AGENT_PID']
  @home = ENV['HOME']
end

Class Method Details

.withObject

Execute the block in a new ssh agent. Equivalent to

agent = SSHAgent.new
begin
 agent.open
 ...
ensure
 agent.close
end


181
182
183
184
185
186
187
188
189
# File 'lib/right_scraper/processes/ssh_agent.rb', line 181

def self.with
  agent = SSHAgent.new
  begin
    agent.open
    yield agent
  ensure
    agent.close
  end
end

Instance Method Details

#add_key(key) ⇒ Object

Add the given key data to the ssh agent.

Parameters

key(String)

ssh key data



126
127
128
129
130
131
132
133
134
135
136
# File 'lib/right_scraper/processes/ssh_agent.rb', line 126

def add_key(key)
  begin
    file = Tempfile.new('key')
    file.puts(key)
    file.close

    add_keyfile(file.path)
  ensure
    file.close(true) unless file.nil?
  end
end

#add_keyfile(file) ⇒ Object

Add the key data in the given file to the ssh agent.

Parameters

file(String)

file containing key data



142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/right_scraper/processes/ssh_agent.rb', line 142

def add_keyfile(file)
  @ssh_add_output = ::RightScale::RightPopen::SafeOutputBuffer.new
  cmd = ['ssh-add', file]
  ::RightScale::RightPopen.popen3_sync(
    cmd,
    :target          => self,
    :inherit_io      => true,  # avoid killing any rails connection
    :stderr_handler  => :output_ssh_add,
    :stdout_handler  => :output_ssh_add,
    :timeout_handler => :timeout_ssh_add,
    :exit_handler    => :exit_ssh_add,
    :timeout_seconds => 10)
end

#closeObject

Close the connection to the SSH agent, and restore ENV.



79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/right_scraper/processes/ssh_agent.rb', line 79

def close
  begin
    FileUtils.remove_entry_secure @dir
    lay_to_rest
  ensure
    setvar 'SSH_AGENT_PID', @agentpid
    setvar 'DISPLAY', @display
    setvar 'SSH_ASKPASS', @askpass
    setvar 'SSH_AUTH_SOCK', @sshauth
    setvar 'HOME', @home
  end
end

#exit_ssh_add(status) ⇒ Object



164
165
166
167
168
169
170
# File 'lib/right_scraper/processes/ssh_agent.rb', line 164

def exit_ssh_add(status)
  unless status.success?
    @ssh_add_output.safe_buffer_data("Exit code = #{status.exitstatus}")
    raise SSHAgentError, "ssh-add failed: #{@ssh_add_output.display_text}"
  end
  true
end

#exit_ssh_agent(status) ⇒ Object



114
115
116
117
118
119
120
# File 'lib/right_scraper/processes/ssh_agent.rb', line 114

def exit_ssh_agent(status)
  unless @interupted_to_close || status.success?
    @ssh_agent_output.safe_buffer_data("Exit code = #{status.exitstatus}")
    raise SSHAgentError, "ssh-agent failed: #{@ssh_agent_output.display_text}"
  end
  true
end

#openObject

Open a connection to the SSH agent and set ENV appropriately.



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/right_scraper/processes/ssh_agent.rb', line 50

def open
  ENV['SSH_ASKPASS'] = File.expand_path(File.join(File.dirname(__FILE__),
                                                  '..', '..', '..',
                                                  'scripts',
                                                  'stub_ssh_askpass'))
  ENV['HOME'] = "/dev/null"
  @dir = Dir.mktmpdir
  @socketfile = File.join(@dir, "agent")
  @process = nil
  @interupted_to_close = false
  @ssh_agent_output = ::RightScale::RightPopen::SafeOutputBuffer.new
  cmd = ['ssh-agent', '-a', @socketfile, '-d']
  ::RightScale::RightPopen.popen3_sync(
    cmd,
    :target          => self,
    :inherit_io      => true,  # avoid killing any rails connection
    :watch_handler   => :watch_ssh_agent,
    :stderr_handler  => :output_ssh_agent,
    :stdout_handler  => :output_ssh_agent,
    :timeout_handler => :timeout_ssh_agent,
    :exit_handler    => :exit_ssh_agent,
    :timeout_seconds => 10)
  if @process
    ENV['SSH_AGENT_PID'] = @process.pid.to_s
    ENV['SSH_AUTH_SOCK'] = @socketfile
  end
end

#output_ssh_add(data) ⇒ Object



156
157
158
# File 'lib/right_scraper/processes/ssh_agent.rb', line 156

def output_ssh_add(data)
  @ssh_add_output.safe_buffer_data(data)
end

#output_ssh_agent(data) ⇒ Object



92
93
94
# File 'lib/right_scraper/processes/ssh_agent.rb', line 92

def output_ssh_agent(data)
  @ssh_agent_output.safe_buffer_data(data)
end

#timeout_ssh_addObject

Raises:



160
161
162
# File 'lib/right_scraper/processes/ssh_agent.rb', line 160

def timeout_ssh_add
  raise SSHAgentError, 'ssh-add timed out'
end

#timeout_ssh_agentObject



108
109
110
111
112
# File 'lib/right_scraper/processes/ssh_agent.rb', line 108

def timeout_ssh_agent
  unless @interupted_to_close
    raise SSHAgentError, 'Timed out waiting for ssh-agent control socket to appear'
  end
end

#watch_ssh_agent(process) ⇒ TrueClass|FalseClass

abandons watch when socket file appears

Returns:

  • (TrueClass|FalseClass)

    true to continue watch, false to abandon



99
100
101
102
103
104
105
106
# File 'lib/right_scraper/processes/ssh_agent.rb', line 99

def watch_ssh_agent(process)
  if @interupted_to_close
    true
  else
    @process = process
    !::File.exists?(@socketfile)
  end
end