1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
|
$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../lib"
require_relative '../common'
require 'mocha/setup'
require 'pty'
require 'expect'
module IntegrationTestHelpers
VERBOSE = false
def sh(command)
puts "$ #{command}" if VERBOSE
res = system(command)
status = $?
raise "Command: #{command} failed:#{status.exitstatus}" unless res
end
def tmpdir(&block)
Dir.mktmpdir do |dir|
yield(dir)
end
end
def set_authorized_key(user,pubkey)
authorized_key = "/home/#{user}/.ssh/authorized_keys"
sh "sudo cp #{pubkey} #{authorized_key}"
sh "sudo chown #{user} #{authorized_key}"
sh "sudo chmod 0744 #{authorized_key}"
end
def sign_user_key(user,pubkey)
cert = "/etc/ssh/users_ca"
sh "sudo ssh-keygen -s #{cert} -I user_#{user} -n #{user} -V +52w #{pubkey}"
end
def with_agent(&block)
puts "/usr/bin/ssh-agent -c" if VERBOSE
agent_out = `/usr/bin/ssh-agent -c`
agent_out.split("\n").each do |line|
if line =~ /setenv (\S+) (\S+);/
ENV[$1] = $2
puts "ENV[#{$1}]=#{$2}" if VERBOSE
end
end
begin
yield
ensure
sh "/usr/bin/ssh-agent -k > /dev/null"
end
end
def ssh_add(key,password)
command = "ssh-add #{key}"
status = nil
PTY.spawn(command) do |reader, writer, pid|
begin
reader.expect(/Enter passphrase for .*:/) { |data| puts data }
writer.puts(password)
until reader.eof? do
line = reader.readline
puts line if VERBOSE
end
rescue Errno::EIO => _e
end
pid, status = Process.wait2 pid
end
raise "Command: #{command} failed:#{status.exitstatus}" unless status
status.exitstatus
end
def with_sshd_config(sshd_config, &block)
raise "Failed to copy config" unless system("sudo cp -f /etc/ssh/sshd_config /etc/ssh/sshd_config.original")
begin
Tempfile.open('sshd_config') do |f|
f.write(sshd_config)
f.close
system("sudo cp -f #{f.path} /etc/ssh/sshd_config")
end
system("sudo chmod 0644 /etc/ssh/sshd_config")
raise "Failed to restart sshd" unless system("sudo service ssh restart")
yield
ensure
system("sudo cp -f /etc/ssh/sshd_config.original /etc/ssh/sshd_config")
system("sudo service ssh restart")
end
end
def with_lines_as_tempfile(lines = [], add_pid: true, debug: false, &block)
Tempfile.open('sshd_config') do |f|
f.write(lines.join("\n"))
pidpath = nil
if add_pid
pidpath = f.path + '.pid'
f.write("\nPidFile #{pidpath}\n")
end
f.write("\nLogLevel DEBUG3\n") if debug
f.close
puts "CONFIG: #{f.path} PID: #{pidpath}" if debug
yield(f.path, pidpath)
end
end
def port_open?(path)
Socket.tcp("localhost", 10567, connect_timeout: 1) { true } rescue false # rubocop:disable Style/RescueModifier
end
# @yield [pid, port]
def start_sshd_7_or_later(port = '2200', config: nil, debug: false)
pid = nil
sshpidfile = nil
if config
with_lines_as_tempfile(config, debug: debug) do |path, pidpath|
puts "DEBUG - SSH LOG: #{path}-log.txt config: #{path}" if debug
raise "A leftover sshd is already running" if port_open?(port)
extra_params = []
extra_params = ['-E', "#{path}-log.txt"] if debug
pid = spawn('sudo', '/opt/net-ssh-openssh/sbin/sshd', '-D', '-f', path, '-p', port, *extra_params)
sshpidfile = pidpath
yield pid, port
end
else
with_lines_as_tempfile(['']) do |path, pidpath|
pid = spawn('sudo', '/opt/net-ssh-openssh/sbin/sshd', '-D', '-f', path, '-p', port)
sshpidfile = pidpath
yield pid, port
end
end
ensure
# Our pid is sudo and not sshd, -9 (KILL) on sudo will not clean up its children
# properly, so we just have to hope that -15 (TERM) will manage to bring
# down sshd.
if sshpidfile
sshpid = File.read(sshpidfile).strip
system('sudo', 'kill', '-15', sshpid.to_s)
begin
Timeout.timeout(20) do
Process.wait(pid)
end
rescue Timeout::Error
warn "Failed to kill openssh process: #{sshpid}"
system('sudo', 'kill', '-9', sshpid.to_s)
raise
end
elsif pid
system('sudo', 'kill', '-15', pid.to_s)
begin
Timeout.timeout(20) do
Process.wait(pid)
end
rescue Timeout::Error
warn "Failed to kill openssh process: #{pid}"
system('sudo', 'kill', '-9', pid.to_s)
raise
end
end
end
def localhost
'localhost'
end
def user
'net_ssh_1'
end
end
|