smart_proxy_remote_execution_ssh 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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