bolt 3.26.2 → 3.27.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bolt might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7fe078a4da4d1447d8214edee250d80c0132b2a8913bd16f24016315a46ff215
4
- data.tar.gz: 89e27a1ed523fd9aca8d80ea94c53071bde9f0b1af947768880b8055dc47f27b
3
+ metadata.gz: c17b8b0fb4276ed447b6da76d98053171f4d5fda8503233035b919394add9e94
4
+ data.tar.gz: db0861f045bc751bd69e0da10fe7708b6b0186c5fe1e35e252b383ff935b77f4
5
5
  SHA512:
6
- metadata.gz: 8955b0ea1e737618918839b34c9b6049f884c1983e3ebb0f4ee50c4ea85007fade6dabfbf21ae34f201bf0eabb9497bcd5a33fbe3c833ada430ccced628b4477
7
- data.tar.gz: 8b1e6f84326c1e5adeb988cdadac80b2bb49b71ed2ce24dc0b0c881970e88aadbede4eaf5f3479b8f2434a9a4a221128e643d145ecffc47b1075d566ef741cd3
6
+ metadata.gz: af08780fd019620d3db858eb34387a38a0ef195d9ab56cfc2bc1e6629e1b86fcd2301b489facd81a77915a914d95eb017d5e88ec7443e66c74c72c148f334c5f
7
+ data.tar.gz: d01bb8cb30bcfd2a48e9537311b6208e8c7340e02b1101745ffe52affdf1503cf7754de7918b179af033aaa3303e9b4f381d460083cc302864f0747f4bc79d6b
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../../bolt/config/transport/docker'
4
+ require_relative '../../bolt/config/transport/jail'
4
5
  require_relative '../../bolt/config/transport/local'
5
6
  require_relative '../../bolt/config/transport/lxd'
6
7
  require_relative '../../bolt/config/transport/orch'
@@ -16,6 +17,7 @@ module Bolt
16
17
  # gets passed along to the inventory.
17
18
  TRANSPORT_CONFIG = {
18
19
  'docker' => Bolt::Config::Transport::Docker,
20
+ 'jail' => Bolt::Config::Transport::Jail,
19
21
  'local' => Bolt::Config::Transport::Local,
20
22
  'lxd' => Bolt::Config::Transport::LXD,
21
23
  'pcp' => Bolt::Config::Transport::Orch,
@@ -550,6 +552,12 @@ module Bolt
550
552
  _plugin: true,
551
553
  _example: { "cleanup" => false, "service-url" => "https://docker.example.com" }
552
554
  },
555
+ "jail" => {
556
+ description: "A map of configuration options for the jail transport.",
557
+ type: Hash,
558
+ _plugin: true,
559
+ _example: { cleanup: false }
560
+ },
553
561
  "local" => {
554
562
  description: "A map of configuration options for the local transport. The set of available options is "\
555
563
  "platform dependent.",
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../bolt/error'
4
+ require_relative '../../../bolt/config/transport/base'
5
+
6
+ module Bolt
7
+ class Config
8
+ module Transport
9
+ class Jail < Base
10
+ OPTIONS = %w[
11
+ cleanup
12
+ host
13
+ interpreters
14
+ shell-command
15
+ tmpdir
16
+ user
17
+ ].concat(RUN_AS_OPTIONS).sort.freeze
18
+
19
+ DEFAULTS = {
20
+ 'cleanup' => true
21
+ }.freeze
22
+
23
+ private def validate
24
+ super
25
+
26
+ if @config['interpreters']
27
+ @config['interpreters'] = normalize_interpreters(@config['interpreters'])
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
data/lib/bolt/executor.rb CHANGED
@@ -14,6 +14,7 @@ require_relative '../bolt/result'
14
14
  require_relative '../bolt/result_set'
15
15
  # Load transports
16
16
  require_relative '../bolt/transport/docker'
17
+ require_relative '../bolt/transport/jail'
17
18
  require_relative '../bolt/transport/local'
18
19
  require_relative '../bolt/transport/lxd'
19
20
  require_relative '../bolt/transport/orch'
@@ -25,6 +26,7 @@ require_relative '../bolt/transport/winrm'
25
26
  module Bolt
26
27
  TRANSPORTS = {
27
28
  docker: Bolt::Transport::Docker,
29
+ jail: Bolt::Transport::Jail,
28
30
  local: Bolt::Transport::Local,
29
31
  lxd: Bolt::Transport::LXD,
30
32
  pcp: Bolt::Transport::Orch,
@@ -356,7 +356,7 @@ module Bolt
356
356
  if defined? conn.add_env_vars
357
357
  conn.add_env_vars(options[:environment])
358
358
  else
359
- env_decl = options[:environment].map do |env, val|
359
+ env_decl = '/usr/bin/env ' + options[:environment].map do |env, val|
360
360
  "#{env}=#{Shellwords.shellescape(val)}"
361
361
  end.join(' ')
362
362
  end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'logging'
4
+ require_relative '../../../bolt/node/errors'
5
+
6
+ module Bolt
7
+ module Transport
8
+ class Jail < Simple
9
+ class Connection
10
+ attr_reader :user, :target
11
+
12
+ def initialize(target)
13
+ raise Bolt::ValidationError, "Target #{target.safe_name} does not have a host" unless target.host
14
+ @target = target
15
+ @user = @target.user || ENV['USER'] || Etc.getlogin
16
+ @logger = Bolt::Logger.logger(target.safe_name)
17
+ @jail_info = {}
18
+ @logger.trace("Initializing jail connection to #{target.safe_name}")
19
+ end
20
+
21
+ def shell
22
+ @shell ||= Bolt::Shell::Bash.new(target, self)
23
+ end
24
+
25
+ def reset_cwd?
26
+ true
27
+ end
28
+
29
+ def jail_id
30
+ @jail_info['jid'].to_s
31
+ end
32
+
33
+ def jail_path
34
+ @jail_info['path']
35
+ end
36
+
37
+ def connect
38
+ output = JSON.parse(`jls --libxo=json`)
39
+ @jail_info = output['jail-information']['jail'].select { |jail| jail['hostname'] == target.host }.first
40
+ raise "Could not find a jail with name matching #{target.host}" if @jail_info.nil?
41
+ @logger.trace { "Opened session" }
42
+ true
43
+ rescue StandardError => e
44
+ raise Bolt::Node::ConnectError.new(
45
+ "Failed to connect to #{target.safe_name}: #{e.message}",
46
+ 'CONNECT_ERROR'
47
+ )
48
+ end
49
+
50
+ def execute(command)
51
+ args = ['-lU', @user]
52
+
53
+ jail_command = %w[jexec] + args + [jail_id] + Shellwords.split(command)
54
+ @logger.trace { "Executing #{jail_command.join(' ')}" }
55
+
56
+ Open3.popen3({}, *jail_command)
57
+ rescue StandardError
58
+ @logger.trace { "Command aborted" }
59
+ raise
60
+ end
61
+
62
+ def upload_file(source, destination)
63
+ @logger.trace { "Uploading #{source} to #{destination}" }
64
+ jail_destination = File.join(jail_path, destination)
65
+ FileUtils.cp(source, jail_destination)
66
+ rescue StandardError => e
67
+ raise Bolt::Node::FileError.new(e.message, 'WRITE_ERROR')
68
+ end
69
+
70
+ def download_file(source, destination, _download)
71
+ @logger.trace { "Downloading #{source} to #{destination}" }
72
+ jail_source = File.join(jail_path, source)
73
+ FileUtils.mkdir_p(destination)
74
+ FileUtils.cp(jail_source, destination)
75
+ rescue StandardError => e
76
+ raise Bolt::Node::FileError.new(e.message, 'WRITE_ERROR')
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../bolt/transport/simple'
4
+
5
+ module Bolt
6
+ module Transport
7
+ class Jail < Simple
8
+ def provided_features
9
+ ['shell']
10
+ end
11
+
12
+ def with_connection(target)
13
+ conn = Connection.new(target)
14
+ conn.connect
15
+ yield conn
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ require_relative 'jail/connection'
data/lib/bolt/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bolt
4
- VERSION = '3.26.2'
4
+ VERSION = '3.27.1'
5
5
  end
@@ -9,7 +9,11 @@
9
9
  "type": "object",
10
10
  "description": "JSON formatted parameters to be provided to task"
11
11
  },
12
- "target": { "$ref": "partial:target-any" }
12
+ "target": { "$ref": "partial:target-any" },
13
+ "timeout": {
14
+ "type": "integer",
15
+ "description": "Number of seconds to wait before abandoning the task execution on the tartet."
16
+ }
13
17
  },
14
18
  "required": ["target", "task"],
15
19
  "additionalProperties": false
@@ -9,7 +9,6 @@ require 'bolt/project'
9
9
  require 'bolt/target'
10
10
  require 'bolt_server/file_cache'
11
11
  require 'bolt_server/plugin'
12
- require 'bolt_server/plugin/puppet_connect_data'
13
12
  require 'bolt_server/request_error'
14
13
  require 'bolt/task/puppet_server'
15
14
  require 'json'
@@ -42,7 +41,6 @@ module BoltServer
42
41
  action-upload_file
43
42
  transport-ssh
44
43
  transport-winrm
45
- connect-data
46
44
  action-apply_prep
47
45
  action-apply
48
46
  ].freeze
@@ -126,7 +124,17 @@ module BoltServer
126
124
  end
127
125
  end
128
126
 
129
- def task_helper(target, task, parameters)
127
+ def unwrap_sensitive_results(result_set)
128
+ # Take a ResultSet and unwrap sensitive values
129
+ result_set.each do |result|
130
+ value = result.value
131
+ next unless value.is_a?(Hash)
132
+ next unless value.key?('_sensitive')
133
+ value['_sensitive'] = value['_sensitive'].unwrap
134
+ end
135
+ end
136
+
137
+ def task_helper(target, task, parameters, timeout = nil)
130
138
  # Wrap parameters marked with '"sensitive": true' in the task metadata with a
131
139
  # Sensitive wrapper type. This way it's not shown in logs.
132
140
  if (param_spec = task.parameters)
@@ -137,11 +145,20 @@ module BoltServer
137
145
  end
138
146
  end
139
147
 
140
- @executor.run_task(target, task, parameters).each do |result|
141
- value = result.value
142
- next unless value.is_a?(Hash)
143
- next unless value.key?('_sensitive')
144
- value['_sensitive'] = value['_sensitive'].unwrap
148
+ if timeout && timeout > 0
149
+ task_thread = Thread.new do
150
+ unwrap_sensitive_results(@executor.run_task(target, task, parameters))
151
+ end
152
+ # Wait for the timeout for the task to execute in the thread. If `join` times out, result will be nil.
153
+ if task_thread.join(timeout).nil?
154
+ task_thread.kill
155
+ raise Bolt::Error.new("Task execution on #{target.first.safe_name} timed out after #{timeout} seconds",
156
+ 'boltserver/task-timeout')
157
+ else
158
+ task_thread.value
159
+ end
160
+ else
161
+ unwrap_sensitive_results(@executor.run_task(target, task, parameters))
145
162
  end
146
163
  end
147
164
 
@@ -150,7 +167,7 @@ module BoltServer
150
167
 
151
168
  task_data = body['task']
152
169
  task = Bolt::Task::PuppetServer.new(task_data['name'], task_data['metadata'], task_data['files'], @file_cache)
153
- task_helper(target, task, body['parameters'] || {})
170
+ task_helper(target, task, body['parameters'] || {}, body['timeout'])
154
171
  end
155
172
 
156
173
  def extract_install_task(target)
@@ -825,53 +842,6 @@ module BoltServer
825
842
  [500, e.message]
826
843
  end
827
844
 
828
- # Returns a list of targets parsed from a Project inventory
829
- #
830
- # @param versioned_project [String] the versioned_project to compute the inventory from
831
- post '/project_inventory_targets' do
832
- content_type :json
833
- body = JSON.parse(request.body.read)
834
- validate_schema(@schemas["connect-data"], body)
835
- in_bolt_project(body['versioned_project']) do |context|
836
- if context[:config].inventoryfile &&
837
- context[:config].project.inventory_file.to_s !=
838
- context[:config].inventoryfile
839
- raise Bolt::ValidationError, "Project inventory must be defined in the " \
840
- "inventory.yaml file at the root of the project directory"
841
- end
842
-
843
- Bolt::Util.validate_file('inventory file', context[:config].project.inventory_file)
844
-
845
- begin
846
- # Set the default puppet_library plugin hook if it has not already been
847
- # set
848
- context[:config].data['plugin-hooks']['puppet_library'] ||= {
849
- 'plugin' => 'task',
850
- 'task' => 'puppet_agent::install',
851
- 'parameters' => {
852
- 'stop_service' => true
853
- }
854
- }
855
-
856
- connect_plugin = BoltServer::Plugin::PuppetConnectData.new(body['puppet_connect_data'])
857
- plugins = Bolt::Plugin.new(context[:config], context[:pal], load_plugins: false)
858
- plugins.add_plugin(connect_plugin)
859
- %w[aws_inventory azure_inventory gcloud_inventory].each do |plugin_name|
860
- plugins.add_module_plugin(plugin_name) if plugins.known_plugin?(plugin_name)
861
- end
862
- inventory = Bolt::Inventory.from_config(context[:config], plugins)
863
- target_list = inventory.get_targets('all').map do |targ|
864
- targ.to_h.merge({ 'transport' => targ.transport, 'plugin_hooks' => targ.plugin_hooks })
865
- end
866
- rescue Bolt::Plugin::PluginError::LoadingDisabled => e
867
- msg = "Cannot load plugin #{e.details['plugin_name']}: plugin not supported"
868
- raise BoltServer::Plugin::PluginNotSupported.new(msg, e.details['plugin_name'])
869
- end
870
-
871
- [200, target_list.to_json]
872
- end
873
- end
874
-
875
845
  # Returns the base64 encoded tar archive of plugin code that is needed to calculate
876
846
  # custom facts
877
847
  #
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bolt
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.26.2
4
+ version: 3.27.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-11-16 00:00:00.000000000 Z
11
+ date: 2023-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -59,6 +59,9 @@ dependencies:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: '1.0'
62
+ - - "<"
63
+ - !ruby/object:Gem::Version
64
+ version: 1.2.0
62
65
  type: :runtime
63
66
  prerelease: false
64
67
  version_requirements: !ruby/object:Gem::Requirement
@@ -66,6 +69,9 @@ dependencies:
66
69
  - - "~>"
67
70
  - !ruby/object:Gem::Version
68
71
  version: '1.0'
72
+ - - "<"
73
+ - !ruby/object:Gem::Version
74
+ version: 1.2.0
69
75
  - !ruby/object:Gem::Dependency
70
76
  name: ffi
71
77
  requirement: !ruby/object:Gem::Requirement
@@ -165,7 +171,7 @@ dependencies:
165
171
  version: '4.0'
166
172
  - - "<"
167
173
  - !ruby/object:Gem::Version
168
- version: '7.0'
174
+ version: '8.0'
169
175
  type: :runtime
170
176
  prerelease: false
171
177
  version_requirements: !ruby/object:Gem::Requirement
@@ -175,7 +181,7 @@ dependencies:
175
181
  version: '4.0'
176
182
  - - "<"
177
183
  - !ruby/object:Gem::Version
178
- version: '7.0'
184
+ version: '8.0'
179
185
  - !ruby/object:Gem::Dependency
180
186
  name: net-ssh-krb
181
187
  requirement: !ruby/object:Gem::Requirement
@@ -374,16 +380,16 @@ dependencies:
374
380
  name: puppetlabs_spec_helper
375
381
  requirement: !ruby/object:Gem::Requirement
376
382
  requirements:
377
- - - "<="
383
+ - - "~>"
378
384
  - !ruby/object:Gem::Version
379
- version: 2.15.0
385
+ version: '5.0'
380
386
  type: :development
381
387
  prerelease: false
382
388
  version_requirements: !ruby/object:Gem::Requirement
383
389
  requirements:
384
- - - "<="
390
+ - - "~>"
385
391
  - !ruby/object:Gem::Version
386
- version: 2.15.0
392
+ version: '5.0'
387
393
  - !ruby/object:Gem::Dependency
388
394
  name: rake
389
395
  requirement: !ruby/object:Gem::Requirement
@@ -509,6 +515,7 @@ files:
509
515
  - lib/bolt/config/options.rb
510
516
  - lib/bolt/config/transport/base.rb
511
517
  - lib/bolt/config/transport/docker.rb
518
+ - lib/bolt/config/transport/jail.rb
512
519
  - lib/bolt/config/transport/local.rb
513
520
  - lib/bolt/config/transport/lxd.rb
514
521
  - lib/bolt/config/transport/options.rb
@@ -606,6 +613,8 @@ files:
606
613
  - lib/bolt/transport/base.rb
607
614
  - lib/bolt/transport/docker.rb
608
615
  - lib/bolt/transport/docker/connection.rb
616
+ - lib/bolt/transport/jail.rb
617
+ - lib/bolt/transport/jail/connection.rb
609
618
  - lib/bolt/transport/local.rb
610
619
  - lib/bolt/transport/local/connection.rb
611
620
  - lib/bolt/transport/lxd.rb
@@ -640,7 +649,6 @@ files:
640
649
  - lib/bolt_server/schemas/action-run_script.json
641
650
  - lib/bolt_server/schemas/action-run_task.json
642
651
  - lib/bolt_server/schemas/action-upload_file.json
643
- - lib/bolt_server/schemas/connect-data.json
644
652
  - lib/bolt_server/schemas/partials/target-any.json
645
653
  - lib/bolt_server/schemas/partials/target-ssh.json
646
654
  - lib/bolt_server/schemas/partials/target-winrm.json
@@ -1,25 +0,0 @@
1
- {
2
- "$schema": "http://json-schema.org/draft-04/schema#",
3
- "title": "project_inventory_targets connect plugin data",
4
- "description": "POST project_inventory_targets connect plugin data",
5
- "type": "object",
6
- "properties": {
7
- "puppet_connect_data": {
8
- "type": "object",
9
- "patternProperties": {
10
- ".*": {
11
- "type": "object",
12
- "properties": {
13
- "value": {}
14
- },
15
- "required": ["value"]
16
- }
17
- },
18
- "additionalProperties": false
19
- },
20
- "versioned_project": {
21
- "type": "string"
22
- }
23
- },
24
- "required": ["puppet_connect_data", "versioned_project"]
25
- }