hybrid_platforms_conductor 33.4.0 → 33.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +47 -0
  3. data/README.md +5 -5
  4. data/docs/config_dsl.md +7 -5
  5. data/docs/plugins/cmdb/host_keys.md +3 -1
  6. data/docs/plugins/connector/ssh.md +1 -0
  7. data/lib/hybrid_platforms_conductor/actions_executor.rb +29 -1
  8. data/lib/hybrid_platforms_conductor/bitbucket.rb +2 -2
  9. data/lib/hybrid_platforms_conductor/cmd_runner.rb +4 -4
  10. data/lib/hybrid_platforms_conductor/config.rb +2 -0
  11. data/lib/hybrid_platforms_conductor/confluence.rb +2 -2
  12. data/lib/hybrid_platforms_conductor/connector.rb +5 -2
  13. data/lib/hybrid_platforms_conductor/credentials.rb +20 -12
  14. data/lib/hybrid_platforms_conductor/deployer.rb +5 -7
  15. data/lib/hybrid_platforms_conductor/github.rb +1 -1
  16. data/lib/hybrid_platforms_conductor/hpc_plugins/action/bash.rb +1 -1
  17. data/lib/hybrid_platforms_conductor/hpc_plugins/action/remote_bash.rb +27 -17
  18. data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/host_keys.rb +13 -12
  19. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/local.rb +6 -4
  20. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/my_connector.rb.sample +1 -1
  21. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/ssh.rb +37 -25
  22. data/lib/hybrid_platforms_conductor/hpc_plugins/log/remote_fs.rb +5 -6
  23. data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef.rb +23 -14
  24. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/docker.rb +1 -1
  25. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox.rb +3 -2
  26. data/lib/hybrid_platforms_conductor/hpc_plugins/secrets_reader/keepass.rb +1 -1
  27. data/lib/hybrid_platforms_conductor/hpc_plugins/test/check_deploy_and_idempotence.rb +17 -3
  28. data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_removes_root_access.rb +30 -10
  29. data/lib/hybrid_platforms_conductor/hpc_plugins/test/file_system.rb +1 -1
  30. data/lib/hybrid_platforms_conductor/hpc_plugins/test/hostname.rb +1 -2
  31. data/lib/hybrid_platforms_conductor/hpc_plugins/test/idempotence.rb +1 -1
  32. data/lib/hybrid_platforms_conductor/hpc_plugins/test/ip.rb +1 -2
  33. data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_conf.rb +1 -1
  34. data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_masters_ok.rb +2 -2
  35. data/lib/hybrid_platforms_conductor/hpc_plugins/test/local_users.rb +1 -2
  36. data/lib/hybrid_platforms_conductor/hpc_plugins/test/mounts.rb +1 -2
  37. data/lib/hybrid_platforms_conductor/hpc_plugins/test/orphan_files.rb +1 -2
  38. data/lib/hybrid_platforms_conductor/hpc_plugins/test/spectre.rb +1 -1
  39. data/lib/hybrid_platforms_conductor/hpc_plugins/test/vulnerabilities.rb +1 -2
  40. data/lib/hybrid_platforms_conductor/logger_helpers.rb +17 -0
  41. data/lib/hybrid_platforms_conductor/test.rb +21 -7
  42. data/lib/hybrid_platforms_conductor/tests_runner.rb +7 -6
  43. data/lib/hybrid_platforms_conductor/thycotic.rb +2 -2
  44. data/lib/hybrid_platforms_conductor/version.rb +1 -1
  45. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/bash_spec.rb +15 -0
  46. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/remote_bash_spec.rb +32 -0
  47. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/local/remote_actions_spec.rb +87 -0
  48. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/connections_spec.rb +30 -0
  49. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/global_helpers_spec.rb +10 -0
  50. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/remote_actions_spec.rb +38 -0
  51. data/spec/hybrid_platforms_conductor_test/api/actions_executor/helpers_spec.rb +195 -0
  52. data/spec/hybrid_platforms_conductor_test/api/cmd_runner_spec.rb +14 -0
  53. data/spec/hybrid_platforms_conductor_test/api/config_spec.rb +11 -0
  54. data/spec/hybrid_platforms_conductor_test/api/credentials_spec.rb +8 -4
  55. data/spec/hybrid_platforms_conductor_test/api/deployer/log_plugins/remote_fs_spec.rb +215 -0
  56. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/host_keys_spec.rb +49 -10
  57. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/services_deployment_spec.rb +64 -16
  58. data/spec/hybrid_platforms_conductor_test/helpers/connector_ssh_helpers.rb +5 -3
  59. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_local_node/chef_versions.yml +3 -0
  60. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_local_node/nodes/node.json +15 -0
  61. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_local_node/policyfiles/test_policy.rb +3 -0
  62. data/spec/hybrid_platforms_conductor_test/shared_examples/deployer.rb +134 -0
  63. data/spec/hybrid_platforms_conductor_test/test_connector.rb +2 -2
  64. metadata +20 -2
@@ -24,7 +24,7 @@ module HybridPlatformsConductor
24
24
  # * Hash<Symbol, Symbol or Array<Symbol> >: The list of necessary properties (or single one) that should be set, per property name (:others can also be used here)
25
25
  def property_dependencies
26
26
  {
27
- host_keys: %i[hostname host_ip]
27
+ host_keys: %i[hostname host_ip ssh_port]
28
28
  }
29
29
  end
30
30
 
@@ -41,19 +41,20 @@ module HybridPlatformsConductor
41
41
  # Nodes for which the property can't be fetched can be ommitted.
42
42
  def get_host_keys(_nodes, metadata)
43
43
  updated_metadata = {}
44
- # Get the list of nodes, per hostname (just in case several nodes share the same hostname)
45
- # Hash<String, Array<String> >
44
+ # Get the list of nodes, per [hostname, port] (just in case several nodes share the same hostname and port)
45
+ # Hash<[String, Integer], Array<String> >
46
46
  hostnames = Hash.new { |hash, key| hash[key] = [] }
47
47
  metadata.each do |node, node_metadata|
48
+ ssh_port = node_metadata[:ssh_port] || 22
48
49
  if node_metadata[:host_ip]
49
- hostnames[node_metadata[:host_ip]] << node
50
+ hostnames[[node_metadata[:host_ip], ssh_port]] << node
50
51
  elsif node_metadata[:hostname]
51
- hostnames[node_metadata[:hostname]] << node
52
+ hostnames[[node_metadata[:hostname], ssh_port]] << node
52
53
  end
53
54
  end
54
55
  unless hostnames.empty?
55
- host_keys_for(*hostnames.keys).each do |hostname, ip|
56
- hostnames[hostname].each do |node|
56
+ host_keys_for(*hostnames.keys).each do |host_id, ip|
57
+ hostnames[host_id].each do |node|
57
58
  updated_metadata[node] = ip
58
59
  end
59
60
  end
@@ -71,7 +72,7 @@ module HybridPlatformsConductor
71
72
  # Discover the host keys associated to a list of hosts.
72
73
  #
73
74
  # Parameters::
74
- # * *hosts* (Array<String>): The hosts to check for
75
+ # * *hosts* (Array<[String, Integer]>): The hosts to check for ([hostname, port])
75
76
  # Result::
76
77
  # * Hash<String, Array<String> >: The corresponding host keys, per host name
77
78
  def host_keys_for(*hosts)
@@ -82,9 +83,9 @@ module HybridPlatformsConductor
82
83
  parallel: true,
83
84
  nbr_threads_max: MAX_THREADS_SSH_KEY_SCAN,
84
85
  progress: log_debug? ? 'Gather host keys' : nil
85
- ) do |host|
86
+ ) do |(host, ssh_port)|
86
87
  exit_status, stdout, _stderr = @cmd_runner.run_cmd(
87
- "ssh-keyscan #{host}",
88
+ "ssh-keyscan -p #{ssh_port} #{host}",
88
89
  timeout: TIMEOUT_SSH_KEYSCAN,
89
90
  log_to_stdout: log_debug?,
90
91
  no_exception: true
@@ -97,9 +98,9 @@ module HybridPlatformsConductor
97
98
  found_keys << "#{type} #{key}"
98
99
  end
99
100
  end
100
- results[host] = found_keys.sort unless found_keys.empty?
101
+ results[[host, ssh_port]] = found_keys.sort unless found_keys.empty?
101
102
  else
102
- log_warn "Unable to get host key for #{host}. Ignoring it. Accessing #{host} might require manual acceptance of its host key."
103
+ log_warn "Unable to get host key for #{host} (port #{ssh_port}). Ignoring it. Accessing #{host} might require manual acceptance of its host key."
103
104
  end
104
105
  end
105
106
  results
@@ -35,9 +35,11 @@ module HybridPlatformsConductor
35
35
  # [API] - @stderr_io can be used to send stderr output
36
36
  #
37
37
  # Parameters::
38
- # * *bash_cmds* (String): Bash commands to execute
38
+ # * *bash_cmds* (String or SecretString): Bash commands to execute. Use #to_unprotected to access the real content (otherwise secrets are obfuscated).
39
39
  def remote_bash(bash_cmds)
40
- run_cmd "cd #{workspace_for(@node)} ; #{bash_cmds}", force_bash: true
40
+ SecretString.protect("cd #{workspace_for(@node)} ; #{bash_cmds.to_unprotected}", silenced_str: "cd #{workspace_for(@node)} ; #{bash_cmds}") do |cmd|
41
+ run_cmd cmd, force_bash: true
42
+ end
41
43
  end
42
44
 
43
45
  # Execute an interactive shell on the remote node
@@ -75,8 +77,8 @@ module HybridPlatformsConductor
75
77
  def remote_copy(from, to, sudo: false, owner: nil, group: nil)
76
78
  # If the destination is a relative path, prepend the workspace dir to it.
77
79
  to = "#{workspace_for(@node)}/#{to}" unless to.start_with?('/')
78
- if sudo
79
- run_cmd "#{@nodes_handler.sudo_on(@node)} cp -r \"#{from}\" \"#{to}\""
80
+ if sudo && !@actions_executor.privileged_access?(@node)
81
+ run_cmd "#{@actions_executor.sudo_prefix(@node)}cp -r \"#{from}\" \"#{to}\""
80
82
  else
81
83
  FileUtils.cp_r from, to unless @cmd_runner.dry_run
82
84
  end
@@ -104,7 +104,7 @@ module HybridPlatformsConductor
104
104
  # [API] - @stderr_io can be used to send stderr output
105
105
  #
106
106
  # Parameters::
107
- # * *bash_cmds* (String): Bash commands to execute
107
+ # * *bash_cmds* (String or SecretString): Bash commands to execute. Use #to_unprotected to access the real content (otherwise secrets are obfuscated).
108
108
  def remote_bash(bash_cmds)
109
109
  MyConnectLib.connect_to(@nodes_handler.get_host_ip_of(@node)).run_bash(bash_cmds)
110
110
  end
@@ -236,31 +236,40 @@ module HybridPlatformsConductor
236
236
  # [API] - @stderr_io can be used to send stderr output
237
237
  #
238
238
  # Parameters::
239
- # * *bash_cmds* (String): Bash commands to execute
239
+ # * *bash_cmds* (String or SecretString): Bash commands to execute. Use #to_unprotected to access the real content (otherwise secrets are obfuscated).
240
240
  def remote_bash(bash_cmds)
241
- ssh_cmd =
241
+ SecretString.protect(
242
242
  if @nodes_handler.get_ssh_session_exec_of(@node) == false
243
243
  # When ExecSession is disabled we need to use stdin directly
244
- "{ cat | #{ssh_exec} #{ssh_url} -T; } <<'HPC_EOF'\n#{bash_cmds}\nHPC_EOF"
244
+ "{ cat | #{ssh_exec} #{ssh_url} -T; } <<'HPC_EOF'\n#{bash_cmds.to_unprotected}\nHPC_EOF"
245
245
  else
246
- "#{ssh_exec} #{ssh_url} /bin/bash <<'HPC_EOF'\n#{bash_cmds}\nHPC_EOF"
247
- end
248
- # Due to a limitation of Process.spawn, each individual argument is limited to 128KB of size.
249
- # Therefore we need to make sure that if bash_cmds exceeds MAX_CMD_ARG_LENGTH bytes (considering EOF chars) then we use an intermediary shell script to store the commands.
250
- if bash_cmds.size > MAX_CMD_ARG_LENGTH
251
- # Write the commands in a file
252
- temp_file = "#{Dir.tmpdir}/hpc_temp_cmds_#{Digest::MD5.hexdigest(bash_cmds)}.sh"
253
- File.open(temp_file, 'w+') do |file|
254
- file.write ssh_cmd
255
- file.chmod 0o700
256
- end
257
- begin
258
- run_cmd(temp_file)
259
- ensure
260
- File.unlink(temp_file)
246
+ "#{ssh_exec} #{ssh_url} /bin/bash <<'HPC_EOF'\n#{bash_cmds.to_unprotected}\nHPC_EOF"
247
+ end,
248
+ silenced_str:
249
+ if @nodes_handler.get_ssh_session_exec_of(@node) == false
250
+ # When ExecSession is disabled we need to use stdin directly
251
+ "{ cat | #{ssh_exec} #{ssh_url} -T; } <<'HPC_EOF'\n#{bash_cmds}\nHPC_EOF"
252
+ else
253
+ "#{ssh_exec} #{ssh_url} /bin/bash <<'HPC_EOF'\n#{bash_cmds}\nHPC_EOF"
254
+ end
255
+ ) do |ssh_cmd|
256
+ # Due to a limitation of Process.spawn, each individual argument is limited to 128KB of size.
257
+ # Therefore we need to make sure that if bash_cmds exceeds MAX_CMD_ARG_LENGTH bytes (considering EOF chars) then we use an intermediary shell script to store the commands.
258
+ if bash_cmds.to_unprotected.size > MAX_CMD_ARG_LENGTH
259
+ # Write the commands in a file
260
+ temp_file = "#{Dir.tmpdir}/hpc_temp_cmds_#{Digest::MD5.hexdigest(bash_cmds.to_unprotected)}.sh"
261
+ File.open(temp_file, 'w+') do |file|
262
+ file.write ssh_cmd.to_unprotected
263
+ file.chmod 0o700
264
+ end
265
+ begin
266
+ run_cmd(temp_file)
267
+ ensure
268
+ File.unlink(temp_file)
269
+ end
270
+ else
271
+ run_cmd ssh_cmd
261
272
  end
262
- else
263
- run_cmd ssh_cmd
264
273
  end
265
274
  end
266
275
 
@@ -301,13 +310,14 @@ module HybridPlatformsConductor
301
310
  # * *owner* (String or nil): Owner to be used when copying the files, or nil for current one [default: nil]
302
311
  # * *group* (String or nil): Group to be used when copying the files, or nil for current one [default: nil]
303
312
  def remote_copy(from, to, sudo: false, owner: nil, group: nil)
313
+ need_sudo = sudo && !@actions_executor.privileged_access?(@node)
304
314
  if @nodes_handler.get_ssh_session_exec_of(@node) == false
305
315
  # We don't have ExecSession, so don't use ssh, but scp instead.
306
- if sudo
316
+ if need_sudo
307
317
  # We need to first copy the file in an accessible directory, and then sudo mv
308
318
  remote_bash('mkdir -p hpc_tmp_scp')
309
319
  run_cmd "scp -S #{ssh_exec} #{from} #{ssh_url}:./hpc_tmp_scp"
310
- remote_bash("#{@nodes_handler.sudo_on(@node)} mv ./hpc_tmp_scp/#{File.basename(from)} #{to}")
320
+ remote_bash("#{@actions_executor.sudo_prefix(@node)}mv ./hpc_tmp_scp/#{File.basename(from)} #{to}")
311
321
  else
312
322
  run_cmd "scp -S #{ssh_exec} #{from} #{ssh_url}:#{to}"
313
323
  end
@@ -323,7 +333,7 @@ module HybridPlatformsConductor
323
333
  #{File.basename(from)} | \
324
334
  #{ssh_exec} \
325
335
  #{ssh_url} \
326
- \"#{sudo ? "#{@nodes_handler.sudo_on(@node)} " : ''}tar \
336
+ \"#{need_sudo ? @actions_executor.sudo_prefix(@node) : ''}tar \
327
337
  --extract \
328
338
  --gunzip \
329
339
  --file - \
@@ -374,16 +384,18 @@ module HybridPlatformsConductor
374
384
 
375
385
  # Add each node
376
386
  # Query for the metadata of all nodes at once
377
- @nodes_handler.prefetch_metadata_of nodes, %i[private_ips hostname host_ip description]
387
+ @nodes_handler.prefetch_metadata_of nodes, %i[private_ips hostname host_ip description ssh_port]
378
388
  nodes.sort.each do |node|
379
389
  # Generate the conf for the node
380
390
  connection, connection_user, gateway, gateway_user = connection_info_for(node, no_exception: true)
381
391
  if connection.nil?
382
392
  config_content << "# #{node} - Not connectable using SSH - #{@nodes_handler.get_description_of(node) || ''}\n"
383
393
  else
394
+ ssh_port = @nodes_handler.get_ssh_port_of(node)
384
395
  config_content << "# #{node} - #{connection} - #{@nodes_handler.get_description_of(node) || ''}\n"
385
396
  config_content << "Host #{ssh_aliases_for(node).join(' ')}\n"
386
397
  config_content << " Hostname #{connection}\n"
398
+ config_content << " Port #{ssh_port}\n" unless ssh_port.nil?
387
399
  config_content << " User \"#{connection_user}\"\n" if connection_user != @ssh_user
388
400
  config_content << " ProxyCommand #{ssh_exec} -q -W %h:%p #{gateway_user}@#{gateway}\n" unless gateway.nil?
389
401
  if @passwords.key?(node)
@@ -648,7 +660,7 @@ module HybridPlatformsConductor
648
660
  existing_users = File.exist?(control_master_users_file) ? File.read(control_master_users_file).split("\n") : []
649
661
  ssh_url = "hpc.#{node}"
650
662
  connection, connection_user, _gateway, _gateway_user = connection_info_for(node)
651
- control_path_file = control_master_file(connection, '22', connection_user)
663
+ control_path_file = control_master_file(connection, @nodes_handler.get_ssh_port_of(node) || 22, connection_user)
652
664
  if existing_users.empty?
653
665
  # Make sure there is no stale one.
654
666
  if File.exist?(control_path_file)
@@ -29,10 +29,9 @@ module HybridPlatformsConductor
29
29
  # Result::
30
30
  # * Array< Hash<Symbol,Object> >: List of actions to be done
31
31
  def actions_to_save_logs(node, services, deployment_info, exit_status, stdout, stderr)
32
- # Create a log file to be scp with all relevant info
33
- ssh_user = @actions_executor.connector(:ssh).ssh_user
34
- sudo_prefix = ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(node)} "
35
- log_file = "#{Dir.tmpdir}/hpc_deploy_logs/#{node}_#{Time.now.utc.strftime('%F_%H%M%S')}_#{ssh_user}"
32
+ # Create a log file to be scp-ed with all relevant info
33
+ sudo_prefix = @actions_executor.sudo_prefix(node)
34
+ log_file = "#{Dir.tmpdir}/hpc_deploy_logs/#{node}_#{Time.now.utc.strftime('%F_%H%M%S')}_#{@actions_executor.connector(:ssh).ssh_user}"
36
35
  [
37
36
  {
38
37
  ruby: proc do
@@ -56,7 +55,7 @@ module HybridPlatformsConductor
56
55
  {
57
56
  scp: {
58
57
  log_file => '/var/log/deployments',
59
- :sudo => ssh_user != 'root',
58
+ :sudo => !@actions_executor.privileged_access?(node),
60
59
  :owner => 'root',
61
60
  :group => 'root'
62
61
  }
@@ -85,7 +84,7 @@ module HybridPlatformsConductor
85
84
  # Result::
86
85
  # * Array< Hash<Symbol,Object> >: List of actions to be done
87
86
  def actions_to_read_logs(node)
88
- sudo_prefix = @actions_executor.connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(node)} "
87
+ sudo_prefix = @actions_executor.sudo_prefix(node)
89
88
  [
90
89
  { remote_bash: "#{sudo_prefix}cat /var/log/deployments/`#{sudo_prefix}ls -t /var/log/deployments/ | head -1`" }
91
90
  ]
@@ -241,18 +241,24 @@ module HybridPlatformsConductor
241
241
  '--json-attributes', "nodes/#{node}.json"
242
242
  ]
243
243
  client_options << '--why-run' if use_why_run
244
+ # Force setting of TERM variable and usage of unbuffer to get colored output from chef-client even if executed through a non-interactive SSH session.
245
+ client_env = {
246
+ 'SSL_CERT_DIR' => '/etc/ssl/certs',
247
+ 'TERM' => 'xterm-256color'
248
+ }
244
249
  if @nodes_handler.get_use_local_chef_of(node)
245
250
  # Just run the chef-client directly from the packaged repository
246
- sudo_prefix = @cmd_runner.root? ? '' : 'sudo '
251
+ sudo_prefix = @cmd_runner.root? ? '' : 'sudo -E '
247
252
  [
248
253
  {
249
254
  bash: [
250
255
  'set -e',
251
256
  "cd #{package_dir}"
252
257
  ] +
253
- gems_to_install.map { |(gem_name, gem_version)| "#{sudo_prefix}SSL_CERT_DIR=/etc/ssl/certs /opt/chef-workstation/bin/chef gem install #{gem_name} --version \"#{gem_version}\"" } +
258
+ client_env.map { |var_name, value| "export #{var_name}=#{value}" } +
259
+ gems_to_install.map { |(gem_name, gem_version)| "#{sudo_prefix}/opt/chef-workstation/bin/chef gem install #{gem_name} --version \"#{gem_version}\"" } +
254
260
  [
255
- "#{sudo_prefix}SSL_CERT_DIR=/etc/ssl/certs /opt/chef-workstation/bin/chef-client #{client_options.join(' ')}"
261
+ "#{sudo_prefix}/opt/chef-workstation/bin/chef-client #{client_options.join(' ')}"
256
262
  ]
257
263
  }
258
264
  ]
@@ -263,14 +269,14 @@ module HybridPlatformsConductor
263
269
  raise "Missing file #{chef_versions_file} specifying the Chef Infra Client version to be deployed" unless File.exist?(chef_versions_file)
264
270
 
265
271
  required_chef_client_version = YAML.load_file(chef_versions_file)['client']
266
- sudo = (@actions_executor.connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(node)} -E ")
272
+ sudo = @actions_executor.sudo_prefix(node, forward_env: true)
267
273
  [
268
274
  {
269
275
  # Install dependencies
270
276
  remote_bash: [
271
277
  'set -e',
272
278
  'set -o pipefail',
273
- "if [ -n \"$(command -v apt)\" ]; then #{sudo}apt update && #{sudo}apt install -y curl build-essential ; else #{sudo}yum groupinstall 'Development Tools' && #{sudo}yum install -y curl ; fi",
279
+ "if [ -n \"$(command -v apt)\" ]; then #{sudo}apt update && #{sudo}apt install -y curl build-essential expect ; else #{sudo}yum groupinstall 'Development Tools' && #{sudo}yum install -y curl expect ; fi",
274
280
  'mkdir -p ./hpc_deploy',
275
281
  'rm -rf ./hpc_deploy/tmp',
276
282
  'mkdir -p ./hpc_deploy/tmp',
@@ -281,16 +287,19 @@ module HybridPlatformsConductor
281
287
  },
282
288
  {
283
289
  scp: { package_dir => './hpc_deploy' },
284
- remote_bash: [
285
- 'set -e',
286
- "cd ./hpc_deploy/#{package_name}"
287
- ] +
288
- gems_to_install.map { |(gem_name, gem_version)| "#{sudo}SSL_CERT_DIR=/etc/ssl/certs /opt/chef/embedded/bin/gem install #{gem_name} --version \"#{gem_version}\"" } +
289
- [
290
- "#{sudo}SSL_CERT_DIR=/etc/ssl/certs /opt/chef/bin/chef-client #{client_options.join(' ')}",
291
- 'cd ..'
290
+ remote_bash: {
291
+ commands: [
292
+ 'set -e',
293
+ "cd ./hpc_deploy/#{package_name}"
292
294
  ] +
293
- (log_debug? ? [] : ["#{sudo}rm -rf ./hpc_deploy/#{package_name}"])
295
+ gems_to_install.map { |(gem_name, gem_version)| "#{sudo}/opt/chef/embedded/bin/gem install #{gem_name} --version \"#{gem_version}\"" } +
296
+ [
297
+ "#{sudo}unbuffer /opt/chef/bin/chef-client #{client_options.join(' ')}",
298
+ 'cd ..'
299
+ ] +
300
+ (log_debug? ? [] : ["#{sudo}rm -rf ./hpc_deploy/#{package_name}"]),
301
+ env: client_env
302
+ }
294
303
  }
295
304
  ]
296
305
  end
@@ -21,7 +21,7 @@ module HybridPlatformsConductor
21
21
  ::Docker.validate_version!
22
22
  docker_ok = true
23
23
  rescue
24
- log_error "[ #{@node}/#{@environment} ] - Docker is not installed correctly. Please install it. Error: #{$ERROR_INFO}"
24
+ log_error "Docker is not installed correctly. Please install it. Error: #{$ERROR_INFO}"
25
25
  end
26
26
  docker_ok
27
27
  end
@@ -2,6 +2,7 @@ require 'json'
2
2
  require 'proxmox'
3
3
  require 'digest'
4
4
  require 'hybrid_platforms_conductor/actions_executor'
5
+ require 'hybrid_platforms_conductor/credentials'
5
6
  require 'hybrid_platforms_conductor/provisioner'
6
7
 
7
8
  module HybridPlatformsConductor
@@ -284,7 +285,7 @@ module HybridPlatformsConductor
284
285
  # cf https://pve.proxmox.com/wiki/Renaming_a_PVE_node
285
286
  URI.parse(url).host.downcase.split('.').first,
286
287
  user,
287
- password,
288
+ password&.to_unprotected,
288
289
  ENV['hpc_realm_for_proxmox'] || 'pam',
289
290
  {
290
291
  verify_ssl: false,
@@ -436,7 +437,7 @@ module HybridPlatformsConductor
436
437
  {
437
438
  proxmox_test_info[:sync_node] => {
438
439
  remote_bash: {
439
- commands: "#{@actions_executor.connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(proxmox_test_info[:sync_node])} -E "}./proxmox/#{cmd}",
440
+ commands: "#{@actions_executor.sudo_prefix(proxmox_test_info[:sync_node], forward_env: true)}./proxmox/#{cmd}",
440
441
  env: {
441
442
  'hpc_user_for_proxmox' => user,
442
443
  'hpc_password_for_proxmox' => password,
@@ -90,7 +90,7 @@ module HybridPlatformsConductor
90
90
  key_file = ENV['hpc_key_file_for_keepass']
91
91
  password_enc = ENV['hpc_password_enc_for_keepass']
92
92
  keepass_credentials = {}
93
- keepass_credentials[:password] = password if password
93
+ keepass_credentials[:password] = password.to_unprotected if password
94
94
  keepass_credentials[:password_enc] = password_enc if password_enc
95
95
  keepass_credentials[:key_file] = key_file if key_file
96
96
  KeepassKpscript.
@@ -26,7 +26,13 @@ module HybridPlatformsConductor
26
26
  # Check that we can connect with root
27
27
  ssh_ok = false
28
28
  begin
29
- Net::SSH.start(instance.ip, 'root', password: 'root_pwd', auth_methods: ['password'], verify_host_key: :never) do |ssh|
29
+ Net::SSH.start(
30
+ instance.ip,
31
+ 'root',
32
+ password: 'root_pwd',
33
+ auth_methods: ['password'],
34
+ verify_host_key: :never
35
+ ) do |ssh|
30
36
  ssh_ok = ssh.exec!('echo Works').strip == 'Works'
31
37
  end
32
38
  rescue
@@ -53,14 +59,22 @@ module HybridPlatformsConductor
53
59
  # System is booting up. See pam_nologin(8)
54
60
  # Authentication failed.
55
61
  instance.stop
56
- instance.with_running_instance(port: 22) do
62
+ ssh_port = @nodes_handler.get_ssh_port_of(@node) || 22
63
+ instance.with_running_instance(port: ssh_port) do
57
64
 
58
65
  unless @nodes_handler.get_root_access_allowed_of(@node)
59
66
  # ===== Deploy removes root access
60
67
  # Check that we can't connect with root
61
68
  ssh_ok = false
62
69
  begin
63
- Net::SSH.start(instance.ip, 'root', password: 'root_pwd', auth_methods: ['password'], verify_host_key: :never) do |ssh|
70
+ Net::SSH.start(
71
+ instance.ip,
72
+ 'root',
73
+ password: 'root_pwd',
74
+ auth_methods: ['password'],
75
+ verify_host_key: :never,
76
+ port: ssh_port
77
+ ) do |ssh|
64
78
  ssh_ok = ssh.exec!('echo Works').strip == 'Works'
65
79
  end
66
80
  rescue
@@ -18,7 +18,13 @@ module HybridPlatformsConductor
18
18
  # Check that we can connect with root
19
19
  ssh_ok = false
20
20
  begin
21
- Net::SSH.start(instance.ip, 'root', password: 'root_pwd', auth_methods: ['password'], verify_host_key: :never) do |ssh|
21
+ Net::SSH.start(
22
+ instance.ip,
23
+ 'root',
24
+ password: 'root_pwd',
25
+ auth_methods: ['password'],
26
+ verify_host_key: :never
27
+ ) do |ssh|
22
28
  ssh_ok = ssh.exec!('echo Works').strip == 'Works'
23
29
  end
24
30
  rescue
@@ -29,17 +35,31 @@ module HybridPlatformsConductor
29
35
  deployer.nbr_retries_on_error = 3
30
36
  deployer.deploy_on @node
31
37
  # As sshd is certainly being restarted, start and stop the container to reload it.
32
- deployer.restart @node
33
- # Check that we can't connect with root
34
- ssh_ok = false
35
- begin
36
- Net::SSH.start(instance.ip, 'root', password: 'root_pwd', auth_methods: ['password'], verify_host_key: :never) do |ssh|
37
- ssh_ok = ssh.exec!('echo Works').strip == 'Works'
38
+ # As it's possible sshd has to be restarted because of a change in its conf, restart the container.
39
+ # Otherwise you'll get the following error upon reconnection:
40
+ # System is booting up. See pam_nologin(8)
41
+ # Authentication failed.
42
+ instance.stop
43
+ ssh_port = @nodes_handler.get_ssh_port_of(@node) || 22
44
+ instance.with_running_instance(port: ssh_port) do
45
+ # Check that we can't connect with root
46
+ ssh_ok = false
47
+ begin
48
+ Net::SSH.start(
49
+ instance.ip,
50
+ 'root',
51
+ password: 'root_pwd',
52
+ auth_methods: ['password'],
53
+ verify_host_key: :never,
54
+ port: ssh_port
55
+ ) do |ssh|
56
+ ssh_ok = ssh.exec!('echo Works').strip == 'Works'
57
+ end
58
+ rescue
59
+ nil
38
60
  end
39
- rescue
40
- nil
61
+ assert_equal ssh_ok, false, 'Root can still connect on the image after deployment'
41
62
  end
42
- assert_equal ssh_ok, false, 'Root can still connect on the image after deployment'
43
63
  end
44
64
  end
45
65
  end