smart_proxy_remote_execution_ssh 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a599d3732d4f6b064a850ae8baced28354980096785a340828533f953f844c4
4
- data.tar.gz: 160b80ab983f0eb7b987987191b48c19db42d3b76079b0ba6639ec831dccc6f3
3
+ metadata.gz: f28e2eb48888626dad82eb56e7a5309da15d584e6d4c53eaf648e5ddfc6f3d1e
4
+ data.tar.gz: a5b604d80264dc78b461e1792100ecd6fc9a4a71791b8df5b064bd80a32f6920
5
5
  SHA512:
6
- metadata.gz: 349961aa474809225d9781bda09687eb23f00db51cca9f758a57e075fa3d19fc07b729569b064887f91bb7f07190152d6ec9cb01e8ccf48df0841e9c3f85d10e
7
- data.tar.gz: 8ad40859c92f7d1cd089adf0f37bb0aaa8add745cd461c2e1ed5b484d3ae6b856ac0ee53e61c62e89d564a4ba676b22bf5f01618da970986cd60e42591ff6346
6
+ metadata.gz: 3231a3d465b180d1b8b325fd9fc341c009b566452946ee56837f9f37e6502d7095d1a213bc5b4b13078b9d54e5bd592f5430aea502ecdee93edab15901440815
7
+ data.tar.gz: 62e77d3cf6d37c90b2e6e8e48ad8b2080186a50fd1d3633b38743a099e0897b9b1e4d4dafaf7b02b1855dcd51036d418333c156438c3b20e5fa42feac93ded17
@@ -5,6 +5,8 @@ require 'time'
5
5
  module Proxy::RemoteExecution::Ssh::Actions
6
6
  class PullScript < Proxy::Dynflow::Action::Runner
7
7
  JobDelivered = Class.new
8
+ PickupTimeout = Class.new
9
+ ResendNotification = Class.new
8
10
 
9
11
  execution_plan_hooks.use :cleanup, :on => :stopped
10
12
 
@@ -17,9 +19,20 @@ module Proxy::RemoteExecution::Ssh::Actions
17
19
  if event == JobDelivered
18
20
  output[:state] = :delivered
19
21
  suspend
22
+ elsif event == PickupTimeout
23
+ process_pickup_timeout
24
+ elsif event == ResendNotification
25
+ if input[:with_mqtt] && %w(ready_for_pickup notified).include?(output[:state])
26
+ schedule_mqtt_resend
27
+ mqtt_start(::Proxy::Dynflow::OtpManager.passwords[execution_plan_id])
28
+ end
29
+ suspend
20
30
  else
21
31
  super
22
32
  end
33
+ rescue => e
34
+ action_logger.error(e)
35
+ process_update(Proxy::Dynflow::Runner::Update.encode_exception('Proxy error', e))
23
36
  end
24
37
 
25
38
  def init_run
@@ -27,10 +40,15 @@ module Proxy::RemoteExecution::Ssh::Actions
27
40
  ::Proxy::Dynflow::OtpManager.generate_otp(execution_plan_id)
28
41
  end
29
42
 
30
- input[:job_uuid] = job_storage.store_job(host_name, execution_plan_id, run_step_id, input[:script].tr("\r", ''))
43
+ plan_event(PickupTimeout, input[:time_to_pickup], optional: true) if input[:time_to_pickup]
44
+
45
+ input[:job_uuid] = job_storage.store_job(host_name, execution_plan_id, run_step_id, input[:script].tr("\r", ''), effective_user: input[:effective_user])
31
46
  output[:state] = :ready_for_pickup
32
47
  output[:result] = []
33
- mqtt_start(otp_password) if input[:with_mqtt]
48
+ if input[:with_mqtt]
49
+ schedule_mqtt_resend
50
+ mqtt_start(otp_password)
51
+ end
34
52
  suspend
35
53
  end
36
54
 
@@ -103,6 +121,8 @@ module Proxy::RemoteExecution::Ssh::Actions
103
121
  'username': execution_plan_id,
104
122
  'password': otp_password,
105
123
  'return_url': "#{input[:proxy_url]}/ssh/jobs/#{input[:job_uuid]}/update",
124
+ 'version': 'v1',
125
+ 'effective_user': input[:effective_user]
106
126
  },
107
127
  )
108
128
  mqtt_notify payload
@@ -164,5 +184,17 @@ module Proxy::RemoteExecution::Ssh::Actions
164
184
  directive: 'foreman'
165
185
  }
166
186
  end
187
+
188
+ def process_pickup_timeout
189
+ if output[:state] != :delivered
190
+ raise "The job was not picked up in time"
191
+ else
192
+ suspend
193
+ end
194
+ end
195
+
196
+ def schedule_mqtt_resend
197
+ plan_event(ResendNotification, settings[:mqtt_resend_interval], optional: true)
198
+ end
167
199
  end
168
200
  end
@@ -65,6 +65,7 @@ module Proxy::RemoteExecution
65
65
 
66
66
  with_authorized_job(job_uuid) do |job_record|
67
67
  notify_job(job_record, Actions::PullScript::JobDelivered)
68
+ response.headers['X-Foreman-Effective-User'] = job_record[:effective_user]
68
69
  job_record[:job]
69
70
  end
70
71
  end
@@ -14,7 +14,7 @@ module Proxy::RemoteExecution::Ssh::Runners
14
14
  logger.debug(line.chomp) if user_method.nil? || !user_method.filter_password?(line)
15
15
  user_method.on_data(data, pm.stdin) if user_method
16
16
  end
17
- ''
17
+ data
18
18
  end
19
19
  pm.on_stdout(&callback)
20
20
  pm.on_stderr(&callback)
@@ -11,6 +11,7 @@ module Proxy::RemoteExecution::Ssh
11
11
  String :hostname, null: false, index: true
12
12
  String :execution_plan_uuid, fixed: true, size: 36, null: false, index: true
13
13
  Integer :run_step_id, null: false
14
+ String :effective_user
14
15
  String :job, text: true
15
16
  end
16
17
  end
@@ -24,13 +25,14 @@ module Proxy::RemoteExecution::Ssh
24
25
  .select_map(:uuid)
25
26
  end
26
27
 
27
- def store_job(hostname, execution_plan_uuid, run_step_id, job, uuid: SecureRandom.uuid, timestamp: Time.now.utc)
28
+ def store_job(hostname, execution_plan_uuid, run_step_id, job, uuid: SecureRandom.uuid, timestamp: Time.now.utc, effective_user: nil)
28
29
  jobs.insert(timestamp: timestamp,
29
30
  uuid: uuid,
30
31
  hostname: hostname,
31
32
  execution_plan_uuid: execution_plan_uuid,
32
33
  run_step_id: run_step_id,
33
- job: job)
34
+ job: job,
35
+ effective_user: effective_user)
34
36
  uuid
35
37
  end
36
38
 
@@ -32,7 +32,7 @@ module Proxy::RemoteExecution::Ssh::Runners
32
32
  return [] unless @password
33
33
 
34
34
  prompt = ['-P', @prompt] if @prompt
35
- [{'SSHPASS' => SensitiveString.new(@password)}, '/usr/bin/sshpass', '-e', prompt].compact
35
+ [{'SSHPASS' => SensitiveString.new(@password)}, 'sshpass', '-e', prompt].compact
36
36
  end
37
37
 
38
38
  def ssh_options
@@ -93,7 +93,7 @@ module Proxy::RemoteExecution::Ssh::Runners
93
93
  def command(cmd)
94
94
  raise "Cannot build command to run over multiplexed connection without having an established connection" unless connected?
95
95
 
96
- ['/usr/bin/ssh', reuse_ssh_options, cmd].flatten
96
+ ['ssh', reuse_ssh_options, cmd].flatten
97
97
  end
98
98
 
99
99
  private
@@ -103,7 +103,7 @@ module Proxy::RemoteExecution::Ssh::Runners
103
103
  # does not close its stderr which trips up the process manager which
104
104
  # expects all FDs to be closed
105
105
 
106
- full_command = [method.ssh_command_prefix, '/usr/bin/ssh', establish_ssh_options, method.ssh_options, @host, 'true'].flatten
106
+ full_command = [method.ssh_command_prefix, 'ssh', establish_ssh_options, method.ssh_options, @host, 'true'].flatten
107
107
  log_command(full_command)
108
108
  pm = Proxy::Dynflow::ProcessManager.new(full_command)
109
109
  pm.start!
@@ -166,7 +166,7 @@ module Proxy::RemoteExecution::Ssh::Runners
166
166
  end
167
167
 
168
168
  def verify_key_passphrase
169
- command = ['/usr/bin/ssh-keygen', '-y', '-f', File.expand_path(@client_private_key_file)]
169
+ command = ['ssh-keygen', '-y', '-f', File.expand_path(@client_private_key_file)]
170
170
  log_command(command, label: "Checking if private key has passphrase")
171
171
  pm = Proxy::Dynflow::ProcessManager.new(command)
172
172
  pm.start!
@@ -25,7 +25,8 @@ module Proxy::RemoteExecution::Ssh
25
25
  # :mqtt_broker => nil,
26
26
  # :mqtt_port => nil,
27
27
  # :mqtt_tls => nil,
28
- :mode => :ssh
28
+ :mode => :ssh,
29
+ :mqtt_resend_interval => 900
29
30
 
30
31
  capability(proc { 'cockpit' if settings.cockpit_integration })
31
32
 
@@ -133,7 +133,6 @@ module Proxy::RemoteExecution::Ssh::Runners
133
133
  def cleanup
134
134
  if @cleanup_working_dirs
135
135
  ensure_remote_command("rm -rf #{remote_command_dir}",
136
- publish: true,
137
136
  error: "Unable to remove working directory #{remote_command_dir} on remote system, exit code: %{exit_code}")
138
137
  end
139
138
  end
@@ -1,7 +1,7 @@
1
1
  module Proxy
2
2
  module RemoteExecution
3
3
  module Ssh
4
- VERSION = '0.8.0'
4
+ VERSION = '0.9.0'
5
5
  end
6
6
  end
7
7
  end
@@ -32,3 +32,7 @@
32
32
  # unset, SSL gets used if smart-proxy's foreman_ssl_cert, foreman_ssl_key and
33
33
  # foreman_ssl_ca settings are set available.
34
34
  # :mqtt_tls:
35
+
36
+ # The notification is sent over mqtt every $mqtt_resend_interval seconds, until
37
+ # the job is picked up by the host or cancelled
38
+ # :mqtt_resend_interval: 900
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smart_proxy_remote_execution_ssh
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Nečas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 1980-01-01 00:00:00.000000000 Z
11
+ date: 2022-11-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -205,7 +205,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
205
205
  - !ruby/object:Gem::Version
206
206
  version: '0'
207
207
  requirements: []
208
- rubygems_version: 3.2.26
208
+ rubygems_version: 3.3.20
209
209
  signing_key:
210
210
  specification_version: 4
211
211
  summary: Ssh remote execution provider for Foreman Smart-Proxy