bolt 1.27.1 → 1.28.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/bolt-modules/boltlib/lib/puppet/functions/get_targets.rb +4 -0
- data/lib/bolt/analytics.rb +14 -2
- data/lib/bolt/bolt_option_parser.rb +116 -116
- data/lib/bolt/config.rb +3 -3
- data/lib/bolt/pal/yaml_plan/evaluator.rb +2 -0
- data/lib/bolt/pal/yaml_plan/step/resources.rb +7 -0
- data/lib/bolt/plugin.rb +3 -1
- data/lib/bolt/plugin/aws.rb +3 -3
- data/lib/bolt/plugin/vault.rb +206 -0
- data/lib/bolt/transport/ssh.rb +9 -6
- data/lib/bolt/transport/ssh/connection.rb +5 -1
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt_server/schemas/partials/target-ssh.json +4 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a2d33a034fb69edd25b761aec5e21075aa9ad9f0ccce67122994a2e24dda01f4
|
4
|
+
data.tar.gz: '0348c1d2ed663a0c3556795017c219a88c4e432788fe10e8d75bb1f03f0eed89'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b842c4a35c334729e47f361ea5be9a0467934d1afc718cec50d117f6573f1a2024eac84e4049730c02bd6cc97158dadc7c4ce1d6adff207efbdc103ffc4f0560
|
7
|
+
data.tar.gz: 470115a05e6edd058de12934e48e77441105cd83baeadca192d7bf7591b2e5f2bef998164614bee9cbebe0b511fe7507a8dcd61b0fbb19810e75e59bb55c7900
|
@@ -3,6 +3,10 @@
|
|
3
3
|
require 'bolt/error'
|
4
4
|
|
5
5
|
# Parses common ways of referring to targets and returns an array of Targets.
|
6
|
+
#
|
7
|
+
# **NOTE:** Calling `get_targets` inside an `apply` block with a
|
8
|
+
# version 2 inventory creates a new Target object.
|
9
|
+
# `get_targets('all')` returns an empty array.
|
6
10
|
Puppet::Functions.create_function(:get_targets) do
|
7
11
|
# @param names A pattern or array of patterns identifying a set of targets.
|
8
12
|
# @return A list of unique Targets resolved from any target URIs and groups.
|
data/lib/bolt/analytics.rb
CHANGED
@@ -29,7 +29,7 @@ module Bolt
|
|
29
29
|
def self.build_client
|
30
30
|
logger = Logging.logger[self]
|
31
31
|
config_file = File.expand_path('~/.puppetlabs/bolt/analytics.yaml')
|
32
|
-
config = load_config(config_file)
|
32
|
+
config = load_config(config_file, logger)
|
33
33
|
|
34
34
|
if config['disabled'] || ENV['BOLT_DISABLE_ANALYTICS']
|
35
35
|
logger.debug "Analytics opt-out is set, analytics will be disabled"
|
@@ -47,10 +47,22 @@ module Bolt
|
|
47
47
|
NoopClient.new
|
48
48
|
end
|
49
49
|
|
50
|
-
def self.load_config(filename)
|
50
|
+
def self.load_config(filename, logger)
|
51
51
|
if File.exist?(filename)
|
52
52
|
YAML.load_file(filename)
|
53
53
|
else
|
54
|
+
unless ENV['BOLT_DISABLE_ANALYTICS']
|
55
|
+
logger.warn <<~ANALYTICS
|
56
|
+
Bolt collects data about how you use it. You can opt out of providing this data.
|
57
|
+
|
58
|
+
To disable analytics data collection, add this line to ~/.puppetlabs/bolt/analytics.yaml :
|
59
|
+
disabled: true
|
60
|
+
|
61
|
+
Read more about what data Bolt collects and why here:
|
62
|
+
https://puppet.com/docs/bolt/latest/bolt_installing.html#concept-8242
|
63
|
+
ANALYTICS
|
64
|
+
end
|
65
|
+
|
54
66
|
{}
|
55
67
|
end
|
56
68
|
end
|
@@ -83,181 +83,181 @@ module Bolt
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def self.examples(cmd, desc)
|
86
|
-
|
87
|
-
#{desc} a Windows host via WinRM, providing for the password
|
88
|
-
|
89
|
-
#{desc} the local machine, a Linux host via SSH, and hosts from a group specified in an inventory file
|
90
|
-
|
91
|
-
#{desc} Windows hosts queried from PuppetDB via WinRM as a domain user, prompting for the password
|
92
|
-
|
93
|
-
EXAMP
|
86
|
+
<<~EXAMP
|
87
|
+
#{desc} a Windows host via WinRM, providing for the password
|
88
|
+
bolt #{cmd} -n winrm://winhost -u Administrator -p
|
89
|
+
#{desc} the local machine, a Linux host via SSH, and hosts from a group specified in an inventory file
|
90
|
+
bolt #{cmd} -n localhost,nixhost,node_group
|
91
|
+
#{desc} Windows hosts queried from PuppetDB via WinRM as a domain user, prompting for the password
|
92
|
+
bolt #{cmd} -q 'inventory[certname] { facts.os.family = "windows" }' --transport winrm -u 'domain\\Administrator' -p
|
93
|
+
EXAMP
|
94
94
|
end
|
95
95
|
|
96
|
-
BANNER =
|
97
|
-
Usage: bolt <subcommand> <action>
|
98
|
-
|
99
|
-
Available subcommands:
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
Run `bolt <subcommand> --help` to view specific examples.
|
119
|
-
|
120
|
-
Available options are:
|
96
|
+
BANNER = <<~HELP
|
97
|
+
Usage: bolt <subcommand> <action>
|
98
|
+
|
99
|
+
Available subcommands:
|
100
|
+
bolt command run <command> Run a command remotely
|
101
|
+
bolt file upload <src> <dest> Upload a local file or directory
|
102
|
+
bolt script run <script> Upload a local script and run it remotely
|
103
|
+
bolt task show Show list of available tasks
|
104
|
+
bolt task show <task> Show documentation for task
|
105
|
+
bolt task run <task> [params] Run a Puppet task
|
106
|
+
bolt plan convert <plan_path> Convert a YAML plan to a Puppet plan
|
107
|
+
bolt plan show Show list of available plans
|
108
|
+
bolt plan show <plan> Show details for plan
|
109
|
+
bolt plan run <plan> [params] Run a Puppet task plan
|
110
|
+
bolt apply <manifest> Apply Puppet manifest code
|
111
|
+
bolt puppetfile install Install modules from a Puppetfile into a Boltdir
|
112
|
+
bolt puppetfile show-modules List modules available to Bolt
|
113
|
+
bolt secret createkeys Create new encryption keys
|
114
|
+
bolt secret encrypt <plaintext> Encrypt a value
|
115
|
+
bolt secret decrypt <encrypted> Decrypt a value
|
116
|
+
bolt inventory show Show the list of targets an action would run on
|
117
|
+
|
118
|
+
Run `bolt <subcommand> --help` to view specific examples.
|
119
|
+
|
120
|
+
Available options are:
|
121
121
|
HELP
|
122
122
|
|
123
|
-
TASK_HELP =
|
124
|
-
Usage: bolt task <action> <task> [parameters]
|
123
|
+
TASK_HELP = <<~HELP
|
124
|
+
Usage: bolt task <action> <task> [parameters]
|
125
125
|
|
126
|
-
Available actions are:
|
127
|
-
|
128
|
-
|
129
|
-
|
126
|
+
Available actions are:
|
127
|
+
show Show list of available tasks
|
128
|
+
show <task> Show documentation for task
|
129
|
+
run <task> Run a Puppet task
|
130
130
|
|
131
|
-
Parameters are of the form <parameter>=<value>.
|
131
|
+
Parameters are of the form <parameter>=<value>.
|
132
132
|
|
133
|
-
#{examples('task run facts', 'run facter on')}
|
134
|
-
Available options are:
|
133
|
+
#{examples('task run facts', 'run facter on')}
|
134
|
+
Available options are:
|
135
135
|
HELP
|
136
136
|
|
137
|
-
TASK_SHOW_HELP =
|
138
|
-
Usage: bolt task show <task>
|
137
|
+
TASK_SHOW_HELP = <<~HELP
|
138
|
+
Usage: bolt task show <task>
|
139
139
|
|
140
|
-
Available actions are:
|
141
|
-
|
142
|
-
|
140
|
+
Available actions are:
|
141
|
+
show Show list of available tasks
|
142
|
+
show <task> Show documentation for task
|
143
143
|
|
144
|
-
Available options are:
|
144
|
+
Available options are:
|
145
145
|
HELP
|
146
146
|
|
147
|
-
TASK_RUN_HELP =
|
148
|
-
Usage: bolt task run <task> [parameters]
|
147
|
+
TASK_RUN_HELP = <<~HELP
|
148
|
+
Usage: bolt task run <task> [parameters]
|
149
149
|
|
150
|
-
Parameters are of the form <parameter>=<value>.
|
150
|
+
Parameters are of the form <parameter>=<value>.
|
151
151
|
|
152
|
-
#{examples('task run facts', 'run facter on')}
|
153
|
-
Available options are:
|
152
|
+
#{examples('task run facts', 'run facter on')}
|
153
|
+
Available options are:
|
154
154
|
HELP
|
155
155
|
|
156
|
-
COMMAND_HELP =
|
157
|
-
Usage: bolt command <action> <command>
|
156
|
+
COMMAND_HELP = <<~HELP
|
157
|
+
Usage: bolt command <action> <command>
|
158
158
|
|
159
|
-
Available actions are:
|
160
|
-
|
159
|
+
Available actions are:
|
160
|
+
run Run a command remotely
|
161
161
|
|
162
|
-
#{examples('command run hostname', 'run hostname on')}
|
163
|
-
Available options are:
|
162
|
+
#{examples('command run hostname', 'run hostname on')}
|
163
|
+
Available options are:
|
164
164
|
HELP
|
165
165
|
|
166
|
-
SCRIPT_HELP =
|
167
|
-
Usage: bolt script <action> <script> [[arg1] ... [argN]]
|
166
|
+
SCRIPT_HELP = <<~HELP
|
167
|
+
Usage: bolt script <action> <script> [[arg1] ... [argN]]
|
168
168
|
|
169
|
-
Available actions are:
|
170
|
-
|
169
|
+
Available actions are:
|
170
|
+
run Upload a local script and run it remotely
|
171
171
|
|
172
|
-
#{examples('script run my_script.ps1 some args', 'run a script on')}
|
173
|
-
Available options are:
|
172
|
+
#{examples('script run my_script.ps1 some args', 'run a script on')}
|
173
|
+
Available options are:
|
174
174
|
HELP
|
175
175
|
|
176
|
-
PLAN_HELP =
|
177
|
-
Usage: bolt plan <action> <plan> [parameters]
|
176
|
+
PLAN_HELP = <<~HELP
|
177
|
+
Usage: bolt plan <action> <plan> [parameters]
|
178
178
|
|
179
|
-
Available actions are:
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
179
|
+
Available actions are:
|
180
|
+
convert <plan_path> Convert a YAML plan to a Puppet plan
|
181
|
+
show Show list of available plans
|
182
|
+
show <plan> Show details for plan
|
183
|
+
run Run a Puppet task plan
|
184
184
|
|
185
|
-
Parameters are of the form <parameter>=<value>.
|
185
|
+
Parameters are of the form <parameter>=<value>.
|
186
186
|
|
187
|
-
#{examples('plan run canary command=hostname', 'run the canary plan on')}
|
188
|
-
Available options are:
|
187
|
+
#{examples('plan run canary command=hostname', 'run the canary plan on')}
|
188
|
+
Available options are:
|
189
189
|
HELP
|
190
190
|
|
191
|
-
PLAN_CONVERT_HELP =
|
192
|
-
Usage: bolt plan convert <plan_path>
|
191
|
+
PLAN_CONVERT_HELP = <<~HELP
|
192
|
+
Usage: bolt plan convert <plan_path>
|
193
193
|
|
194
|
-
Available options are:
|
194
|
+
Available options are:
|
195
195
|
HELP
|
196
196
|
|
197
|
-
PLAN_SHOW_HELP =
|
198
|
-
Usage: bolt plan show <plan>
|
197
|
+
PLAN_SHOW_HELP = <<~HELP
|
198
|
+
Usage: bolt plan show <plan>
|
199
199
|
|
200
|
-
Available actions are:
|
201
|
-
|
202
|
-
|
200
|
+
Available actions are:
|
201
|
+
show Show list of available plans
|
202
|
+
show <plan> Show details for plan
|
203
203
|
|
204
|
-
Available options are:
|
204
|
+
Available options are:
|
205
205
|
HELP
|
206
206
|
|
207
|
-
PLAN_RUN_HELP =
|
208
|
-
Usage: bolt plan run <plan> [parameters]
|
207
|
+
PLAN_RUN_HELP = <<~HELP
|
208
|
+
Usage: bolt plan run <plan> [parameters]
|
209
209
|
|
210
|
-
Parameters are of the form <parameter>=<value>.
|
210
|
+
Parameters are of the form <parameter>=<value>.
|
211
211
|
|
212
|
-
#{examples('plan run canary command=hostname', 'run the canary plan on')}
|
213
|
-
Available options are:
|
212
|
+
#{examples('plan run canary command=hostname', 'run the canary plan on')}
|
213
|
+
Available options are:
|
214
214
|
HELP
|
215
215
|
|
216
|
-
FILE_HELP =
|
217
|
-
Usage: bolt file <action>
|
216
|
+
FILE_HELP = <<~HELP
|
217
|
+
Usage: bolt file <action>
|
218
218
|
|
219
|
-
Available actions are:
|
220
|
-
|
219
|
+
Available actions are:
|
220
|
+
upload <src> <dest> Upload local file or directory <src> to <dest> on each node
|
221
221
|
|
222
|
-
#{examples('file upload /tmp/source /etc/profile.d/login.sh', 'upload a file to')}
|
223
|
-
Available options are:
|
222
|
+
#{examples('file upload /tmp/source /etc/profile.d/login.sh', 'upload a file to')}
|
223
|
+
Available options are:
|
224
224
|
HELP
|
225
225
|
|
226
|
-
PUPPETFILE_HELP =
|
227
|
-
Usage: bolt puppetfile <action>
|
226
|
+
PUPPETFILE_HELP = <<~HELP
|
227
|
+
Usage: bolt puppetfile <action>
|
228
228
|
|
229
|
-
Available actions are:
|
230
|
-
|
231
|
-
|
229
|
+
Available actions are:
|
230
|
+
install Install modules from a Puppetfile into a Boltdir
|
231
|
+
show-modules List modules available to Bolt
|
232
232
|
|
233
|
-
Install modules into the local Boltdir
|
234
|
-
|
233
|
+
Install modules into the local Boltdir
|
234
|
+
bolt puppetfile install
|
235
235
|
|
236
|
-
Available options are:
|
236
|
+
Available options are:
|
237
237
|
HELP
|
238
238
|
|
239
|
-
PUPPETFILE_INSTALL_HELP =
|
240
|
-
Usage: bolt puppetfile install
|
239
|
+
PUPPETFILE_INSTALL_HELP = <<~HELP
|
240
|
+
Usage: bolt puppetfile install
|
241
241
|
|
242
|
-
Install modules into the local Boltdir
|
243
|
-
|
242
|
+
Install modules into the local Boltdir
|
243
|
+
bolt puppetfile install
|
244
244
|
|
245
|
-
Available options are:
|
245
|
+
Available options are:
|
246
246
|
HELP
|
247
247
|
|
248
|
-
PUPPETFILE_SHOWMODULES_HELP =
|
249
|
-
Usage: bolt puppetfile show-modules
|
248
|
+
PUPPETFILE_SHOWMODULES_HELP = <<~HELP
|
249
|
+
Usage: bolt puppetfile show-modules
|
250
250
|
|
251
|
-
Available options are:
|
251
|
+
Available options are:
|
252
252
|
HELP
|
253
253
|
|
254
|
-
APPLY_HELP =
|
255
|
-
Usage: bolt apply <manifest.pp>
|
254
|
+
APPLY_HELP = <<~HELP
|
255
|
+
Usage: bolt apply <manifest.pp>
|
256
256
|
|
257
|
-
#{examples('apply site.pp', 'apply a manifest on')}
|
258
|
-
|
257
|
+
#{examples('apply site.pp', 'apply a manifest on')}
|
258
|
+
bolt apply site.pp --nodes foo.example.com,bar.example.com
|
259
259
|
|
260
|
-
Available options are:
|
260
|
+
Available options are:
|
261
261
|
HELP
|
262
262
|
|
263
263
|
SECRET_HELP = <<~SECRET_HELP
|
data/lib/bolt/config.rb
CHANGED
@@ -31,13 +31,13 @@ module Bolt
|
|
31
31
|
end
|
32
32
|
|
33
33
|
class Config
|
34
|
-
attr_accessor :
|
34
|
+
attr_accessor :concurrency, :format, :trace, :log, :puppetdb, :color, :save_rerun,
|
35
35
|
:transport, :transports, :inventoryfile, :compile_concurrency, :boltdir,
|
36
36
|
:puppetfile_config, :plugins
|
37
37
|
attr_writer :modulepath
|
38
38
|
|
39
39
|
TRANSPORT_OPTIONS = %i[password run-as sudo-password extensions
|
40
|
-
private-key tty tmpdir user connect-timeout
|
40
|
+
private-key tty tmpdir user connect-timeout disconnect-timeout
|
41
41
|
cacert token-file service-url interpreters file-protocol smb-port realm].freeze
|
42
42
|
|
43
43
|
PUPPETFILE_OPTIONS = %w[proxy forge].freeze
|
@@ -162,7 +162,7 @@ module Bolt
|
|
162
162
|
# Plugins are only settable from config not inventory so we can overwrite
|
163
163
|
@plugins = data['plugins'] if data.key?('plugins')
|
164
164
|
|
165
|
-
%w[
|
165
|
+
%w[concurrency format puppetdb color transport].each do |key|
|
166
166
|
send("#{key}=", data[key]) if data.key?(key)
|
167
167
|
end
|
168
168
|
|
data/lib/bolt/plugin.rb
CHANGED
@@ -6,6 +6,7 @@ require 'bolt/plugin/pkcs7'
|
|
6
6
|
require 'bolt/plugin/prompt'
|
7
7
|
require 'bolt/plugin/task'
|
8
8
|
require 'bolt/plugin/aws'
|
9
|
+
require 'bolt/plugin/vault'
|
9
10
|
|
10
11
|
module Bolt
|
11
12
|
class Plugin
|
@@ -37,7 +38,8 @@ module Bolt
|
|
37
38
|
plugins.add_plugin(Bolt::Plugin::Prompt.new)
|
38
39
|
plugins.add_plugin(Bolt::Plugin::Pkcs7.new(config.boltdir.path, config.plugins['pkcs7'] || {}))
|
39
40
|
plugins.add_plugin(Bolt::Plugin::Task.new(config))
|
40
|
-
plugins.add_plugin(Bolt::Plugin::Aws::EC2.new(config))
|
41
|
+
plugins.add_plugin(Bolt::Plugin::Aws::EC2.new(config.plugins['aws'] || {}))
|
42
|
+
plugins.add_plugin(Bolt::Plugin::Vault.new(config.plugins['vault'] || {}))
|
41
43
|
plugins
|
42
44
|
end
|
43
45
|
|
data/lib/bolt/plugin/aws.rb
CHANGED
@@ -34,12 +34,12 @@ module Bolt
|
|
34
34
|
if opts.key?('profile')
|
35
35
|
options[:profile] = opts['profile']
|
36
36
|
end
|
37
|
-
if config
|
38
|
-
creds = File.expand_path(config
|
37
|
+
if config['credentials']
|
38
|
+
creds = File.expand_path(config['credentials'])
|
39
39
|
if File.exist?(creds)
|
40
40
|
options[:credentials] = ::Aws::SharedCredentials.new(path: creds)
|
41
41
|
else
|
42
|
-
raise Bolt::ValidationError, "Cannot load credentials file #{config
|
42
|
+
raise Bolt::ValidationError, "Cannot load credentials file #{config['credentials']}"
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
@@ -0,0 +1,206 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bolt
|
4
|
+
class Plugin
|
5
|
+
class Vault
|
6
|
+
class VaultHTTPError < Bolt::Error
|
7
|
+
def initialize(response)
|
8
|
+
err = JSON.parse(response.body)['errors']
|
9
|
+
m = String.new("#{response.code} \"#{response.msg}\"")
|
10
|
+
m << ": #{err.join(';')}" unless err.nil?
|
11
|
+
super(m, 'bolt.plugin/vault-http-error')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_reader :config
|
16
|
+
|
17
|
+
# All requests for secrets must have a token in the request header
|
18
|
+
TOKEN_HEADER = "X-Vault-Token"
|
19
|
+
|
20
|
+
# Default header for all requests, including auth methods
|
21
|
+
DEFAULT_HEADER = {
|
22
|
+
"Content-Type" => "application/json",
|
23
|
+
"Accept" => "application/json"
|
24
|
+
}.freeze
|
25
|
+
|
26
|
+
# Make sure no unexpected keys are in the config
|
27
|
+
def validate_config(config)
|
28
|
+
known_keys = %w[server_url auth cacert]
|
29
|
+
|
30
|
+
config.each do |key, _v|
|
31
|
+
next if known_keys.include?(key)
|
32
|
+
raise Bolt::ValidationError, "Unexpected key in Vault plugin config: #{key}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Make sure no unexpected keys are in the inventory config and
|
37
|
+
# that required keys are present
|
38
|
+
def validate_options(opts)
|
39
|
+
known_keys = %w[_plugin server_url auth path field version cacert]
|
40
|
+
required_keys = %w[path]
|
41
|
+
|
42
|
+
opts.each do |key, _v|
|
43
|
+
next if known_keys.include?(key)
|
44
|
+
raise Bolt::ValidationError, "Unexpected key in inventory config: #{key}"
|
45
|
+
end
|
46
|
+
|
47
|
+
required_keys.each do |key|
|
48
|
+
next if opts[key]
|
49
|
+
raise Bolt::ValidationError, "Expected key in inventory config: #{key}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def name
|
54
|
+
'vault'
|
55
|
+
end
|
56
|
+
|
57
|
+
def hooks
|
58
|
+
['inventory_config']
|
59
|
+
end
|
60
|
+
|
61
|
+
def initialize(config)
|
62
|
+
validate_config(config)
|
63
|
+
@config = config
|
64
|
+
@logger = Logging.logger[self]
|
65
|
+
end
|
66
|
+
|
67
|
+
def inventory_config(opts)
|
68
|
+
validate_options(opts)
|
69
|
+
|
70
|
+
header = {
|
71
|
+
TOKEN_HEADER => token(opts)
|
72
|
+
}
|
73
|
+
|
74
|
+
response = request(:Get, uri(opts), opts, nil, header)
|
75
|
+
|
76
|
+
parse_response(response, opts)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Request uri - built up from Vault server url and secrets path
|
80
|
+
def uri(opts, path = nil)
|
81
|
+
url = opts['server_url'] || config['server_url'] || ENV['VAULT_ADDR']
|
82
|
+
|
83
|
+
# Handle the different versions of the API
|
84
|
+
if opts['version'] == 2
|
85
|
+
mount, store = opts['path'].split('/', 2)
|
86
|
+
opts['path'] = [mount, 'data', store].join('/')
|
87
|
+
end
|
88
|
+
|
89
|
+
path ||= opts['path']
|
90
|
+
|
91
|
+
URI.parse(File.join(url, "v1", path))
|
92
|
+
end
|
93
|
+
|
94
|
+
# Configure the http/s client
|
95
|
+
def client(uri, opts)
|
96
|
+
client = Net::HTTP.new(uri.host, uri.port)
|
97
|
+
|
98
|
+
if uri.scheme == 'https'
|
99
|
+
cacert = opts['cacert'] || config['cacert'] || ENV['VAULT_CACERT']
|
100
|
+
|
101
|
+
unless cacert
|
102
|
+
raise Bolt::ValidationError, "Expected cacert to be set when using https"
|
103
|
+
end
|
104
|
+
|
105
|
+
client.use_ssl = true
|
106
|
+
client.ssl_version = :TLSv1_2
|
107
|
+
client.ca_file = cacert
|
108
|
+
client.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
109
|
+
end
|
110
|
+
|
111
|
+
client
|
112
|
+
end
|
113
|
+
|
114
|
+
# Auth token to vault server
|
115
|
+
def token(opts)
|
116
|
+
if (auth = opts['auth'] || config['auth'])
|
117
|
+
request_token(auth, opts)
|
118
|
+
else
|
119
|
+
ENV['VAULT_TOKEN']
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def request(verb, uri, opts, data, header = {})
|
124
|
+
# Add on any header options
|
125
|
+
header = DEFAULT_HEADER.merge(header)
|
126
|
+
|
127
|
+
# Create the HTTP request
|
128
|
+
client = client(uri, opts)
|
129
|
+
request = Net::HTTP.const_get(verb).new(uri.request_uri, header)
|
130
|
+
|
131
|
+
# Attach any data
|
132
|
+
request.body = data if data
|
133
|
+
|
134
|
+
# Send the request
|
135
|
+
begin
|
136
|
+
response = client.request(request)
|
137
|
+
rescue StandardError => e
|
138
|
+
raise Bolt::Error.new(
|
139
|
+
"Failed to connect to #{uri}: #{e.message}",
|
140
|
+
'CONNECT_ERROR'
|
141
|
+
)
|
142
|
+
end
|
143
|
+
|
144
|
+
case response
|
145
|
+
when Net::HTTPOK
|
146
|
+
JSON.parse(response.body)
|
147
|
+
else
|
148
|
+
raise VaultHTTPError, response
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def parse_response(response, opts)
|
153
|
+
data = case opts['version']
|
154
|
+
when 2
|
155
|
+
response['data']['data']
|
156
|
+
else
|
157
|
+
response['data']
|
158
|
+
end
|
159
|
+
|
160
|
+
if opts['field']
|
161
|
+
unless data[opts['field']]
|
162
|
+
raise Bolt::ValidationError, "Unknown secrets field: #{opts['field']}"
|
163
|
+
end
|
164
|
+
data[opts['field']]
|
165
|
+
else
|
166
|
+
data
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
# Request a token from Vault using one of the auth methods
|
171
|
+
def request_token(auth, opts)
|
172
|
+
case auth['method']
|
173
|
+
when 'token'
|
174
|
+
auth_token(auth)
|
175
|
+
when 'userpass'
|
176
|
+
auth_userpass(auth, opts)
|
177
|
+
else
|
178
|
+
raise Bolt::ValidationError, "Unknown auth method: #{auth['method']}"
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def validate_auth(auth, required_keys)
|
183
|
+
required_keys.each do |key|
|
184
|
+
next if auth[key]
|
185
|
+
raise Bolt::ValidationError, "Expected key in #{auth['method']} auth method: #{key}"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
# Authenticate with Vault using the 'Token' auth method
|
190
|
+
def auth_token(auth)
|
191
|
+
validate_auth(auth, %w[token])
|
192
|
+
auth['token']
|
193
|
+
end
|
194
|
+
|
195
|
+
# Authenticate with Vault using the 'Userpass' auth method
|
196
|
+
def auth_userpass(auth, opts)
|
197
|
+
validate_auth(auth, %w[user pass])
|
198
|
+
path = "auth/userpass/login/#{auth['user']}"
|
199
|
+
uri = uri(opts, path)
|
200
|
+
data = { "password" => auth['pass'] }.to_json
|
201
|
+
|
202
|
+
request(:Post, uri, opts, data)['auth']['client_token']
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
data/lib/bolt/transport/ssh.rb
CHANGED
@@ -10,7 +10,7 @@ module Bolt
|
|
10
10
|
class SSH < Sudoable
|
11
11
|
def self.options
|
12
12
|
%w[host port user password sudo-password private-key host-key-check
|
13
|
-
connect-timeout tmpdir run-as tty run-as-command proxyjump interpreters]
|
13
|
+
connect-timeout disconnect-timeout tmpdir run-as tty run-as-command proxyjump interpreters]
|
14
14
|
end
|
15
15
|
|
16
16
|
def self.default_options
|
@@ -18,7 +18,8 @@ module Bolt
|
|
18
18
|
'connect-timeout' => 10,
|
19
19
|
'host-key-check' => true,
|
20
20
|
'tty' => false,
|
21
|
-
'load-config' => true
|
21
|
+
'load-config' => true,
|
22
|
+
'disconnect-timeout' => 5
|
22
23
|
}
|
23
24
|
end
|
24
25
|
|
@@ -42,10 +43,12 @@ module Bolt
|
|
42
43
|
end
|
43
44
|
end
|
44
45
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
%w[connect-timeout disconnect-timeout].each do |timeout|
|
47
|
+
timeout_value = options[timeout]
|
48
|
+
unless timeout_value.is_a?(Integer) || timeout_value.nil?
|
49
|
+
error_msg = "#{timeout} value must be an Integer, received #{timeout_value}:#{timeout_value.class}"
|
50
|
+
raise Bolt::ValidationError, error_msg
|
51
|
+
end
|
49
52
|
end
|
50
53
|
end
|
51
54
|
|
@@ -130,7 +130,11 @@ module Bolt
|
|
130
130
|
|
131
131
|
def disconnect
|
132
132
|
if @session && !@session.closed?
|
133
|
-
|
133
|
+
begin
|
134
|
+
Timeout.timeout(@target.options['disconnect-timeout']) { @session.close }
|
135
|
+
rescue Timeout::Error
|
136
|
+
@session.shutdown!
|
137
|
+
end
|
134
138
|
@logger.debug { "Closed session" }
|
135
139
|
end
|
136
140
|
end
|
data/lib/bolt/version.rb
CHANGED
@@ -28,6 +28,10 @@
|
|
28
28
|
"type": "integer",
|
29
29
|
"description": "How long Bolt should wait when establishing connections"
|
30
30
|
},
|
31
|
+
"disconnect-timeout": {
|
32
|
+
"type": "integer",
|
33
|
+
"description": "How long Bolt should wait before forcing a disconnect"
|
34
|
+
},
|
31
35
|
"run-as-command": {
|
32
36
|
"type": "array",
|
33
37
|
"description": "Command elevate permissions",
|
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: 1.
|
4
|
+
version: 1.28.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Puppet
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-08-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -416,6 +416,7 @@ files:
|
|
416
416
|
- lib/bolt/plugin/puppetdb.rb
|
417
417
|
- lib/bolt/plugin/task.rb
|
418
418
|
- lib/bolt/plugin/terraform.rb
|
419
|
+
- lib/bolt/plugin/vault.rb
|
419
420
|
- lib/bolt/puppetdb.rb
|
420
421
|
- lib/bolt/puppetdb/client.rb
|
421
422
|
- lib/bolt/puppetdb/config.rb
|