bolt 2.7.0 → 2.11.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 +4 -4
- data/Puppetfile +4 -3
- data/bolt-modules/boltlib/lib/puppet/datatypes/applyresult.rb +2 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/resourceinstance.rb +27 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/result.rb +2 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/resultset.rb +2 -0
- data/bolt-modules/boltlib/lib/puppet/datatypes/target.rb +4 -3
- data/bolt-modules/boltlib/lib/puppet/functions/run_task_with.rb +192 -0
- data/bolt-modules/boltlib/lib/puppet/functions/set_resources.rb +122 -0
- data/bolt-modules/boltlib/types/planresult.pp +12 -1
- data/bolt-modules/file/lib/puppet/functions/file/exists.rb +3 -1
- data/bolt-modules/file/lib/puppet/functions/file/join.rb +1 -1
- data/bolt-modules/file/lib/puppet/functions/file/read.rb +2 -1
- data/bolt-modules/file/lib/puppet/functions/file/readable.rb +3 -1
- data/bolt-modules/file/lib/puppet/functions/file/write.rb +3 -1
- data/lib/bolt/applicator.rb +3 -2
- data/lib/bolt/apply_inventory.rb +1 -1
- data/lib/bolt/apply_result.rb +1 -1
- data/lib/bolt/apply_target.rb +11 -2
- data/lib/bolt/bolt_option_parser.rb +22 -6
- data/lib/bolt/cli.rb +52 -22
- data/lib/bolt/config.rb +57 -27
- data/lib/bolt/config/transport/base.rb +3 -3
- data/lib/bolt/config/transport/docker.rb +2 -0
- data/lib/bolt/config/transport/local.rb +2 -0
- data/lib/bolt/config/transport/orch.rb +4 -2
- data/lib/bolt/config/transport/remote.rb +2 -0
- data/lib/bolt/config/transport/ssh.rb +51 -2
- data/lib/bolt/config/transport/winrm.rb +3 -1
- data/lib/bolt/executor.rb +16 -0
- data/lib/bolt/inventory.rb +2 -1
- data/lib/bolt/inventory/group.rb +1 -0
- data/lib/bolt/inventory/inventory.rb +5 -0
- data/lib/bolt/inventory/target.rb +17 -1
- data/lib/bolt/node/output.rb +1 -1
- data/lib/bolt/outputter/human.rb +5 -4
- data/lib/bolt/outputter/json.rb +1 -1
- data/lib/bolt/pal.rb +32 -14
- data/lib/bolt/pal/yaml_plan.rb +1 -0
- data/lib/bolt/plugin.rb +14 -8
- data/lib/bolt/plugin/module.rb +40 -7
- data/lib/bolt/plugin/puppetdb.rb +5 -2
- data/lib/bolt/project.rb +135 -0
- data/lib/bolt/puppetdb/config.rb +16 -28
- data/lib/bolt/rerun.rb +1 -1
- data/lib/bolt/resource_instance.rb +126 -0
- data/lib/bolt/result.rb +46 -23
- data/lib/bolt/result_set.rb +2 -5
- data/lib/bolt/secret.rb +20 -4
- data/lib/bolt/shell/bash.rb +12 -5
- data/lib/bolt/shell/powershell.rb +12 -4
- data/lib/bolt/target.rb +16 -1
- data/lib/bolt/transport/base.rb +24 -8
- data/lib/bolt/transport/orch.rb +4 -0
- data/lib/bolt/transport/ssh.rb +6 -2
- data/lib/bolt/transport/ssh/connection.rb +4 -0
- data/lib/bolt/transport/ssh/exec_connection.rb +110 -0
- data/lib/bolt/transport/winrm/connection.rb +6 -2
- data/lib/bolt/version.rb +1 -1
- data/lib/bolt_server/pe/pal.rb +1 -38
- data/lib/bolt_server/transport_app.rb +7 -7
- data/lib/bolt_spec/bolt_context.rb +3 -6
- data/lib/bolt_spec/plans.rb +1 -1
- data/lib/bolt_spec/plans/mock_executor.rb +1 -0
- data/lib/bolt_spec/run.rb +10 -13
- metadata +10 -7
- data/lib/bolt/boltdir.rb +0 -54
- data/lib/bolt/plugin/pkcs7.rb +0 -104
- data/lib/bolt/secret/base.rb +0 -41
@@ -108,8 +108,8 @@ module Bolt
|
|
108
108
|
# it will fail if the shell attempts to provide stdin
|
109
109
|
inp.close
|
110
110
|
|
111
|
-
out_rd, out_wr = IO.pipe
|
112
|
-
err_rd, err_wr = IO.pipe
|
111
|
+
out_rd, out_wr = IO.pipe('UTF-8')
|
112
|
+
err_rd, err_wr = IO.pipe('UTF-8')
|
113
113
|
th = Thread.new do
|
114
114
|
result = @session.run(command)
|
115
115
|
out_wr << result.stdout
|
@@ -120,6 +120,10 @@ module Bolt
|
|
120
120
|
end
|
121
121
|
|
122
122
|
[inp, out_rd, err_rd, th]
|
123
|
+
rescue Errno::EMFILE => e
|
124
|
+
msg = "#{e.message}. This may be resolved by increasing your user limit "\
|
125
|
+
"with 'ulimit -n 1024'. See https://puppet.com/docs/bolt/latest/bolt_known_issues.html for details."
|
126
|
+
raise Bolt::Error.new(msg, 'bolt/too-many-files')
|
123
127
|
rescue StandardError
|
124
128
|
@logger.debug { "Command aborted" }
|
125
129
|
raise
|
data/lib/bolt/version.rb
CHANGED
data/lib/bolt_server/pe/pal.rb
CHANGED
@@ -51,50 +51,13 @@ module BoltServer
|
|
51
51
|
basemodulepath = plan_executor_config['basemodulepath'] || "#{codedir}/modules:/opt/puppetlabs/puppet/modules"
|
52
52
|
|
53
53
|
with_pe_pal_init_settings(codedir, environmentpath, basemodulepath) do
|
54
|
-
modulepath_dirs = []
|
55
|
-
modulepath_setting_from_bolt = nil
|
56
54
|
environment = Puppet.lookup(:environments).get!(environment_name)
|
57
|
-
path_to_env = environment.configuration.path_to_env
|
58
|
-
|
59
|
-
# In the instance where the environment is "production" but no production dir
|
60
|
-
# exists, the lookup will succeed, but the configuration will be mostly empty.
|
61
|
-
# For other environments the lookup will fail, but for production we don't
|
62
|
-
# want cryptic messages sent to the user about combining `nil` with a string.
|
63
|
-
# Thus if we do get here and `path_to_env` is empty, just assume it's the
|
64
|
-
# default production environment and continue.
|
65
|
-
#
|
66
|
-
# This should hopefully match puppet's behavior for the default 'production'
|
67
|
-
# environment: _technically_ that environment always exists, but if the dir
|
68
|
-
# isn't there it won't find the module and fail with "plan not found" rather
|
69
|
-
# than "environment doesn't exist"
|
70
|
-
if path_to_env
|
71
|
-
bolt_yaml = File.join(environment.configuration.path_to_env, 'bolt.yaml')
|
72
|
-
modulepath_setting_from_bolt = Bolt::Util.read_optional_yaml_hash(bolt_yaml, 'config')['modulepath']
|
73
|
-
end
|
74
|
-
|
75
|
-
# If we loaded a bolt.yaml in the environment root and it contained a modulepath setting:
|
76
|
-
# we will use that modulepath rather than the one loaded through puppet. modulepath will
|
77
|
-
# be the _only_ setting that will work from bolt.yaml in plans in PE.
|
78
|
-
if modulepath_setting_from_bolt
|
79
|
-
modulepath_setting_from_bolt.split(File::PATH_SEPARATOR).each do |path|
|
80
|
-
if Pathname.new(path).absolute? && File.exist?(path)
|
81
|
-
modulepath_dirs << path
|
82
|
-
elsif File.exist?(File.join(path_to_env, path))
|
83
|
-
modulepath_dirs << File.join(path_to_env, path)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
# Append the basemodulepath to include "built-in" modules.
|
88
|
-
modulepath_dirs.concat(basemodulepath.split(File::PATH_SEPARATOR))
|
89
|
-
else
|
90
|
-
modulepath_dirs = environment.modulepath
|
91
|
-
end
|
92
|
-
|
93
55
|
# A new modulepath is created from scratch (rather than using super's @modulepath)
|
94
56
|
# so that we can have full control over all the entries in modulepath. In the future
|
95
57
|
# it's likely we will need to preceed _both_ Bolt::PAL::BOLTLIB_PATH _and_
|
96
58
|
# Bolt::PAL::MODULES_PATH which would be more complex if we tried to use @modulepath since
|
97
59
|
# we need to append our modulepaths and exclude modules shiped in bolt gem code
|
60
|
+
modulepath_dirs = environment.modulepath
|
98
61
|
@original_modulepath = modulepath_dirs
|
99
62
|
@modulepath = [PE_BOLTLIB_PATH, Bolt::PAL::BOLTLIB_PATH, *modulepath_dirs]
|
100
63
|
end
|
@@ -57,8 +57,8 @@ module BoltServer
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def scrub_stack_trace(result)
|
60
|
-
if result.dig(
|
61
|
-
result[
|
60
|
+
if result.dig('value', '_error', 'details', 'stack_trace')
|
61
|
+
result['value']['_error']['details'].reject! { |k| k == 'stack_trace' }
|
62
62
|
end
|
63
63
|
result
|
64
64
|
end
|
@@ -87,14 +87,14 @@ module BoltServer
|
|
87
87
|
# If the `result_set` contains only one item, it will be returned
|
88
88
|
# as a single result object. Set `aggregate` to treat it as a set
|
89
89
|
# of results with length 1 instead.
|
90
|
-
def
|
90
|
+
def result_set_to_data(result_set, aggregate: false)
|
91
91
|
scrubbed_results = result_set.map do |result|
|
92
|
-
scrub_stack_trace(result.
|
92
|
+
scrub_stack_trace(result.to_data)
|
93
93
|
end
|
94
94
|
|
95
95
|
if aggregate || scrubbed_results.length > 1
|
96
96
|
# For actions that act on multiple targets, construct a status hash for the aggregate result
|
97
|
-
all_succeeded = scrubbed_results.all? { |r| r[
|
97
|
+
all_succeeded = scrubbed_results.all? { |r| r['status'] == 'success' }
|
98
98
|
{
|
99
99
|
status: all_succeeded ? 'success' : 'failure',
|
100
100
|
result: scrubbed_results
|
@@ -297,7 +297,7 @@ module BoltServer
|
|
297
297
|
return [400, error.to_json] unless error.nil?
|
298
298
|
|
299
299
|
aggregate = body['target'].nil?
|
300
|
-
[200,
|
300
|
+
[200, result_set_to_data(result_set, aggregate: aggregate).to_json]
|
301
301
|
end
|
302
302
|
|
303
303
|
def make_winrm_target(target_hash)
|
@@ -337,7 +337,7 @@ module BoltServer
|
|
337
337
|
return [400, error.to_json] if error
|
338
338
|
|
339
339
|
aggregate = body['target'].nil?
|
340
|
-
[200,
|
340
|
+
[200, result_set_to_data(result_set, aggregate: aggregate).to_json]
|
341
341
|
end
|
342
342
|
|
343
343
|
# Fetches the metadata for a single plan
|
@@ -138,21 +138,18 @@ module BoltSpec
|
|
138
138
|
# Override in your tests
|
139
139
|
def config
|
140
140
|
@config ||= begin
|
141
|
-
conf = Bolt::Config.new(Bolt::
|
141
|
+
conf = Bolt::Config.new(Bolt::Project.new('.'), {})
|
142
142
|
conf.modulepath = [modulepath].flatten
|
143
143
|
conf
|
144
144
|
end
|
145
145
|
end
|
146
146
|
|
147
147
|
def plugins
|
148
|
-
@plugins ||= Bolt::Plugin.setup(config,
|
149
|
-
pal,
|
150
|
-
nil,
|
151
|
-
Bolt::Analytics::NoopClient.new)
|
148
|
+
@plugins ||= Bolt::Plugin.setup(config, pal)
|
152
149
|
end
|
153
150
|
|
154
151
|
def pal
|
155
|
-
@pal ||= Bolt::PAL.new(config.modulepath, config.hiera_config, config.
|
152
|
+
@pal ||= Bolt::PAL.new(config.modulepath, config.hiera_config, config.project.resource_types)
|
156
153
|
end
|
157
154
|
|
158
155
|
BoltSpec::Plans::MOCKED_ACTIONS.each do |action|
|
data/lib/bolt_spec/plans.rb
CHANGED
@@ -219,7 +219,7 @@ module BoltSpec
|
|
219
219
|
end
|
220
220
|
|
221
221
|
def run_plan(name, params)
|
222
|
-
pal = Bolt::PAL.new(config.modulepath, config.hiera_config, config.
|
222
|
+
pal = Bolt::PAL.new(config.modulepath, config.hiera_config, config.project.resource_types)
|
223
223
|
result = executor.with_plan_allowed_exec(name, params) do
|
224
224
|
pal.run_plan(name, params, executor, inventory, puppetdb_client)
|
225
225
|
end
|
data/lib/bolt_spec/run.rb
CHANGED
@@ -126,25 +126,25 @@ module BoltSpec
|
|
126
126
|
end
|
127
127
|
|
128
128
|
class BoltRunner
|
129
|
-
# Creates a temporary
|
130
|
-
# WARNING: puppetdb config and orch config which do not use the
|
129
|
+
# Creates a temporary project so no settings are picked up
|
130
|
+
# WARNING: puppetdb config and orch config which do not use the project may
|
131
131
|
# still be loaded
|
132
132
|
def self.with_runner(config_data, inventory_data)
|
133
|
-
Dir.mktmpdir do |
|
134
|
-
runner = new(Bolt::Util.deep_clone(config_data), Bolt::Util.deep_clone(inventory_data),
|
133
|
+
Dir.mktmpdir do |project_path|
|
134
|
+
runner = new(Bolt::Util.deep_clone(config_data), Bolt::Util.deep_clone(inventory_data), project_path)
|
135
135
|
yield runner
|
136
136
|
end
|
137
137
|
end
|
138
138
|
|
139
|
-
def initialize(config_data, inventory_data,
|
139
|
+
def initialize(config_data, inventory_data, project_path)
|
140
140
|
@config_data = config_data || {}
|
141
141
|
@inventory_data = inventory_data || {}
|
142
|
-
@
|
142
|
+
@project_path = project_path
|
143
143
|
@analytics = Bolt::Analytics::NoopClient.new
|
144
144
|
end
|
145
145
|
|
146
146
|
def config
|
147
|
-
@config ||= Bolt::Config.new(Bolt::
|
147
|
+
@config ||= Bolt::Config.new(Bolt::Project.new(@project_path), @config_data)
|
148
148
|
end
|
149
149
|
|
150
150
|
def inventory
|
@@ -152,20 +152,17 @@ module BoltSpec
|
|
152
152
|
end
|
153
153
|
|
154
154
|
def plugins
|
155
|
-
@plugins ||= Bolt::Plugin.setup(config, pal
|
155
|
+
@plugins ||= Bolt::Plugin.setup(config, pal)
|
156
156
|
end
|
157
157
|
|
158
158
|
def puppetdb_client
|
159
|
-
|
160
|
-
puppetdb_config = Bolt::PuppetDB::Config.load_config(nil, config.puppetdb)
|
161
|
-
Bolt::PuppetDB::Client.new(puppetdb_config)
|
162
|
-
end
|
159
|
+
plugins.puppetdb_client
|
163
160
|
end
|
164
161
|
|
165
162
|
def pal
|
166
163
|
@pal ||= Bolt::PAL.new(config.modulepath,
|
167
164
|
config.hiera_config,
|
168
|
-
config.
|
165
|
+
config.project.resource_types,
|
169
166
|
config.compile_concurrency)
|
170
167
|
end
|
171
168
|
|
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: 2.
|
4
|
+
version: 2.11.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Puppet
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-05-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -184,7 +184,7 @@ dependencies:
|
|
184
184
|
requirements:
|
185
185
|
- - ">="
|
186
186
|
- !ruby/object:Gem::Version
|
187
|
-
version: 6.
|
187
|
+
version: 6.15.0
|
188
188
|
- - "<"
|
189
189
|
- !ruby/object:Gem::Version
|
190
190
|
version: '7'
|
@@ -194,7 +194,7 @@ dependencies:
|
|
194
194
|
requirements:
|
195
195
|
- - ">="
|
196
196
|
- !ruby/object:Gem::Version
|
197
|
-
version: 6.
|
197
|
+
version: 6.15.0
|
198
198
|
- - "<"
|
199
199
|
- !ruby/object:Gem::Version
|
200
200
|
version: '7'
|
@@ -390,6 +390,7 @@ extra_rdoc_files: []
|
|
390
390
|
files:
|
391
391
|
- Puppetfile
|
392
392
|
- bolt-modules/boltlib/lib/puppet/datatypes/applyresult.rb
|
393
|
+
- bolt-modules/boltlib/lib/puppet/datatypes/resourceinstance.rb
|
393
394
|
- bolt-modules/boltlib/lib/puppet/datatypes/result.rb
|
394
395
|
- bolt-modules/boltlib/lib/puppet/datatypes/resultset.rb
|
395
396
|
- bolt-modules/boltlib/lib/puppet/datatypes/target.rb
|
@@ -410,8 +411,10 @@ files:
|
|
410
411
|
- bolt-modules/boltlib/lib/puppet/functions/run_plan.rb
|
411
412
|
- bolt-modules/boltlib/lib/puppet/functions/run_script.rb
|
412
413
|
- bolt-modules/boltlib/lib/puppet/functions/run_task.rb
|
414
|
+
- bolt-modules/boltlib/lib/puppet/functions/run_task_with.rb
|
413
415
|
- bolt-modules/boltlib/lib/puppet/functions/set_config.rb
|
414
416
|
- bolt-modules/boltlib/lib/puppet/functions/set_feature.rb
|
417
|
+
- bolt-modules/boltlib/lib/puppet/functions/set_resources.rb
|
415
418
|
- bolt-modules/boltlib/lib/puppet/functions/set_var.rb
|
416
419
|
- bolt-modules/boltlib/lib/puppet/functions/upload_file.rb
|
417
420
|
- bolt-modules/boltlib/lib/puppet/functions/vars.rb
|
@@ -438,7 +441,6 @@ files:
|
|
438
441
|
- lib/bolt/apply_result.rb
|
439
442
|
- lib/bolt/apply_target.rb
|
440
443
|
- lib/bolt/bolt_option_parser.rb
|
441
|
-
- lib/bolt/boltdir.rb
|
442
444
|
- lib/bolt/catalog.rb
|
443
445
|
- lib/bolt/catalog/logging.rb
|
444
446
|
- lib/bolt/cli.rb
|
@@ -484,19 +486,19 @@ files:
|
|
484
486
|
- lib/bolt/plugin.rb
|
485
487
|
- lib/bolt/plugin/env_var.rb
|
486
488
|
- lib/bolt/plugin/module.rb
|
487
|
-
- lib/bolt/plugin/pkcs7.rb
|
488
489
|
- lib/bolt/plugin/prompt.rb
|
489
490
|
- lib/bolt/plugin/puppetdb.rb
|
490
491
|
- lib/bolt/plugin/task.rb
|
492
|
+
- lib/bolt/project.rb
|
491
493
|
- lib/bolt/puppetdb.rb
|
492
494
|
- lib/bolt/puppetdb/client.rb
|
493
495
|
- lib/bolt/puppetdb/config.rb
|
494
496
|
- lib/bolt/r10k_log_proxy.rb
|
495
497
|
- lib/bolt/rerun.rb
|
498
|
+
- lib/bolt/resource_instance.rb
|
496
499
|
- lib/bolt/result.rb
|
497
500
|
- lib/bolt/result_set.rb
|
498
501
|
- lib/bolt/secret.rb
|
499
|
-
- lib/bolt/secret/base.rb
|
500
502
|
- lib/bolt/shell.rb
|
501
503
|
- lib/bolt/shell/bash.rb
|
502
504
|
- lib/bolt/shell/bash/tmpdir.rb
|
@@ -517,6 +519,7 @@ files:
|
|
517
519
|
- lib/bolt/transport/simple.rb
|
518
520
|
- lib/bolt/transport/ssh.rb
|
519
521
|
- lib/bolt/transport/ssh/connection.rb
|
522
|
+
- lib/bolt/transport/ssh/exec_connection.rb
|
520
523
|
- lib/bolt/transport/winrm.rb
|
521
524
|
- lib/bolt/transport/winrm/connection.rb
|
522
525
|
- lib/bolt/util.rb
|
data/lib/bolt/boltdir.rb
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'pathname'
|
4
|
-
|
5
|
-
module Bolt
|
6
|
-
class Boltdir
|
7
|
-
BOLTDIR_NAME = 'Boltdir'
|
8
|
-
|
9
|
-
attr_reader :path, :config_file, :inventory_file, :modulepath, :hiera_config,
|
10
|
-
:puppetfile, :rerunfile, :type, :resource_types
|
11
|
-
|
12
|
-
def self.default_boltdir
|
13
|
-
Boltdir.new(File.join('~', '.puppetlabs', 'bolt'), 'user')
|
14
|
-
end
|
15
|
-
|
16
|
-
# Search recursively up the directory hierarchy for the Boltdir. Look for a
|
17
|
-
# directory called Boltdir or a file called bolt.yaml (for a control repo
|
18
|
-
# type Boltdir). Otherwise, repeat the check on each directory up the
|
19
|
-
# hierarchy, falling back to the default if we reach the root.
|
20
|
-
def self.find_boltdir(dir)
|
21
|
-
dir = Pathname.new(dir)
|
22
|
-
if (dir + BOLTDIR_NAME).directory?
|
23
|
-
new(dir + BOLTDIR_NAME, 'embedded')
|
24
|
-
elsif (dir + 'bolt.yaml').file?
|
25
|
-
new(dir, 'local')
|
26
|
-
elsif dir.root?
|
27
|
-
default_boltdir
|
28
|
-
else
|
29
|
-
find_boltdir(dir.parent)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def initialize(path, type = 'option')
|
34
|
-
@path = Pathname.new(path).expand_path
|
35
|
-
@config_file = @path + 'bolt.yaml'
|
36
|
-
@inventory_file = @path + 'inventory.yaml'
|
37
|
-
@modulepath = [(@path + 'modules').to_s, (@path + 'site-modules').to_s, (@path + 'site').to_s]
|
38
|
-
@hiera_config = @path + 'hiera.yaml'
|
39
|
-
@puppetfile = @path + 'Puppetfile'
|
40
|
-
@rerunfile = @path + '.rerun.json'
|
41
|
-
@resource_types = @path + '.resource_types'
|
42
|
-
@type = type
|
43
|
-
end
|
44
|
-
|
45
|
-
def to_s
|
46
|
-
@path.to_s
|
47
|
-
end
|
48
|
-
|
49
|
-
def eql?(other)
|
50
|
-
path == other.path
|
51
|
-
end
|
52
|
-
alias == eql?
|
53
|
-
end
|
54
|
-
end
|
data/lib/bolt/plugin/pkcs7.rb
DELETED
@@ -1,104 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'bolt/secret/base'
|
4
|
-
require 'fileutils'
|
5
|
-
|
6
|
-
module Bolt
|
7
|
-
class Plugin
|
8
|
-
class Pkcs7 < Bolt::Secret::Base
|
9
|
-
def self.validate_config(config = {})
|
10
|
-
known_keys = %w[private-key public-key keysize]
|
11
|
-
known_keys.each do |key|
|
12
|
-
unless key.is_a? String
|
13
|
-
raise Bolt::ValidationError, "Invalid config for pkcs7 plugin: '#{key}' is not a String"
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
config.each_key do |key|
|
18
|
-
unless known_keys.include?(key)
|
19
|
-
raise Bolt::ValidationError, "Unpexpected key in pkcs7 plugin config: #{key}"
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def name
|
25
|
-
'pkcs7'
|
26
|
-
end
|
27
|
-
|
28
|
-
def initialize(config:, context:, **_opts)
|
29
|
-
self.class.validate_config(config)
|
30
|
-
require 'openssl'
|
31
|
-
@context = context
|
32
|
-
@options = config || {}
|
33
|
-
@logger = Logging.logger[self]
|
34
|
-
end
|
35
|
-
|
36
|
-
def boltdir
|
37
|
-
@context.boltdir
|
38
|
-
end
|
39
|
-
|
40
|
-
def private_key_path
|
41
|
-
path = @options['private-key'] || 'keys/private_key.pkcs7.pem'
|
42
|
-
path = File.expand_path(path, boltdir)
|
43
|
-
@logger.debug("Using private-key: #{path}")
|
44
|
-
path
|
45
|
-
end
|
46
|
-
|
47
|
-
def private_key
|
48
|
-
@private_key ||= OpenSSL::PKey::RSA.new(File.read(private_key_path))
|
49
|
-
end
|
50
|
-
|
51
|
-
def public_key_path
|
52
|
-
path = @options['public-key'] || 'keys/public_key.pkcs7.pem'
|
53
|
-
path = File.expand_path(path, boltdir)
|
54
|
-
@logger.debug("Using public-key: #{path}")
|
55
|
-
path
|
56
|
-
end
|
57
|
-
|
58
|
-
def public_key
|
59
|
-
@public_key ||= OpenSSL::X509::Certificate.new(File.read(public_key_path))
|
60
|
-
end
|
61
|
-
|
62
|
-
def keysize
|
63
|
-
@options['keysize'] || 2048
|
64
|
-
end
|
65
|
-
|
66
|
-
# The following implementations are intended to be compatible with hiera-eyaml
|
67
|
-
def encrypt_value(plaintext)
|
68
|
-
cipher = OpenSSL::Cipher::AES.new(256, :CBC)
|
69
|
-
OpenSSL::PKCS7.encrypt([public_key], plaintext, cipher, OpenSSL::PKCS7::BINARY).to_der
|
70
|
-
end
|
71
|
-
|
72
|
-
def decrypt_value(ciphertext)
|
73
|
-
pkcs7 = OpenSSL::PKCS7.new(ciphertext)
|
74
|
-
pkcs7.decrypt(private_key, public_key)
|
75
|
-
end
|
76
|
-
|
77
|
-
def secret_createkeys
|
78
|
-
key = OpenSSL::PKey::RSA.new(keysize)
|
79
|
-
|
80
|
-
cert = OpenSSL::X509::Certificate.new
|
81
|
-
cert.subject = OpenSSL::X509::Name.parse('/')
|
82
|
-
cert.serial = 1
|
83
|
-
cert.version = 2
|
84
|
-
cert.not_before = Time.now
|
85
|
-
cert.not_after = Time.now + 50 * 365 * 24 * 60 * 60
|
86
|
-
cert.public_key = key.public_key
|
87
|
-
cert.sign(key, OpenSSL::Digest.new('SHA512'))
|
88
|
-
|
89
|
-
@logger.warn("Overwriting private-key '#{private_key_path}'") if File.exist?(private_key_path)
|
90
|
-
@logger.warn("Overwriting public-key '#{public_key_path}'") if File.exist?(public_key_path)
|
91
|
-
|
92
|
-
private_keydir = File.dirname(private_key_path)
|
93
|
-
FileUtils.mkdir_p(private_keydir) unless File.exist?(private_keydir)
|
94
|
-
FileUtils.touch(private_key_path)
|
95
|
-
File.chmod(0o600, private_key_path)
|
96
|
-
File.write(private_key_path, key.to_pem)
|
97
|
-
|
98
|
-
public_keydir = File.dirname(public_key_path)
|
99
|
-
FileUtils.mkdir_p(public_keydir) unless File.exist?(public_keydir)
|
100
|
-
File.write(public_key_path, cert.to_pem)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|