bolt 2.1.0 → 2.2.0
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 +4 -4
- data/Puppetfile +5 -5
- data/bolt-modules/boltlib/lib/puppet/functions/run_command.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/run_plan.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/run_script.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +1 -1
- data/bolt-modules/boltlib/lib/puppet/functions/upload_file.rb +1 -1
- data/lib/bolt/applicator.rb +2 -2
- data/lib/bolt/bolt_option_parser.rb +1 -1
- data/lib/bolt/cli.rb +1 -1
- data/lib/bolt/config.rb +201 -206
- data/lib/bolt/config/transport/base.rb +142 -0
- data/lib/bolt/config/transport/docker.rb +42 -0
- data/lib/bolt/config/transport/local.rb +73 -0
- data/lib/bolt/config/transport/orch.rb +47 -0
- data/lib/bolt/config/transport/remote.rb +25 -0
- data/lib/bolt/config/transport/ssh.rb +105 -0
- data/lib/bolt/config/transport/winrm.rb +80 -0
- data/lib/bolt/executor.rb +17 -0
- data/lib/bolt/inventory.rb +12 -5
- data/lib/bolt/inventory/group.rb +1 -1
- data/lib/bolt/inventory/inventory.rb +16 -22
- data/lib/bolt/inventory/target.rb +26 -29
- data/lib/bolt/plugin.rb +5 -5
- data/lib/bolt/plugin/module.rb +1 -1
- data/lib/bolt/plugin/pkcs7.rb +1 -1
- data/lib/bolt/result.rb +1 -1
- data/lib/bolt/target.rb +5 -2
- data/lib/bolt/transport/base.rb +0 -18
- data/lib/bolt/transport/docker.rb +0 -26
- data/lib/bolt/transport/local.rb +0 -30
- data/lib/bolt/transport/local_windows.rb +4 -36
- data/lib/bolt/transport/orch.rb +0 -20
- data/lib/bolt/transport/remote.rb +0 -20
- data/lib/bolt/transport/ssh.rb +0 -85
- data/lib/bolt/transport/sudoable.rb +0 -7
- data/lib/bolt/transport/winrm.rb +0 -66
- data/lib/bolt/util.rb +11 -0
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt_server/transport_app.rb +1 -0
- data/lib/bolt_spec/plans.rb +1 -1
- data/lib/bolt_spec/plans/action_stubs/command_stub.rb +1 -1
- data/lib/bolt_spec/plans/action_stubs/script_stub.rb +1 -1
- data/lib/bolt_spec/plans/action_stubs/task_stub.rb +2 -2
- data/lib/bolt_spec/plans/action_stubs/upload_stub.rb +1 -1
- data/lib/bolt_spec/run.rb +1 -1
- data/libexec/apply_catalog.rb +1 -1
- data/libexec/custom_facts.rb +1 -1
- data/libexec/query_resources.rb +1 -1
- metadata +9 -2
@@ -0,0 +1,142 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bolt/error'
|
4
|
+
require 'bolt/util'
|
5
|
+
|
6
|
+
module Bolt
|
7
|
+
class Config
|
8
|
+
module Transport
|
9
|
+
class Base
|
10
|
+
attr_reader :input
|
11
|
+
|
12
|
+
def initialize(data = {}, boltdir = nil)
|
13
|
+
assert_hash_or_config(data)
|
14
|
+
@input = data
|
15
|
+
@resolved = !Bolt::Util.references?(input)
|
16
|
+
@config = resolved? ? Bolt::Util.deep_merge(defaults, filter(input)) : defaults
|
17
|
+
@boltdir = boltdir
|
18
|
+
|
19
|
+
validate if resolved?
|
20
|
+
end
|
21
|
+
|
22
|
+
# Accessor methods
|
23
|
+
# These are mostly all wrappers for same-named Hash methods, but they all
|
24
|
+
# require that the config options be fully-resolved before accessing data
|
25
|
+
def [](key)
|
26
|
+
resolved_config[key]
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_h
|
30
|
+
resolved_config
|
31
|
+
end
|
32
|
+
|
33
|
+
def fetch(*args)
|
34
|
+
resolved_config.fetch(*args)
|
35
|
+
end
|
36
|
+
|
37
|
+
def include?(args)
|
38
|
+
resolved_config.include?(args)
|
39
|
+
end
|
40
|
+
|
41
|
+
def dig(*keys)
|
42
|
+
resolved_config.dig(*keys)
|
43
|
+
end
|
44
|
+
|
45
|
+
private def resolved_config
|
46
|
+
unless resolved?
|
47
|
+
raise Bolt::Error.new(
|
48
|
+
"Unable to access transport config, #{self.class} has unresolved config: #{input.inspect}",
|
49
|
+
'bolt/unresolved-transport-config'
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
@config
|
54
|
+
end
|
55
|
+
|
56
|
+
# Merges the original input data with the provided data, which is either a hash
|
57
|
+
# or transport config object. Accepts multiple inputs.
|
58
|
+
def merge(*data)
|
59
|
+
merged = data.compact.inject(@input) do |acc, layer|
|
60
|
+
assert_hash_or_config(layer)
|
61
|
+
layer_data = layer.is_a?(self.class) ? layer.input : layer
|
62
|
+
Bolt::Util.deep_merge(acc, layer_data)
|
63
|
+
end
|
64
|
+
|
65
|
+
self.class.new(merged, @boltdir)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Resolve any references in the input data, then remerge it with the defaults
|
69
|
+
# and validate all values
|
70
|
+
def resolve(plugins)
|
71
|
+
@input = plugins.resolve_references(input)
|
72
|
+
@config = Bolt::Util.deep_merge(defaults, filter(input))
|
73
|
+
@resolved = true
|
74
|
+
|
75
|
+
validate
|
76
|
+
end
|
77
|
+
|
78
|
+
def resolved?
|
79
|
+
@resolved
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.options
|
83
|
+
unless defined? self::OPTIONS
|
84
|
+
raise NotImplementedError,
|
85
|
+
"Constant OPTIONS must be implemented by the transport config class"
|
86
|
+
end
|
87
|
+
self::OPTIONS
|
88
|
+
end
|
89
|
+
|
90
|
+
private def defaults
|
91
|
+
unless defined? self.class::DEFAULTS
|
92
|
+
raise NotImplementedError,
|
93
|
+
"Constant DEFAULTS must be implemented by the transport config class"
|
94
|
+
end
|
95
|
+
self.class::DEFAULTS
|
96
|
+
end
|
97
|
+
|
98
|
+
private def filter(unfiltered)
|
99
|
+
unfiltered.slice(*self.class.options.keys)
|
100
|
+
end
|
101
|
+
|
102
|
+
private def assert_hash_or_config(data)
|
103
|
+
return if data.is_a?(Hash) || data.is_a?(self.class)
|
104
|
+
raise Bolt::ValidationError,
|
105
|
+
"Transport config must be a Hash or #{self.class}, received #{data.class} #{data.inspect}"
|
106
|
+
end
|
107
|
+
|
108
|
+
private def normalize_interpreters(interpreters)
|
109
|
+
Bolt::Util.walk_keys(interpreters) do |key|
|
110
|
+
key.chars[0] == '.' ? key : '.' + key
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Validation defaults to just asserting the option types
|
115
|
+
private def validate
|
116
|
+
assert_type
|
117
|
+
end
|
118
|
+
|
119
|
+
# Validates that each option is the correct type. Types are loaded from the OPTIONS hash.
|
120
|
+
private def assert_type
|
121
|
+
@config.each_pair do |opt, val|
|
122
|
+
next unless (type = self.class.options.dig(opt, :type))
|
123
|
+
|
124
|
+
# Options that accept a Boolean value are indicated by the type TrueClass, so we
|
125
|
+
# need some special handling here to check if the value is either true or false.
|
126
|
+
if type == TrueClass
|
127
|
+
unless [true, false].include?(val)
|
128
|
+
raise Bolt::ValidationError,
|
129
|
+
"#{opt} must be a Boolean true or false, received #{val.class} #{val.inspect}"
|
130
|
+
end
|
131
|
+
else
|
132
|
+
unless val.nil? || val.is_a?(type)
|
133
|
+
raise Bolt::ValidationError,
|
134
|
+
"#{opt} must be a #{type}, received #{val.class} #{val.inspect}"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bolt/error'
|
4
|
+
require 'bolt/config/transport/base'
|
5
|
+
|
6
|
+
module Bolt
|
7
|
+
class Config
|
8
|
+
module Transport
|
9
|
+
class Docker < Base
|
10
|
+
OPTIONS = {
|
11
|
+
"host" => { type: String,
|
12
|
+
desc: "Host name." },
|
13
|
+
"interpreters" => { type: Hash,
|
14
|
+
desc: "A map of an extension name to the absolute path of an executable, "\
|
15
|
+
"enabling you to override the shebang defined in a task executable. The "\
|
16
|
+
"extension can optionally be specified with the `.` character (`.py` and "\
|
17
|
+
"`py` both map to a task executable `task.py`) and the extension is case "\
|
18
|
+
"sensitive. When a target's name is `localhost`, Ruby tasks run with the "\
|
19
|
+
"Bolt Ruby interpreter by default." },
|
20
|
+
"service-url" => { type: String,
|
21
|
+
desc: "URL of the Docker host used for API requests." },
|
22
|
+
"shell-command" => { type: String,
|
23
|
+
desc: "A shell command to wrap any Docker exec commands in, such as `bash -lc`." },
|
24
|
+
"tmpdir" => { type: String,
|
25
|
+
desc: "The directory to upload and execute temporary files on the target." },
|
26
|
+
"tty" => { type: TrueClass,
|
27
|
+
desc: "Whether to enable tty on exec commands." }
|
28
|
+
}.freeze
|
29
|
+
|
30
|
+
DEFAULTS = {}.freeze
|
31
|
+
|
32
|
+
private def validate
|
33
|
+
super
|
34
|
+
|
35
|
+
if @config['interpreters']
|
36
|
+
@config['interpreters'] = normalize_interpreters(@config['interpreters'])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bolt/error'
|
4
|
+
require 'bolt/config/transport/base'
|
5
|
+
|
6
|
+
module Bolt
|
7
|
+
class Config
|
8
|
+
module Transport
|
9
|
+
class Local < Base
|
10
|
+
OPTIONS = {
|
11
|
+
"interpreters" => { type: Hash,
|
12
|
+
desc: "A map of an extension name to the absolute path of an executable, "\
|
13
|
+
"enabling you to override the shebang defined in a task executable. The "\
|
14
|
+
"extension can optionally be specified with the `.` character (`.py` and "\
|
15
|
+
"`py` both map to a task executable `task.py`) and the extension is case "\
|
16
|
+
"sensitive. When a target's name is `localhost`, Ruby tasks run with the "\
|
17
|
+
"Bolt Ruby interpreter by default." },
|
18
|
+
"run-as" => { type: String,
|
19
|
+
desc: "A different user to run commands as after login." },
|
20
|
+
"run-as-command" => { type: Array,
|
21
|
+
desc: "The command to elevate permissions. Bolt appends the user and command "\
|
22
|
+
"strings to the configured `run-as-command` before running it on the target. "\
|
23
|
+
"This command must not require an interactive password prompt, and the "\
|
24
|
+
"`sudo-password` option is ignored when `run-as-command` is specified. The "\
|
25
|
+
"`run-as-command` must be specified as an array." },
|
26
|
+
"sudo-executable" => { type: String,
|
27
|
+
desc: "The executable to use when escalating to the configured `run-as` user. This "\
|
28
|
+
"is useful when you want to escalate using the configured `sudo-password`, "\
|
29
|
+
"since `run-as-command` does not use `sudo-password` or support prompting. "\
|
30
|
+
"The command executed on the target is `<sudo-executable> -S -u <user> -p "\
|
31
|
+
"custom_bolt_prompt <command>`. **This option is experimental.**" },
|
32
|
+
"sudo-password" => { type: String,
|
33
|
+
desc: "Password to use when changing users via `run-as`." },
|
34
|
+
"tmpdir" => { type: String,
|
35
|
+
desc: "The directory to copy and execute temporary files." }
|
36
|
+
}.freeze
|
37
|
+
|
38
|
+
WINDOWS_OPTIONS = {
|
39
|
+
"interpreters" => { type: Hash,
|
40
|
+
desc: "A map of an extension name to the absolute path of an executable, "\
|
41
|
+
"enabling you to override the shebang defined in a task executable. The "\
|
42
|
+
"extension can optionally be specified with the `.` character (`.py` and "\
|
43
|
+
"`py` both map to a task executable `task.py`) and the extension is case "\
|
44
|
+
"sensitive. When a target's name is `localhost`, Ruby tasks run with the "\
|
45
|
+
"Bolt Ruby interpreter by default." },
|
46
|
+
"tmpdir" => { type: String,
|
47
|
+
desc: "The directory to copy and execute temporary files." }
|
48
|
+
}.freeze
|
49
|
+
|
50
|
+
DEFAULTS = {}.freeze
|
51
|
+
|
52
|
+
def self.options
|
53
|
+
Bolt::Util.windows? ? WINDOWS_OPTIONS : OPTIONS
|
54
|
+
end
|
55
|
+
|
56
|
+
private def validate
|
57
|
+
super
|
58
|
+
|
59
|
+
if @config['interpreters']
|
60
|
+
@config['interpreters'] = normalize_interpreters(@config['interpreters'])
|
61
|
+
end
|
62
|
+
|
63
|
+
if (run_as_cmd = @config['run-as-command'])
|
64
|
+
unless run_as_cmd.all? { |n| n.is_a?(String) }
|
65
|
+
raise Bolt::ValidationError,
|
66
|
+
"run-as-command must be an Array of Strings, received #{run_as_cmd.class} #{run_as_cmd.inspect}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bolt/error'
|
4
|
+
require 'bolt/config/transport/base'
|
5
|
+
|
6
|
+
module Bolt
|
7
|
+
class Config
|
8
|
+
module Transport
|
9
|
+
class Orch < Base
|
10
|
+
OPTIONS = {
|
11
|
+
"cacert" => { type: String,
|
12
|
+
desc: "The path to the CA certificate." },
|
13
|
+
"host" => { type: String,
|
14
|
+
desc: "Host name." },
|
15
|
+
"job-poll-interval" => { type: Integer,
|
16
|
+
desc: "Set interval to poll orchestrator for job status." },
|
17
|
+
"job-poll-timeout" => { type: Integer,
|
18
|
+
desc: "Set time to wait for orchestrator job status." },
|
19
|
+
"service-url" => { type: String,
|
20
|
+
desc: "The URL of the orchestrator API." },
|
21
|
+
"task-environment" => { type: String,
|
22
|
+
desc: "The environment the orchestrator loads task code from." },
|
23
|
+
"token-file" => { type: String,
|
24
|
+
desc: "The path to the token file." }
|
25
|
+
}.freeze
|
26
|
+
|
27
|
+
DEFAULTS = {
|
28
|
+
"task-environment" => "production"
|
29
|
+
}.freeze
|
30
|
+
|
31
|
+
private def validate
|
32
|
+
super
|
33
|
+
|
34
|
+
if @config['cacert']
|
35
|
+
@config['cacert'] = File.expand_path(@config['cacert'], @boltdir)
|
36
|
+
Bolt::Util.validate_file('cacert', @config['cacert'])
|
37
|
+
end
|
38
|
+
|
39
|
+
if @config['token-file']
|
40
|
+
@config['token-file'] = File.expand_path(@config['token-file'], @boltdir)
|
41
|
+
Bolt::Util.validate_file('token-file', @config['token-file'])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bolt/error'
|
4
|
+
require 'bolt/config/transport/base'
|
5
|
+
|
6
|
+
module Bolt
|
7
|
+
class Config
|
8
|
+
module Transport
|
9
|
+
class Remote < Base
|
10
|
+
OPTIONS = {
|
11
|
+
"run-on" => { type: String,
|
12
|
+
desc: "The proxy target that the task executes on." }
|
13
|
+
}.freeze
|
14
|
+
|
15
|
+
DEFAULTS = {
|
16
|
+
"run-on" => "localhost"
|
17
|
+
}.freeze
|
18
|
+
|
19
|
+
private def filter(unfiltered)
|
20
|
+
unfiltered
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bolt/error'
|
4
|
+
require 'bolt/config/transport/base'
|
5
|
+
|
6
|
+
module Bolt
|
7
|
+
class Config
|
8
|
+
module Transport
|
9
|
+
class SSH < Base
|
10
|
+
OPTIONS = {
|
11
|
+
"connect-timeout" => { type: Integer,
|
12
|
+
desc: "How long to wait when establishing connections." },
|
13
|
+
"disconnect-timeout" => { type: Integer,
|
14
|
+
desc: "How long to wait before force-closing a connection." },
|
15
|
+
"host" => { type: String,
|
16
|
+
desc: "Host name." },
|
17
|
+
"host-key-check" => { type: TrueClass,
|
18
|
+
desc: "Whether to perform host key validation when connecting." },
|
19
|
+
"interpreters" => { type: Hash,
|
20
|
+
desc: "A map of an extension name to the absolute path of an executable, "\
|
21
|
+
"enabling you to override the shebang defined in a task executable. The "\
|
22
|
+
"extension can optionally be specified with the `.` character (`.py` and "\
|
23
|
+
"`py` both map to a task executable `task.py`) and the extension is case "\
|
24
|
+
"sensitive. When a target's name is `localhost`, Ruby tasks run with the "\
|
25
|
+
"Bolt Ruby interpreter by default." },
|
26
|
+
"load-config" => { type: TrueClass,
|
27
|
+
desc: "Whether to load system SSH configuration." },
|
28
|
+
"password" => { type: String,
|
29
|
+
desc: "Login password." },
|
30
|
+
"port" => { type: Integer,
|
31
|
+
desc: "Connection port." },
|
32
|
+
"private-key" => { desc: "Either the path to the private key file to use for authentication, or a "\
|
33
|
+
"hash with the key `key-data` and the contents of the private key." },
|
34
|
+
"proxyjump" => { type: String,
|
35
|
+
desc: "A jump host to proxy connections through, and an optional user to "\
|
36
|
+
"connect with." },
|
37
|
+
"run-as" => { type: String,
|
38
|
+
desc: "A different user to run commands as after login." },
|
39
|
+
"run-as-command" => { type: Array,
|
40
|
+
desc: "The command to elevate permissions. Bolt appends the user and command "\
|
41
|
+
"strings to the configured `run-as-command` before running it on the "\
|
42
|
+
"target. This command must not require an interactive password prompt, "\
|
43
|
+
"and the `sudo-password` option is ignored when `run-as-command` is "\
|
44
|
+
"specified. The `run-as-command` must be specified as an array." },
|
45
|
+
"script-dir" => { type: String,
|
46
|
+
desc: "The subdirectory of the tmpdir to use in place of a randomized "\
|
47
|
+
"subdirectory for uploading and executing temporary files on the "\
|
48
|
+
"target. It's expected that this directory already exists as a subdir "\
|
49
|
+
"of tmpdir, which is either configured or defaults to `/tmp`." },
|
50
|
+
"sudo-executable" => { type: String,
|
51
|
+
desc: "The executable to use when escalating to the configured `run-as` "\
|
52
|
+
"user. This is useful when you want to escalate using the configured "\
|
53
|
+
"`sudo-password`, since `run-as-command` does not use `sudo-password` "\
|
54
|
+
"or support prompting. The command executed on the target is "\
|
55
|
+
"`<sudo-executable> -S -u <user> -p custom_bolt_prompt <command>`. "\
|
56
|
+
"**This option is experimental.**" },
|
57
|
+
"sudo-password" => { type: String,
|
58
|
+
desc: "Password to use when changing users via `run-as`." },
|
59
|
+
"tmpdir" => { type: String,
|
60
|
+
desc: "The directory to upload and execute temporary files on the target." },
|
61
|
+
"tty" => { type: TrueClass,
|
62
|
+
desc: "Request a pseudo tty for the session. This option is generally "\
|
63
|
+
"only used in conjunction with the `run-as` option when the sudoers "\
|
64
|
+
"policy requires a `tty`." },
|
65
|
+
"user" => { type: String,
|
66
|
+
desc: "Login user." }
|
67
|
+
}.freeze
|
68
|
+
|
69
|
+
DEFAULTS = {
|
70
|
+
"connect-timeout" => 10,
|
71
|
+
"tty" => false,
|
72
|
+
"load-config" => true,
|
73
|
+
"disconnect-timeout" => 5
|
74
|
+
}.freeze
|
75
|
+
|
76
|
+
private def validate
|
77
|
+
super
|
78
|
+
|
79
|
+
if (key_opt = @config['private-key'])
|
80
|
+
unless key_opt.instance_of?(String) || (key_opt.instance_of?(Hash) && key_opt.include?('key-data'))
|
81
|
+
raise Bolt::ValidationError,
|
82
|
+
"private-key option must be a path to a private key file or a Hash containing the 'key-data', "\
|
83
|
+
"received #{key_opt.class} #{key_opt}"
|
84
|
+
end
|
85
|
+
|
86
|
+
if key_opt.instance_of?(String)
|
87
|
+
@config['private-key'] = File.expand_path(key_opt, @boltdir)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
if @config['interpreters']
|
92
|
+
@config['interpreters'] = normalize_interpreters(@config['interpreters'])
|
93
|
+
end
|
94
|
+
|
95
|
+
if (run_as_cmd = @config['run-as-command'])
|
96
|
+
unless run_as_cmd.all? { |n| n.is_a?(String) }
|
97
|
+
raise Bolt::ValidationError,
|
98
|
+
"run-as-command must be an Array of Strings, received #{run_as_cmd.class} #{run_as_cmd.inspect}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bolt/error'
|
4
|
+
require 'bolt/config/transport/base'
|
5
|
+
|
6
|
+
module Bolt
|
7
|
+
class Config
|
8
|
+
module Transport
|
9
|
+
class WinRM < Base
|
10
|
+
OPTIONS = {
|
11
|
+
"cacert" => { type: String,
|
12
|
+
desc: "The path to the CA certificate." },
|
13
|
+
"connect-timeout" => { type: Integer,
|
14
|
+
desc: "How long Bolt should wait when establishing connections." },
|
15
|
+
"extensions" => { type: Array,
|
16
|
+
desc: "List of file extensions that are accepted for scripts or tasks. "\
|
17
|
+
"Scripts with these file extensions rely on the target's file type "\
|
18
|
+
"association to run. For example, if Python is installed on the system, "\
|
19
|
+
"a `.py` script runs with `python.exe`. The extensions `.ps1`, `.rb`, and "\
|
20
|
+
"`.pp` are always allowed and run via hard-coded executables." },
|
21
|
+
"file-protocol" => { type: String,
|
22
|
+
desc: "Which file transfer protocol to use. Either `winrm` or `smb`. Using `smb` is "\
|
23
|
+
"recommended for large file transfers." },
|
24
|
+
"host" => { type: String,
|
25
|
+
desc: "Host name." },
|
26
|
+
"interpreters" => { type: Hash,
|
27
|
+
desc: "A map of an extension name to the absolute path of an executable, "\
|
28
|
+
"enabling you to override the shebang defined in a task executable. The "\
|
29
|
+
"extension can optionally be specified with the `.` character (`.py` and "\
|
30
|
+
"`py` both map to a task executable `task.py`) and the extension is case "\
|
31
|
+
"sensitive. When a target's name is `localhost`, Ruby tasks run with the "\
|
32
|
+
"Bolt Ruby interpreter by default." },
|
33
|
+
"password" => { type: String,
|
34
|
+
desc: "Login password. **Required unless using Kerberos.**" },
|
35
|
+
"port" => { type: Integer,
|
36
|
+
desc: "Connection port." },
|
37
|
+
"realm" => { type: String,
|
38
|
+
desc: "Kerberos realm (Active Directory domain) to authenticate against." },
|
39
|
+
"smb-port" => { type: Integer,
|
40
|
+
desc: "With file-protocol set to smb, this is the port to establish a "\
|
41
|
+
"connection on." },
|
42
|
+
"ssl" => { type: TrueClass,
|
43
|
+
desc: "When true, Bolt uses secure https connections for WinRM." },
|
44
|
+
"ssl-verify" => { type: TrueClass,
|
45
|
+
desc: "When true, verifies the targets certificate matches the cacert." },
|
46
|
+
"tmpdir" => { type: String,
|
47
|
+
desc: "The directory to upload and execute temporary files on the target." },
|
48
|
+
"user" => { type: String,
|
49
|
+
desc: "Login user. **Required unless using Kerberos.**" }
|
50
|
+
}.freeze
|
51
|
+
|
52
|
+
DEFAULTS = {
|
53
|
+
"connect-timeout" => 10,
|
54
|
+
"ssl" => true,
|
55
|
+
"ssl-verify" => true,
|
56
|
+
"file-protocol" => "winrm"
|
57
|
+
}.freeze
|
58
|
+
|
59
|
+
private def validate
|
60
|
+
super
|
61
|
+
|
62
|
+
if @config['ssl']
|
63
|
+
if @config['file-protocol'] == 'smb'
|
64
|
+
raise Bolt::ValidationError, "SMB file transfers are not allowed with SSL enabled"
|
65
|
+
end
|
66
|
+
|
67
|
+
if @config['cacert']
|
68
|
+
@config['cacert'] = File.expand_path(@config['cacert'], @boltdir)
|
69
|
+
Bolt::Util.validate_file('cacert', @config['cacert'])
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
if @config['interpreters']
|
74
|
+
@config['interpreters'] = normalize_interpreters(@config['interpreters'])
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|