puppet 6.27.0 → 6.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 puppet might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Gemfile.lock +71 -11
- data/lib/puppet/agent.rb +47 -11
- data/lib/puppet/application/agent.rb +2 -12
- data/lib/puppet/http/client.rb +22 -2
- data/lib/puppet/provider/package/puppetserver_gem.rb +7 -16
- data/lib/puppet/provider/package/windows/exe_package.rb +30 -1
- data/lib/puppet/provider/package/windows/package.rb +2 -1
- data/lib/puppet/provider/package/windows.rb +14 -1
- data/lib/puppet/provider/user/directoryservice.rb +5 -0
- data/lib/puppet/ssl/ssl_provider.rb +65 -12
- data/lib/puppet/ssl/state_machine.rb +13 -17
- data/lib/puppet/type/user.rb +3 -0
- data/lib/puppet/version.rb +1 -1
- data/lib/puppet.rb +1 -14
- data/man/man5/puppet.conf.5 +2 -2
- data/man/man8/puppet-agent.8 +1 -1
- data/man/man8/puppet-apply.8 +1 -1
- data/man/man8/puppet-catalog.8 +1 -1
- data/man/man8/puppet-config.8 +1 -1
- data/man/man8/puppet-describe.8 +1 -1
- data/man/man8/puppet-device.8 +1 -1
- data/man/man8/puppet-doc.8 +1 -1
- data/man/man8/puppet-epp.8 +1 -1
- data/man/man8/puppet-facts.8 +1 -1
- data/man/man8/puppet-filebucket.8 +1 -1
- data/man/man8/puppet-generate.8 +1 -1
- data/man/man8/puppet-help.8 +1 -1
- data/man/man8/puppet-key.8 +1 -1
- data/man/man8/puppet-lookup.8 +1 -1
- data/man/man8/puppet-man.8 +1 -1
- data/man/man8/puppet-module.8 +1 -1
- data/man/man8/puppet-node.8 +1 -1
- data/man/man8/puppet-parser.8 +1 -1
- data/man/man8/puppet-plugin.8 +1 -1
- data/man/man8/puppet-report.8 +1 -1
- data/man/man8/puppet-resource.8 +1 -1
- data/man/man8/puppet-script.8 +1 -1
- data/man/man8/puppet-ssl.8 +1 -1
- data/man/man8/puppet-status.8 +1 -1
- data/man/man8/puppet.8 +2 -2
- data/spec/integration/application/agent_spec.rb +108 -0
- data/spec/integration/http/client_spec.rb +27 -10
- data/spec/lib/puppet_spec/https.rb +1 -1
- data/spec/lib/puppet_spec/puppetserver.rb +39 -2
- data/spec/unit/agent_spec.rb +28 -2
- data/spec/unit/application/agent_spec.rb +26 -16
- data/spec/unit/daemon_spec.rb +2 -11
- data/spec/unit/http/client_spec.rb +18 -0
- data/spec/unit/provider/package/puppetserver_gem_spec.rb +2 -2
- data/spec/unit/provider/package/windows/exe_package_spec.rb +17 -0
- data/spec/unit/ssl/ssl_provider_spec.rb +75 -1
- data/spec/unit/ssl/state_machine_spec.rb +1 -0
- data/tasks/generate_cert_fixtures.rake +5 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4a5961fa6df54cdc74777c8fbab36fad2ae62bbd11ab0bbb80cccbb2ba062a37
|
4
|
+
data.tar.gz: 3747fb6b31a88749e0ab737d599be3b0df1e89b421d9601e3ce13a803725c140
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 465ace5e96735204aba54d8135aca487329238e36b2250cd0c0fd022306f7104a3c9f89c79370886d9c9182862f0d96d3e2621cb1b5fa1af965f47945994c671
|
7
|
+
data.tar.gz: 8e83132e776e4f6e0291c2e28d8ea01c57cbb35093234ee3d3b109e6d22af16eb33b32e3deccf888d006837542c61726c633d185c8f16717f787d2a73373fe87
|
data/Gemfile.lock
CHANGED
@@ -1,19 +1,21 @@
|
|
1
1
|
GIT
|
2
2
|
remote: https://github.com/puppetlabs/packaging
|
3
|
-
revision:
|
3
|
+
revision: 6edc2f8e4ebe3cbea96c3af9c294bcd6e2953648
|
4
4
|
branch: 1.0.x
|
5
5
|
specs:
|
6
|
-
packaging (0.
|
6
|
+
packaging (0.107.0.9.g6edc2f8)
|
7
7
|
apt_stage_artifacts
|
8
8
|
artifactory (~> 3)
|
9
9
|
csv (= 3.1.5)
|
10
|
+
google-cloud-storage
|
11
|
+
googleauth
|
10
12
|
rake (>= 12.3)
|
11
13
|
release-metrics
|
12
14
|
|
13
15
|
PATH
|
14
16
|
remote: .
|
15
17
|
specs:
|
16
|
-
puppet (6.
|
18
|
+
puppet (6.28.0)
|
17
19
|
CFPropertyList (~> 2.2)
|
18
20
|
concurrent-ruby (~> 1.0)
|
19
21
|
deep_merge (~> 1.0)
|
@@ -31,7 +33,7 @@ GEM
|
|
31
33
|
CFPropertyList (2.3.6)
|
32
34
|
addressable (2.8.0)
|
33
35
|
public_suffix (>= 2.0.2, < 5.0)
|
34
|
-
apt_stage_artifacts (0.
|
36
|
+
apt_stage_artifacts (0.11.0)
|
35
37
|
docopt
|
36
38
|
artifactory (3.0.15)
|
37
39
|
ast (2.4.2)
|
@@ -40,12 +42,19 @@ GEM
|
|
40
42
|
crack (0.4.5)
|
41
43
|
rexml
|
42
44
|
csv (3.1.5)
|
45
|
+
declarative (0.0.20)
|
43
46
|
deep_merge (1.2.2)
|
44
47
|
diff-lcs (1.5.0)
|
48
|
+
digest-crc (0.6.4)
|
49
|
+
rake (>= 12.0.0, < 14.0.0)
|
45
50
|
docopt (0.6.1)
|
46
|
-
facter (4.2.
|
51
|
+
facter (4.2.10)
|
47
52
|
hocon (~> 1.3)
|
48
53
|
thor (>= 1.0.1, < 2.0)
|
54
|
+
faraday (2.3.0)
|
55
|
+
faraday-net_http (~> 2.0)
|
56
|
+
ruby2_keywords (>= 0.0.4)
|
57
|
+
faraday-net_http (2.0.3)
|
49
58
|
fast_gettext (1.1.2)
|
50
59
|
ffi (1.15.5)
|
51
60
|
gettext (3.2.9)
|
@@ -55,9 +64,43 @@ GEM
|
|
55
64
|
fast_gettext (~> 1.1.0)
|
56
65
|
gettext (>= 3.0.2, < 3.3.0)
|
57
66
|
locale
|
67
|
+
google-apis-core (0.7.0)
|
68
|
+
addressable (~> 2.5, >= 2.5.1)
|
69
|
+
googleauth (>= 0.16.2, < 2.a)
|
70
|
+
httpclient (>= 2.8.1, < 3.a)
|
71
|
+
mini_mime (~> 1.0)
|
72
|
+
representable (~> 3.0)
|
73
|
+
retriable (>= 2.0, < 4.a)
|
74
|
+
rexml
|
75
|
+
webrick
|
76
|
+
google-apis-iamcredentials_v1 (0.13.0)
|
77
|
+
google-apis-core (>= 0.7, < 2.a)
|
78
|
+
google-apis-storage_v1 (0.18.0)
|
79
|
+
google-apis-core (>= 0.7, < 2.a)
|
80
|
+
google-cloud-core (1.6.0)
|
81
|
+
google-cloud-env (~> 1.0)
|
82
|
+
google-cloud-errors (~> 1.0)
|
83
|
+
google-cloud-env (1.6.0)
|
84
|
+
faraday (>= 0.17.3, < 3.0)
|
85
|
+
google-cloud-errors (1.2.0)
|
86
|
+
google-cloud-storage (1.37.0)
|
87
|
+
addressable (~> 2.8)
|
88
|
+
digest-crc (~> 0.4)
|
89
|
+
google-apis-iamcredentials_v1 (~> 0.1)
|
90
|
+
google-apis-storage_v1 (~> 0.1)
|
91
|
+
google-cloud-core (~> 1.6)
|
92
|
+
googleauth (>= 0.16.2, < 2.a)
|
93
|
+
mini_mime (~> 1.0)
|
94
|
+
googleauth (1.2.0)
|
95
|
+
faraday (>= 0.17.3, < 3.a)
|
96
|
+
jwt (>= 1.4, < 3.0)
|
97
|
+
memoist (~> 0.16)
|
98
|
+
multi_json (~> 1.11)
|
99
|
+
os (>= 0.9, < 2.0)
|
100
|
+
signet (>= 0.16, < 2.a)
|
58
101
|
hashdiff (1.0.1)
|
59
|
-
hiera (3.
|
60
|
-
hiera-eyaml (3.
|
102
|
+
hiera (3.9.0)
|
103
|
+
hiera-eyaml (3.3.0)
|
61
104
|
highline
|
62
105
|
optimist
|
63
106
|
highline (2.0.3)
|
@@ -66,14 +109,18 @@ GEM
|
|
66
109
|
httpclient (2.8.3)
|
67
110
|
json-schema (2.8.1)
|
68
111
|
addressable (>= 2.4)
|
112
|
+
jwt (2.4.1)
|
69
113
|
locale (2.1.3)
|
114
|
+
memoist (0.16.2)
|
70
115
|
memory_profiler (1.0.0)
|
71
116
|
method_source (1.0.0)
|
117
|
+
mini_mime (1.1.2)
|
72
118
|
minitar (0.9)
|
73
|
-
msgpack (1.5.
|
119
|
+
msgpack (1.5.3)
|
74
120
|
multi_json (1.15.0)
|
75
121
|
mustache (1.1.1)
|
76
122
|
optimist (3.0.1)
|
123
|
+
os (1.1.4)
|
77
124
|
parallel (1.22.1)
|
78
125
|
parser (2.7.2.0)
|
79
126
|
ast (~> 2.4.1)
|
@@ -81,7 +128,7 @@ GEM
|
|
81
128
|
pry (0.14.1)
|
82
129
|
coderay (~> 1.1)
|
83
130
|
method_source (~> 1.0)
|
84
|
-
public_suffix (4.0.
|
131
|
+
public_suffix (4.0.7)
|
85
132
|
puppet-resource_api (1.8.14)
|
86
133
|
hocon (>= 1.0)
|
87
134
|
puppetserver-ca (1.11.7)
|
@@ -95,6 +142,11 @@ GEM
|
|
95
142
|
release-metrics (1.1.0)
|
96
143
|
csv
|
97
144
|
docopt
|
145
|
+
representable (3.2.0)
|
146
|
+
declarative (< 0.1.0)
|
147
|
+
trailblazer-option (>= 0.1.1, < 0.2.0)
|
148
|
+
uber (< 0.2.0)
|
149
|
+
retriable (3.1.2)
|
98
150
|
rexml (3.2.5)
|
99
151
|
ronn (0.7.3)
|
100
152
|
hpricot (>= 0.8.2)
|
@@ -127,10 +179,18 @@ GEM
|
|
127
179
|
rubocop (~> 0.49.0)
|
128
180
|
ruby-prof (1.4.3)
|
129
181
|
ruby-progressbar (1.11.0)
|
182
|
+
ruby2_keywords (0.0.5)
|
130
183
|
scanf (1.0.0)
|
131
184
|
semantic_puppet (1.0.4)
|
185
|
+
signet (0.17.0)
|
186
|
+
addressable (~> 2.8)
|
187
|
+
faraday (>= 0.17.5, < 3.a)
|
188
|
+
jwt (>= 1.5, < 3.0)
|
189
|
+
multi_json (~> 1.10)
|
132
190
|
text (1.3.1)
|
133
191
|
thor (1.2.1)
|
192
|
+
trailblazer-option (0.1.2)
|
193
|
+
uber (0.1.0)
|
134
194
|
unicode-display_width (1.8.0)
|
135
195
|
vcr (5.1.0)
|
136
196
|
webmock (3.14.0)
|
@@ -138,7 +198,7 @@ GEM
|
|
138
198
|
crack (>= 0.3.2)
|
139
199
|
hashdiff (>= 0.4.0, < 2.0.0)
|
140
200
|
webrick (1.7.0)
|
141
|
-
yard (0.9.
|
201
|
+
yard (0.9.28)
|
142
202
|
webrick (~> 1.7.0)
|
143
203
|
|
144
204
|
PLATFORMS
|
@@ -176,4 +236,4 @@ DEPENDENCIES
|
|
176
236
|
yard
|
177
237
|
|
178
238
|
BUNDLED WITH
|
179
|
-
2.3.
|
239
|
+
2.3.10
|
data/lib/puppet/agent.rb
CHANGED
@@ -38,26 +38,51 @@ class Puppet::Agent
|
|
38
38
|
# Perform a run with our client.
|
39
39
|
def run(client_options = {})
|
40
40
|
if disabled?
|
41
|
-
|
41
|
+
log_disabled_message
|
42
42
|
return
|
43
43
|
end
|
44
44
|
|
45
45
|
result = nil
|
46
46
|
wait_for_lock_deadline = nil
|
47
47
|
block_run = Puppet::Application.controlled_run do
|
48
|
-
splay
|
48
|
+
# splay may sleep for awhile when running onetime! If not onetime, then
|
49
|
+
# the job scheduler splays (only once) so that agents assign themselves a
|
50
|
+
# slot within the splay interval.
|
51
|
+
do_splay = client_options.fetch(:splay, Puppet[:splay])
|
52
|
+
if do_splay
|
53
|
+
splay(do_splay)
|
54
|
+
|
55
|
+
if disabled?
|
56
|
+
log_disabled_message
|
57
|
+
break
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# waiting for certs may sleep for awhile depending on onetime, waitforcert and maxwaitforcert!
|
62
|
+
# this needs to happen before forking so that if we fail to obtain certs and try to exit, then
|
63
|
+
# we exit the main process and not the forked child.
|
64
|
+
ssl_context = wait_for_certificates(client_options)
|
65
|
+
|
49
66
|
result = run_in_fork(should_fork) do
|
50
67
|
with_client(client_options[:transaction_uuid], client_options[:job_id]) do |client|
|
51
68
|
client_args = client_options.merge(:pluginsync => Puppet::Configurer.should_pluginsync?)
|
52
69
|
begin
|
70
|
+
# lock may sleep for awhile depending on waitforlock and maxwaitforlock!
|
53
71
|
lock do
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
72
|
+
if disabled?
|
73
|
+
log_disabled_message
|
74
|
+
nil
|
75
|
+
else
|
76
|
+
# NOTE: Timeout is pretty heinous as the location in which it
|
77
|
+
# throws an error is entirely unpredictable, which means that
|
78
|
+
# it can interrupt code blocks that perform cleanup or enforce
|
79
|
+
# sanity. The only thing a Puppet agent should do after this
|
80
|
+
# error is thrown is die with as much dignity as possible.
|
81
|
+
Timeout.timeout(Puppet[:runtimeout], RunTimeoutError) do
|
82
|
+
Puppet.override(ssl_context: ssl_context) do
|
83
|
+
client.run(client_args)
|
84
|
+
end
|
85
|
+
end
|
61
86
|
end
|
62
87
|
end
|
63
88
|
rescue Puppet::LockError
|
@@ -78,12 +103,13 @@ class Puppet::Agent
|
|
78
103
|
end
|
79
104
|
rescue RunTimeoutError => detail
|
80
105
|
Puppet.log_exception(detail, _("Execution of %{client_class} did not complete within %{runtimeout} seconds and was terminated.") %
|
81
|
-
{client_class: client_class,
|
82
|
-
runtimeout: Puppet[:runtimeout]})
|
106
|
+
{client_class: client_class, runtimeout: Puppet[:runtimeout]})
|
83
107
|
nil
|
84
108
|
rescue StandardError => detail
|
85
109
|
Puppet.log_exception(detail, _("Could not run %{client_class}: %{detail}") % { client_class: client_class, detail: detail })
|
86
110
|
nil
|
111
|
+
ensure
|
112
|
+
Puppet.runtime[:http].close
|
87
113
|
end
|
88
114
|
end
|
89
115
|
end
|
@@ -137,4 +163,14 @@ class Puppet::Agent
|
|
137
163
|
ensure
|
138
164
|
@client = nil
|
139
165
|
end
|
166
|
+
|
167
|
+
def wait_for_certificates(options)
|
168
|
+
waitforcert = options[:waitforcert] || (Puppet[:onetime] ? 0 : Puppet[:waitforcert])
|
169
|
+
sm = Puppet::SSL::StateMachine.new(waitforcert: waitforcert, onetime: Puppet[:onetime])
|
170
|
+
sm.ensure_client_certificate
|
171
|
+
end
|
172
|
+
|
173
|
+
def log_disabled_message
|
174
|
+
Puppet.notice _("Skipping run of %{client_class}; administratively disabled (Reason: '%{disable_message}');\nUse 'puppet agent --enable' to re-enable.") % { client_class: client_class, disable_message: disable_message }
|
175
|
+
end
|
140
176
|
end
|
@@ -383,15 +383,11 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
|
|
383
383
|
|
384
384
|
log_config if Puppet[:daemonize]
|
385
385
|
|
386
|
-
# run ssl state machine, waiting if needed
|
387
|
-
ssl_context = wait_for_certificates
|
388
|
-
|
389
386
|
# Each application is responsible for pushing loaders onto the context.
|
390
387
|
# Use the current environment that has already been established, though
|
391
388
|
# it may change later during the configurer run.
|
392
389
|
env = Puppet.lookup(:current_environment)
|
393
|
-
Puppet.override(
|
394
|
-
current_environment: env,
|
390
|
+
Puppet.override(current_environment: env,
|
395
391
|
loaders: Puppet::Pops::Loaders.new(env, true)) do
|
396
392
|
if Puppet[:onetime]
|
397
393
|
onetime(daemon)
|
@@ -434,7 +430,7 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
|
|
434
430
|
|
435
431
|
def onetime(daemon)
|
436
432
|
begin
|
437
|
-
exitstatus = daemon.agent.run({:job_id => options[:job_id], :start_time => options[:start_time]})
|
433
|
+
exitstatus = daemon.agent.run({:job_id => options[:job_id], :start_time => options[:start_time], :waitforcert => options[:waitforcert]})
|
438
434
|
rescue => detail
|
439
435
|
Puppet.log_exception(detail)
|
440
436
|
end
|
@@ -524,10 +520,4 @@ Copyright (c) 2011 Puppet Inc., LLC Licensed under the Apache 2.0 License
|
|
524
520
|
|
525
521
|
daemon
|
526
522
|
end
|
527
|
-
|
528
|
-
def wait_for_certificates
|
529
|
-
waitforcert = options[:waitforcert] || (Puppet[:onetime] ? 0 : Puppet[:waitforcert])
|
530
|
-
sm = Puppet::SSL::StateMachine.new(waitforcert: waitforcert)
|
531
|
-
sm.ensure_client_certificate
|
532
|
-
end
|
533
523
|
end
|
data/lib/puppet/http/client.rb
CHANGED
@@ -25,7 +25,7 @@ class Puppet::HTTP::Client
|
|
25
25
|
# used if :include_system_store is set to true
|
26
26
|
# @param [Integer] redirect_limit default number of HTTP redirections to allow
|
27
27
|
# in a given request. Can also be specified per-request.
|
28
|
-
# @param [Integer] retry_limit number of HTTP
|
28
|
+
# @param [Integer] retry_limit number of HTTP retries allowed in a given
|
29
29
|
# request
|
30
30
|
#
|
31
31
|
def initialize(pool: Puppet::Network::HTTP::Pool.new(Puppet[:http_keepalive_timeout]), ssl_context: nil, system_ssl_context: nil, redirect_limit: 10, retry_limit: 100)
|
@@ -272,6 +272,24 @@ class Puppet::HTTP::Client
|
|
272
272
|
#
|
273
273
|
def close
|
274
274
|
@pool.close
|
275
|
+
@default_ssl_context = nil
|
276
|
+
@default_system_ssl_context = nil
|
277
|
+
end
|
278
|
+
|
279
|
+
def default_ssl_context
|
280
|
+
cert = Puppet::X509::CertProvider.new
|
281
|
+
password = cert.load_private_key_password
|
282
|
+
|
283
|
+
ssl = Puppet::SSL::SSLProvider.new
|
284
|
+
ctx = ssl.load_context(certname: Puppet[:certname], password: password)
|
285
|
+
ssl.print(ctx)
|
286
|
+
ctx
|
287
|
+
rescue => e
|
288
|
+
# TRANSLATORS: `message` is an already translated string of why SSL failed to initialize
|
289
|
+
Puppet.log_exception(e, _("Failed to initialize SSL: %{message}") % { message: e.message })
|
290
|
+
# TRANSLATORS: `puppet agent -t` is a command and should not be translated
|
291
|
+
Puppet.err(_("Run `puppet agent -t`"))
|
292
|
+
raise e
|
275
293
|
end
|
276
294
|
|
277
295
|
protected
|
@@ -408,7 +426,9 @@ class Puppet::HTTP::Client
|
|
408
426
|
cacerts = cert_provider.load_cacerts || []
|
409
427
|
|
410
428
|
ssl = Puppet::SSL::SSLProvider.new
|
411
|
-
@default_system_ssl_context = ssl.create_system_context(cacerts: cacerts)
|
429
|
+
@default_system_ssl_context = ssl.create_system_context(cacerts: cacerts, include_client_cert: true)
|
430
|
+
ssl.print(@default_system_ssl_context)
|
431
|
+
@default_system_ssl_context
|
412
432
|
end
|
413
433
|
|
414
434
|
def apply_auth(request, basic_auth)
|
@@ -53,7 +53,7 @@ Puppet::Type.type(:package).provide :puppetserver_gem, :parent => :gem do
|
|
53
53
|
end
|
54
54
|
|
55
55
|
if options[:local]
|
56
|
-
list = execute_rubygems_list_command(
|
56
|
+
list = execute_rubygems_list_command(command_options)
|
57
57
|
else
|
58
58
|
begin
|
59
59
|
list = puppetservercmd(command_options)
|
@@ -137,7 +137,7 @@ Puppet::Type.type(:package).provide :puppetserver_gem, :parent => :gem do
|
|
137
137
|
# for example: json (1.8.3 java)
|
138
138
|
# but java platform gems should not be managed by this (or any) provider.
|
139
139
|
|
140
|
-
def self.execute_rubygems_list_command(
|
140
|
+
def self.execute_rubygems_list_command(command_options)
|
141
141
|
puppetserver_default_gem_home = '/opt/puppetlabs/server/data/puppetserver/jruby-gems'
|
142
142
|
puppetserver_default_vendored_jruby_gems = '/opt/puppetlabs/server/data/puppetserver/vendored-jruby-gems'
|
143
143
|
puppet_default_vendor_gems = '/opt/puppetlabs/puppet/lib/ruby/vendor_gems'
|
@@ -157,24 +157,15 @@ Puppet::Type.type(:package).provide :puppetserver_gem, :parent => :gem do
|
|
157
157
|
gem_env['GEM_PATH'] = puppetserver_conf['jruby-puppet'].key?('gem-path') ? puppetserver_conf['jruby-puppet']['gem-path'].join(':') : puppetserver_default_gem_path
|
158
158
|
end
|
159
159
|
gem_env['GEM_SPEC_CACHE'] = "/tmp/#{$$}"
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
sio_err = StringIO.new
|
165
|
-
stream_ui = Gem::StreamUI.new(sio_inn, sio_out, sio_err, false)
|
166
|
-
gem_list_cmd = Gem::Commands::ListCommand.new
|
167
|
-
gem_list_cmd.options[:domain] = :local
|
168
|
-
gem_list_cmd.options[:args] = [gem_regex] if gem_regex
|
169
|
-
gem_list_cmd.ui = stream_ui
|
170
|
-
gem_list_cmd.execute
|
160
|
+
|
161
|
+
# Remove the 'gem' from the command_options
|
162
|
+
command_options.shift
|
163
|
+
gem_out = execute_gem_command(Puppet::Type::Package::ProviderPuppet_gem.provider_command, command_options, gem_env)
|
171
164
|
|
172
165
|
# There is no method exclude default gems from the local gem list,
|
173
166
|
# for example: psych (default: 2.2.2)
|
174
167
|
# but default gems should not be managed by this (or any) provider.
|
175
|
-
gem_list =
|
168
|
+
gem_list = gem_out.lines.reject { |gem| gem =~ / \(default\: / }
|
176
169
|
gem_list.join("\n")
|
177
|
-
ensure
|
178
|
-
Gem.clear_paths
|
179
170
|
end
|
180
171
|
end
|
@@ -17,6 +17,11 @@ class Puppet::Provider::Package::Windows
|
|
17
17
|
'WindowsInstaller',
|
18
18
|
]
|
19
19
|
|
20
|
+
def self.register(path)
|
21
|
+
Puppet::Type::Package::ProviderWindows.paths ||= []
|
22
|
+
Puppet::Type::Package::ProviderWindows.paths << path
|
23
|
+
end
|
24
|
+
|
20
25
|
# Return an instance of the package from the registry, or nil
|
21
26
|
def self.from_registry(name, values)
|
22
27
|
if valid?(name, values)
|
@@ -55,7 +60,31 @@ class Puppet::Provider::Package::Windows
|
|
55
60
|
end
|
56
61
|
|
57
62
|
def self.install_command(resource)
|
58
|
-
|
63
|
+
file_location = resource[:source]
|
64
|
+
if file_location.start_with?('http://', 'https://')
|
65
|
+
tempfile = Tempfile.new(['','.exe'])
|
66
|
+
begin
|
67
|
+
uri = URI(Puppet::Util.uri_encode(file_location))
|
68
|
+
client = Puppet.runtime[:http]
|
69
|
+
client.get(uri, options: { include_system_store: true }) do |response|
|
70
|
+
raise Puppet::HTTP::ResponseError.new(response) unless response.success?
|
71
|
+
|
72
|
+
File.open(tempfile.path, 'wb') do |file|
|
73
|
+
response.read_body do |data|
|
74
|
+
file.write(data)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
rescue => detail
|
79
|
+
raise Puppet::Error.new(_("Error when installing %{package}: %{detail}") % { package: resource[:name] ,detail: detail.message}, detail)
|
80
|
+
ensure
|
81
|
+
self.register(tempfile.path)
|
82
|
+
tempfile.close()
|
83
|
+
file_location = tempfile.path
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
munge(file_location)
|
59
88
|
end
|
60
89
|
|
61
90
|
def uninstall_command
|
@@ -67,7 +67,8 @@ class Puppet::Provider::Package::Windows
|
|
67
67
|
# REMIND: what about msp, etc
|
68
68
|
MsiPackage
|
69
69
|
when /\.exe"?\Z/i
|
70
|
-
fail(_("The source does not exist: '%{source}'") % { source: resource[:source] }) unless
|
70
|
+
fail(_("The source does not exist: '%{source}'") % { source: resource[:source] }) unless
|
71
|
+
Puppet::FileSystem.exist?(resource[:source]) || resource[:source].start_with?('http://', 'https://')
|
71
72
|
ExePackage
|
72
73
|
else
|
73
74
|
fail(_("Don't know how to install '%{source}'") % { source: resource[:source] })
|
@@ -30,6 +30,19 @@ Puppet::Type.type(:package).provide(:windows, :parent => Puppet::Provider::Packa
|
|
30
30
|
has_feature :versionable
|
31
31
|
|
32
32
|
attr_accessor :package
|
33
|
+
class << self
|
34
|
+
attr_accessor :paths
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.post_resource_eval
|
38
|
+
@paths.each do |path|
|
39
|
+
begin
|
40
|
+
Puppet::FileSystem.unlink(path)
|
41
|
+
rescue => detail
|
42
|
+
raise Puppet::Error.new(_("Error when unlinking %{path}: %{detail}") % { path: path ,detail: detail.message}, detail)
|
43
|
+
end
|
44
|
+
end if @paths
|
45
|
+
end
|
33
46
|
|
34
47
|
# Return an array of provider instances
|
35
48
|
def self.instances
|
@@ -64,7 +77,7 @@ Puppet::Type.type(:package).provide(:windows, :parent => Puppet::Provider::Packa
|
|
64
77
|
|
65
78
|
command = [installer.install_command(resource), install_options].flatten.compact.join(' ')
|
66
79
|
working_dir = File.dirname(resource[:source])
|
67
|
-
|
80
|
+
unless Puppet::FileSystem.exist?(working_dir)
|
68
81
|
working_dir = nil
|
69
82
|
end
|
70
83
|
output = execute(command, :failonfail => false, :combine => true, :cwd => working_dir, :suppress_window => true)
|
@@ -401,6 +401,11 @@ Puppet::Type.type(:user).provide :directoryservice do
|
|
401
401
|
# we have to treat the ds cache just like you would in the password=
|
402
402
|
# method.
|
403
403
|
def salt=(value)
|
404
|
+
if (Puppet::Util::Package.versioncmp(self.class.get_os_version, '10.15') >= 0)
|
405
|
+
if value.length != 64
|
406
|
+
self.fail "macOS versions 10.15 and higher require the salt to be 32-bytes. Since Puppet's user resource requires the value to be hex encoded, the length of the salt's string must be 64. Please check your salt and try again."
|
407
|
+
end
|
408
|
+
end
|
404
409
|
if (Puppet::Util::Package.versioncmp(self.class.get_os_version, '10.7') > 0)
|
405
410
|
assert_full_pbkdf2_password
|
406
411
|
|
@@ -42,15 +42,18 @@ class Puppet::SSL::SSLProvider
|
|
42
42
|
# refers to the cacerts bundle in the puppet-agent package.
|
43
43
|
#
|
44
44
|
# Connections made from the returned context will authenticate the server,
|
45
|
-
# i.e. `VERIFY_PEER`, but will not use a client certificate
|
46
|
-
# perform revocation checking.
|
45
|
+
# i.e. `VERIFY_PEER`, but will not use a client certificate (unless requested)
|
46
|
+
# and will not perform revocation checking.
|
47
47
|
#
|
48
48
|
# @param cacerts [Array<OpenSSL::X509::Certificate>] Array of trusted CA certs
|
49
49
|
# @param path [String, nil] A file containing additional trusted CA certs.
|
50
|
+
# @param include_client_cert [true, false] If true, the client cert will be added to the context
|
51
|
+
# allowing mutual TLS authentication. The default is false. If the client cert doesn't exist
|
52
|
+
# then the option will be ignored.
|
50
53
|
# @return [Puppet::SSL::SSLContext] A context to use to create connections
|
51
54
|
# @raise (see #create_context)
|
52
55
|
# @api private
|
53
|
-
def create_system_context(cacerts:, path: Puppet[:ssl_trust_store])
|
56
|
+
def create_system_context(cacerts:, path: Puppet[:ssl_trust_store], include_client_cert: false)
|
54
57
|
store = create_x509_store(cacerts, [], false, include_system_store: true)
|
55
58
|
|
56
59
|
if path
|
@@ -71,6 +74,29 @@ class Puppet::SSL::SSLProvider
|
|
71
74
|
end
|
72
75
|
end
|
73
76
|
|
77
|
+
if include_client_cert
|
78
|
+
cert_provider = Puppet::X509::CertProvider.new
|
79
|
+
private_key = cert_provider.load_private_key(Puppet[:certname], required: false)
|
80
|
+
unless private_key
|
81
|
+
Puppet.warning("Private key for '#{Puppet[:certname]}' does not exist")
|
82
|
+
end
|
83
|
+
|
84
|
+
client_cert = cert_provider.load_client_cert(Puppet[:certname], required: false)
|
85
|
+
unless client_cert
|
86
|
+
Puppet.warning("Client certificate for '#{Puppet[:certname]}' does not exist")
|
87
|
+
end
|
88
|
+
|
89
|
+
if private_key && client_cert
|
90
|
+
client_chain = resolve_client_chain(store, client_cert, private_key)
|
91
|
+
|
92
|
+
return Puppet::SSL::SSLContext.new(
|
93
|
+
store: store, cacerts: cacerts, crls: [],
|
94
|
+
private_key: private_key, client_cert: client_cert, client_chain: client_chain,
|
95
|
+
revocation: false
|
96
|
+
).freeze
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
74
100
|
Puppet::SSL::SSLContext.new(store: store, cacerts: cacerts, crls: [], revocation: false).freeze
|
75
101
|
end
|
76
102
|
|
@@ -107,15 +133,7 @@ class Puppet::SSL::SSLProvider
|
|
107
133
|
raise ArgumentError, _("Client cert is missing") unless client_cert
|
108
134
|
|
109
135
|
store = create_x509_store(cacerts, crls, revocation, include_system_store: include_system_store)
|
110
|
-
client_chain =
|
111
|
-
|
112
|
-
if !private_key.is_a?(OpenSSL::PKey::RSA) && !private_key.is_a?(OpenSSL::PKey::EC)
|
113
|
-
raise Puppet::SSL::SSLError, _("Unsupported key '%{type}'") % { type: private_key.class.name }
|
114
|
-
end
|
115
|
-
|
116
|
-
unless client_cert.check_private_key(private_key)
|
117
|
-
raise Puppet::SSL::SSLError, _("The certificate for '%{name}' does not match its private key") % { name: subject(client_cert) }
|
118
|
-
end
|
136
|
+
client_chain = resolve_client_chain(store, client_cert, private_key)
|
119
137
|
|
120
138
|
Puppet::SSL::SSLContext.new(
|
121
139
|
store: store, cacerts: cacerts, crls: crls,
|
@@ -174,6 +192,27 @@ class Puppet::SSL::SSLProvider
|
|
174
192
|
csr
|
175
193
|
end
|
176
194
|
|
195
|
+
def print(ssl_context, alg = 'SHA256')
|
196
|
+
if Puppet::Util::Log.sendlevel?(:debug)
|
197
|
+
chain = ssl_context.client_chain
|
198
|
+
# print from root to client
|
199
|
+
chain.reverse.each_with_index do |cert, i|
|
200
|
+
digest = Puppet::SSL::Digest.new(alg, cert.to_der)
|
201
|
+
if i == chain.length - 1
|
202
|
+
Puppet.debug(_("Verified client certificate '%{subject}' fingerprint %{digest}") % {subject: cert.subject.to_utf8, digest: digest})
|
203
|
+
else
|
204
|
+
Puppet.debug(_("Verified CA certificate '%{subject}' fingerprint %{digest}") % {subject: cert.subject.to_utf8, digest: digest})
|
205
|
+
end
|
206
|
+
end
|
207
|
+
ssl_context.crls.each do |crl|
|
208
|
+
oid_values = Hash[crl.extensions.map { |ext| [ext.oid, ext.value] }]
|
209
|
+
crlNumber = oid_values['crlNumber'] || 'unknown'
|
210
|
+
authKeyId = (oid_values['authorityKeyIdentifier'] || 'unknown').chomp!
|
211
|
+
Puppet.debug("Using CRL '#{crl.issuer.to_utf8}' authorityKeyIdentifier '#{authKeyId}' crlNumber '#{crlNumber }'")
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
177
216
|
private
|
178
217
|
|
179
218
|
def default_flags
|
@@ -220,6 +259,20 @@ class Puppet::SSL::SSLProvider
|
|
220
259
|
end
|
221
260
|
end
|
222
261
|
|
262
|
+
def resolve_client_chain(store, client_cert, private_key)
|
263
|
+
client_chain = verify_cert_with_store(store, client_cert)
|
264
|
+
|
265
|
+
if !private_key.is_a?(OpenSSL::PKey::RSA) && !private_key.is_a?(OpenSSL::PKey::EC)
|
266
|
+
raise Puppet::SSL::SSLError, _("Unsupported key '%{type}'") % { type: private_key.class.name }
|
267
|
+
end
|
268
|
+
|
269
|
+
unless client_cert.check_private_key(private_key)
|
270
|
+
raise Puppet::SSL::SSLError, _("The certificate for '%{name}' does not match its private key") % { name: subject(client_cert) }
|
271
|
+
end
|
272
|
+
|
273
|
+
client_chain
|
274
|
+
end
|
275
|
+
|
223
276
|
def verify_cert_with_store(store, cert)
|
224
277
|
# StoreContext#initialize accepts a chain argument, but it's set to [] because
|
225
278
|
# puppet requires any intermediate CA certs needed to complete the client's
|
@@ -27,6 +27,15 @@ class Puppet::SSL::StateMachine
|
|
27
27
|
detail.set_backtrace(cause.backtrace)
|
28
28
|
Error.new(@machine, message, detail)
|
29
29
|
end
|
30
|
+
|
31
|
+
def log_error(message)
|
32
|
+
# When running daemonized we set stdout to /dev/null, so write to the log instead
|
33
|
+
if Puppet[:daemonize]
|
34
|
+
Puppet.err(message)
|
35
|
+
else
|
36
|
+
$stdout.puts(message)
|
37
|
+
end
|
38
|
+
end
|
30
39
|
end
|
31
40
|
|
32
41
|
# Load existing CA certs or download them. Transition to NeedCRLs.
|
@@ -270,15 +279,15 @@ class Puppet::SSL::StateMachine
|
|
270
279
|
def next_state
|
271
280
|
time = @machine.waitforcert
|
272
281
|
if time < 1
|
273
|
-
|
282
|
+
log_error(_("Exiting now because the waitforcert setting is set to 0."))
|
274
283
|
exit(1)
|
275
284
|
elsif Time.now.to_i > @machine.wait_deadline
|
276
|
-
|
285
|
+
log_error(_("Couldn't fetch certificate from CA server; you might still need to sign this agent's certificate (%{name}). Exiting now because the maxwaitforcert timeout has been exceeded.") % {name: Puppet[:certname] })
|
277
286
|
exit(1)
|
278
287
|
else
|
279
288
|
Puppet.info(_("Will try again in %{time} seconds.") % {time: time})
|
280
289
|
|
281
|
-
# close
|
290
|
+
# close http/tls and session state before sleeping
|
282
291
|
Puppet.runtime[:http].close
|
283
292
|
@machine.session = Puppet.runtime[:http].create_session
|
284
293
|
|
@@ -417,20 +426,7 @@ class Puppet::SSL::StateMachine
|
|
417
426
|
def ensure_client_certificate
|
418
427
|
final_state = run_machine(NeedLock.new(self), Done)
|
419
428
|
ssl_context = final_state.ssl_context
|
420
|
-
|
421
|
-
if Puppet::Util::Log.sendlevel?(:debug)
|
422
|
-
chain = ssl_context.client_chain
|
423
|
-
# print from root to client
|
424
|
-
chain.reverse.each_with_index do |cert, i|
|
425
|
-
digest = Puppet::SSL::Digest.new(@digest, cert.to_der)
|
426
|
-
if i == chain.length - 1
|
427
|
-
Puppet.debug(_("Verified client certificate '%{subject}' fingerprint %{digest}") % {subject: cert.subject.to_utf8, digest: digest})
|
428
|
-
else
|
429
|
-
Puppet.debug(_("Verified CA certificate '%{subject}' fingerprint %{digest}") % {subject: cert.subject.to_utf8, digest: digest})
|
430
|
-
end
|
431
|
-
end
|
432
|
-
end
|
433
|
-
|
429
|
+
@ssl_provider.print(ssl_context, @digest)
|
434
430
|
ssl_context
|
435
431
|
end
|
436
432
|
|