puppet 8.1.0-x86-mingw32 → 8.3.1-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +39 -45
  4. data/ext/project_data.yaml +2 -2
  5. data/lib/puppet/application/doc.rb +1 -1
  6. data/lib/puppet/application/ssl.rb +42 -7
  7. data/lib/puppet/application.rb +5 -1
  8. data/lib/puppet/defaults.rb +17 -5
  9. data/lib/puppet/face/config.rb +1 -1
  10. data/lib/puppet/face/epp.rb +2 -2
  11. data/lib/puppet/face/module/list.rb +2 -2
  12. data/lib/puppet/face/parser.rb +1 -1
  13. data/lib/puppet/functions/split.rb +28 -1
  14. data/lib/puppet/http/client.rb +12 -5
  15. data/lib/puppet/http/service/ca.rb +25 -0
  16. data/lib/puppet/indirector/facts/facter.rb +1 -1
  17. data/lib/puppet/indirector/file_bucket_file/file.rb +1 -1
  18. data/lib/puppet/indirector/indirection.rb +1 -1
  19. data/lib/puppet/info_service/task_information_service.rb +1 -1
  20. data/lib/puppet/module_tool.rb +1 -1
  21. data/lib/puppet/network/formats.rb +3 -3
  22. data/lib/puppet/network/http/memory_response.rb +1 -1
  23. data/lib/puppet/node/environment.rb +6 -4
  24. data/lib/puppet/parameter/value_collection.rb +1 -1
  25. data/lib/puppet/parser/files.rb +4 -3
  26. data/lib/puppet/parser/functions.rb +1 -1
  27. data/lib/puppet/pops/evaluator/deferred_resolver.rb +20 -3
  28. data/lib/puppet/pops/loader/loader_paths.rb +4 -4
  29. data/lib/puppet/pops/lookup/explainer.rb +1 -1
  30. data/lib/puppet/pops/lookup/hiera_config.rb +1 -1
  31. data/lib/puppet/pops/model/factory.rb +1 -1
  32. data/lib/puppet/pops/model/tree_dumper.rb +1 -1
  33. data/lib/puppet/pops/parser/epp_support.rb +1 -1
  34. data/lib/puppet/pops/parser/evaluating_parser.rb +1 -1
  35. data/lib/puppet/pops/parser/pn_parser.rb +1 -1
  36. data/lib/puppet/pops/pn.rb +1 -1
  37. data/lib/puppet/pops/serialization/json_path.rb +1 -1
  38. data/lib/puppet/pops/time/timespan.rb +4 -4
  39. data/lib/puppet/pops/types/ruby_generator.rb +2 -2
  40. data/lib/puppet/pops/types/string_converter.rb +6 -6
  41. data/lib/puppet/pops/types/type_formatter.rb +2 -2
  42. data/lib/puppet/pops/types/types.rb +1 -1
  43. data/lib/puppet/provider/nameservice/directoryservice.rb +2 -2
  44. data/lib/puppet/provider/package/apt.rb +1 -1
  45. data/lib/puppet/provider/package/dnf.rb +1 -1
  46. data/lib/puppet/provider/package/yum.rb +1 -1
  47. data/lib/puppet/provider/user/directoryservice.rb +1 -1
  48. data/lib/puppet/reference/configuration.rb +1 -1
  49. data/lib/puppet/reference/indirection.rb +1 -1
  50. data/lib/puppet/reports.rb +1 -1
  51. data/lib/puppet/ssl/oids.rb +2 -0
  52. data/lib/puppet/ssl/ssl_provider.rb +1 -1
  53. data/lib/puppet/ssl/state_machine.rb +60 -9
  54. data/lib/puppet/transaction/report.rb +1 -1
  55. data/lib/puppet/type/filebucket.rb +1 -1
  56. data/lib/puppet/util/diff.rb +1 -1
  57. data/lib/puppet/util/execution.rb +9 -4
  58. data/lib/puppet/util/inifile.rb +2 -2
  59. data/lib/puppet/util/monkey_patches.rb +18 -0
  60. data/lib/puppet/util/package/version/rpm.rb +1 -1
  61. data/lib/puppet/util/provider_features.rb +1 -1
  62. data/lib/puppet/util/selinux.rb +1 -1
  63. data/lib/puppet/util/windows/access_control_entry.rb +1 -1
  64. data/lib/puppet/util/windows/access_control_list.rb +1 -1
  65. data/lib/puppet/util/windows/adsi.rb +9 -2
  66. data/lib/puppet/util/windows/error.rb +1 -1
  67. data/lib/puppet/util/windows/file.rb +2 -2
  68. data/lib/puppet/util/windows/process.rb +1 -1
  69. data/lib/puppet/util/windows/sid.rb +4 -2
  70. data/lib/puppet/util.rb +2 -3
  71. data/lib/puppet/version.rb +1 -1
  72. data/lib/puppet/x509/cert_provider.rb +13 -2
  73. data/locales/puppet.pot +106 -74
  74. data/man/man5/puppet.conf.5 +16 -2
  75. data/man/man8/puppet-agent.8 +1 -1
  76. data/man/man8/puppet-apply.8 +1 -1
  77. data/man/man8/puppet-catalog.8 +1 -1
  78. data/man/man8/puppet-config.8 +1 -1
  79. data/man/man8/puppet-describe.8 +1 -1
  80. data/man/man8/puppet-device.8 +1 -1
  81. data/man/man8/puppet-doc.8 +1 -1
  82. data/man/man8/puppet-epp.8 +1 -1
  83. data/man/man8/puppet-facts.8 +1 -1
  84. data/man/man8/puppet-filebucket.8 +1 -1
  85. data/man/man8/puppet-generate.8 +1 -1
  86. data/man/man8/puppet-help.8 +1 -1
  87. data/man/man8/puppet-lookup.8 +1 -1
  88. data/man/man8/puppet-module.8 +1 -1
  89. data/man/man8/puppet-node.8 +1 -1
  90. data/man/man8/puppet-parser.8 +1 -1
  91. data/man/man8/puppet-plugin.8 +1 -1
  92. data/man/man8/puppet-report.8 +1 -1
  93. data/man/man8/puppet-resource.8 +1 -1
  94. data/man/man8/puppet-script.8 +1 -1
  95. data/man/man8/puppet-ssl.8 +5 -1
  96. data/man/man8/puppet.8 +2 -2
  97. data/spec/fixtures/ssl/127.0.0.1-key.pem +107 -107
  98. data/spec/fixtures/ssl/127.0.0.1.pem +52 -51
  99. data/spec/fixtures/ssl/bad-basic-constraints.pem +56 -56
  100. data/spec/fixtures/ssl/bad-int-basic-constraints.pem +53 -53
  101. data/spec/fixtures/ssl/ca.pem +54 -54
  102. data/spec/fixtures/ssl/crl.pem +26 -26
  103. data/spec/fixtures/ssl/ec-key.pem +11 -11
  104. data/spec/fixtures/ssl/ec.pem +33 -32
  105. data/spec/fixtures/ssl/encrypted-ec-key.pem +12 -12
  106. data/spec/fixtures/ssl/encrypted-key.pem +108 -108
  107. data/spec/fixtures/ssl/intermediate-agent-crl.pem +26 -26
  108. data/spec/fixtures/ssl/intermediate-agent.pem +56 -56
  109. data/spec/fixtures/ssl/intermediate-crl.pem +29 -29
  110. data/spec/fixtures/ssl/intermediate.pem +53 -53
  111. data/spec/fixtures/ssl/oid-key.pem +107 -107
  112. data/spec/fixtures/ssl/oid.pem +51 -50
  113. data/spec/fixtures/ssl/pluto-key.pem +107 -107
  114. data/spec/fixtures/ssl/pluto.pem +52 -51
  115. data/spec/fixtures/ssl/renewed.pem +67 -0
  116. data/spec/fixtures/ssl/request-key.pem +107 -107
  117. data/spec/fixtures/ssl/request.pem +50 -48
  118. data/spec/fixtures/ssl/revoked-key.pem +107 -107
  119. data/spec/fixtures/ssl/revoked.pem +51 -50
  120. data/spec/fixtures/ssl/signed-key.pem +107 -107
  121. data/spec/fixtures/ssl/signed.pem +49 -48
  122. data/spec/fixtures/ssl/tampered-cert.pem +51 -50
  123. data/spec/fixtures/ssl/tampered-csr.pem +50 -48
  124. data/spec/fixtures/ssl/unknown-127.0.0.1-key.pem +107 -107
  125. data/spec/fixtures/ssl/unknown-127.0.0.1.pem +50 -49
  126. data/spec/fixtures/ssl/unknown-ca-key.pem +107 -107
  127. data/spec/fixtures/ssl/unknown-ca.pem +54 -54
  128. data/spec/integration/application/agent_spec.rb +27 -27
  129. data/spec/integration/application/apply_spec.rb +14 -0
  130. data/spec/integration/http/client_spec.rb +16 -0
  131. data/spec/integration/type/exec_spec.rb +13 -0
  132. data/spec/lib/puppet/test_ca.rb +3 -10
  133. data/spec/lib/puppet_spec/verbose.rb +10 -1
  134. data/spec/unit/agent_spec.rb +2 -9
  135. data/spec/unit/application/ssl_spec.rb +49 -0
  136. data/spec/unit/defaults_spec.rb +2 -40
  137. data/spec/unit/file_system/path_pattern_spec.rb +15 -0
  138. data/spec/unit/functions/split_spec.rb +6 -0
  139. data/spec/unit/http/service/ca_spec.rb +71 -0
  140. data/spec/unit/info_service_spec.rb +1 -1
  141. data/spec/unit/ssl/certificate_signer_spec.rb +17 -0
  142. data/spec/unit/ssl/ssl_provider_spec.rb +21 -1
  143. data/spec/unit/ssl/state_machine_spec.rb +75 -3
  144. data/spec/unit/util/execution_spec.rb +1 -0
  145. data/spec/unit/util/monkey_patches_spec.rb +42 -0
  146. data/spec/unit/util/windows/adsi_spec.rb +25 -0
  147. data/spec/unit/x509/cert_provider_spec.rb +23 -0
  148. data/tasks/generate_cert_fixtures.rake +4 -0
  149. metadata +11 -13
@@ -1,4 +1,4 @@
1
- # Support code for running stuff with warnings disabled.
1
+ # Support code for running stuff with warnings disabled or enabled
2
2
  module Kernel
3
3
  def with_verbose_disabled
4
4
  verbose, $VERBOSE = $VERBOSE, nil
@@ -6,4 +6,13 @@ module Kernel
6
6
  $VERBOSE = verbose
7
7
  return result
8
8
  end
9
+
10
+ def with_verbose_enabled
11
+ verbose, $VERBOSE = $VERBOSE, true
12
+ begin
13
+ yield
14
+ ensure
15
+ $VERBOSE = verbose
16
+ end
17
+ end
9
18
  end
@@ -15,19 +15,12 @@ class AgentTestClient
15
15
  end
16
16
  end
17
17
 
18
- def without_warnings
19
- flag = $VERBOSE
20
- $VERBOSE = nil
21
- yield
22
- $VERBOSE = flag
23
- end
24
-
25
18
  describe Puppet::Agent do
26
19
  before do
27
20
  @agent = Puppet::Agent.new(AgentTestClient, false)
28
21
 
29
22
  # make Puppet::Application safe for stubbing; restore in an :after block; silence warnings for this.
30
- without_warnings { Puppet::Application = Class.new(Puppet::Application) }
23
+ with_verbose_disabled { Puppet::Application = Class.new(Puppet::Application) }
31
24
  allow(Puppet::Application).to receive(:clear?).and_return(true)
32
25
  Puppet::Application.class_eval do
33
26
  class << self
@@ -44,7 +37,7 @@ describe Puppet::Agent do
44
37
 
45
38
  after do
46
39
  # restore Puppet::Application from stub-safe subclass, and silence warnings
47
- without_warnings { Puppet::Application = Puppet::Application.superclass }
40
+ with_verbose_disabled { Puppet::Application = Puppet::Application.superclass }
48
41
  end
49
42
 
50
43
  it "should set its client class at initialization" do
@@ -171,6 +171,50 @@ describe Puppet::Application::Ssl, unless: Puppet::Util::Platform.jruby? do
171
171
  end
172
172
  end
173
173
 
174
+ context 'when generating a CSR' do
175
+ let(:csr_path) { Puppet[:hostcsr] }
176
+ let(:requestdir) { Puppet[:requestdir] }
177
+
178
+ before do
179
+ ssl.command_line.args << 'generate_request'
180
+ end
181
+
182
+ it 'generates an RSA private key' do
183
+ File.unlink(Puppet[:hostprivkey])
184
+
185
+ expects_command_to_pass(%r{Generated certificate request in '#{csr_path}'})
186
+ end
187
+
188
+ it 'generates an EC private key' do
189
+ Puppet[:key_type] = 'ec'
190
+ File.unlink(Puppet[:hostprivkey])
191
+
192
+ expects_command_to_pass(%r{Generated certificate request in '#{csr_path}'})
193
+ end
194
+
195
+ it 'registers OIDs' do
196
+ expect(Puppet::SSL::Oids).to receive(:register_puppet_oids)
197
+
198
+ expects_command_to_pass(%r{Generated certificate request in '#{csr_path}'})
199
+ end
200
+
201
+ it 'saves the CSR locally' do
202
+ expects_command_to_pass(%r{Generated certificate request in '#{csr_path}'})
203
+
204
+ expect(Puppet::FileSystem).to be_exist(csr_path)
205
+ end
206
+
207
+ it 'accepts dns alt names' do
208
+ Puppet[:dns_alt_names] = 'majortom'
209
+
210
+ expects_command_to_pass
211
+
212
+ csr = Puppet::SSL::CertificateRequest.new(name)
213
+ csr.read(csr_path)
214
+ expect(csr.subject_alt_names).to include('DNS:majortom')
215
+ end
216
+ end
217
+
174
218
  context 'when downloading a certificate' do
175
219
  before do
176
220
  ssl.command_line.args << 'download_cert'
@@ -347,6 +391,11 @@ describe Puppet::Application::Ssl, unless: Puppet::Util::Platform.jruby? do
347
391
  expects_command_to_fail(%r{Failed to connect to the CA to determine if certificate #{name} has been cleaned})
348
392
  end
349
393
 
394
+ it 'raises if we have extra args' do
395
+ ssl.command_line.args << 'hostname.example.biz'
396
+ expects_command_to_fail(/Extra arguments detected: hostname.example.biz/)
397
+ end
398
+
350
399
  context 'when deleting local CA' do
351
400
  before do
352
401
  ssl.command_line.args << '--localca'
@@ -3,46 +3,8 @@ require 'puppet/settings'
3
3
 
4
4
  describe "Defaults" do
5
5
  describe ".default_diffargs" do
6
- describe "on AIX" do
7
- before(:each) do
8
- allow(Facter).to receive(:value).with(:kernel).and_return("AIX")
9
- end
10
-
11
- describe "on 5.3" do
12
- before(:each) do
13
- allow(Facter).to receive(:value).with(:kernelmajversion).and_return("5300")
14
- end
15
-
16
- it "should be empty" do
17
- expect(Puppet.default_diffargs).to eq("")
18
- end
19
- end
20
-
21
- [ "",
22
- nil,
23
- "6300",
24
- "7300",
25
- ].each do |kernel_version|
26
- describe "on kernel version #{kernel_version.inspect}" do
27
- before(:each) do
28
- allow(Facter).to receive(:value).with(:kernelmajversion).and_return(kernel_version)
29
- end
30
-
31
- it "should be '-u'" do
32
- expect(Puppet.default_diffargs).to eq("-u")
33
- end
34
- end
35
- end
36
- end
37
-
38
- describe "on everything else" do
39
- before(:each) do
40
- allow(Facter).to receive(:value).with(:kernel).and_return("NOT_AIX")
41
- end
42
-
43
- it "should be '-u'" do
44
- expect(Puppet.default_diffargs).to eq("-u")
45
- end
6
+ it "should be '-u'" do
7
+ expect(Puppet.default_diffargs).to eq("-u")
46
8
  end
47
9
  end
48
10
 
@@ -1,6 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'puppet_spec/files'
3
3
  require 'puppet/file_system'
4
+ require 'puppet/util'
4
5
 
5
6
  describe Puppet::FileSystem::PathPattern do
6
7
  include PuppetSpec::Files
@@ -132,6 +133,20 @@ describe Puppet::FileSystem::PathPattern do
132
133
  File.join(dir, "found_two")])
133
134
  end
134
135
 
136
+ it 'globs wildcard patterns properly' do
137
+ # See PUP-11788 and https://github.com/jruby/jruby/issues/7836.
138
+ pending 'JRuby does not properly handle Dir.glob' if Puppet::Util::Platform.jruby?
139
+
140
+ dir = tmpdir('globtest')
141
+ create_file_in(dir, 'foo.pp')
142
+ create_file_in(dir, 'foo.pp.pp')
143
+
144
+ pattern = Puppet::FileSystem::PathPattern.absolute(File.join(dir, '**/*.pp'))
145
+
146
+ expect(pattern.glob).to match_array([File.join(dir, 'foo.pp'),
147
+ File.join(dir, 'foo.pp.pp')])
148
+ end
149
+
135
150
  def create_file_in(dir, name)
136
151
  File.open(File.join(dir, name), "w") { |f| f.puts "data" }
137
152
  end
@@ -50,4 +50,10 @@ describe 'the split function' do
50
50
  it 'should handle pattern in Regexp Type form with missing regular expression' do
51
51
  expect(split('ab',type_parser.parse('Regexp'))).to eql(['a', 'b'])
52
52
  end
53
+
54
+ it 'should handle sensitive String' do
55
+ expect(split(Puppet::Pops::Types::PSensitiveType::Sensitive.new('a,b'), ',')).to be_a(Puppet::Pops::Types::PSensitiveType::Sensitive)
56
+ expect(split(Puppet::Pops::Types::PSensitiveType::Sensitive.new('a,b'), /,/)).to be_a(Puppet::Pops::Types::PSensitiveType::Sensitive)
57
+ expect(split(Puppet::Pops::Types::PSensitiveType::Sensitive.new('a,b'), type_parser.parse('Regexp[/,/]'))).to be_a(Puppet::Pops::Types::PSensitiveType::Sensitive)
58
+ end
53
59
  end
@@ -207,4 +207,75 @@ describe Puppet::HTTP::Service::Ca do
207
207
  end
208
208
  end
209
209
  end
210
+
211
+ context 'when getting certificates' do
212
+ let(:cert) { cert_fixture('signed.pem') }
213
+ let(:pem) { cert.to_pem }
214
+ let(:url) { "https://www.example.com/puppet-ca/v1/certificate_renewal" }
215
+ let(:cert_context) { Puppet::SSL::SSLContext.new(client_cert: pem) }
216
+ let(:client) { Puppet::HTTP::Client.new(ssl_context: cert_context) }
217
+ let(:session) { Puppet::HTTP::Session.new(client, []) }
218
+ let(:subject) { client.create_session.route_to(:ca) }
219
+
220
+ it "gets a certificate from the 'certificate_renewal' endpoint" do
221
+ stub_request(:post, url).to_return(body: pem)
222
+
223
+ _, body = subject.post_certificate_renewal(cert_context)
224
+ expect(body).to eq(pem)
225
+ end
226
+
227
+ it 'returns the request response' do
228
+ stub_request(:post, url).to_return(body: 'pem')
229
+
230
+ resp, _ = subject.post_certificate_renewal(cert_context)
231
+ expect(resp).to be_a(Puppet::HTTP::Response)
232
+ end
233
+
234
+ it 'accepts text/plain responses' do
235
+ stub_request(:post, url).with(headers: {'Accept' => 'text/plain'})
236
+
237
+ subject.post_certificate_renewal(cert_context)
238
+ end
239
+
240
+ it 'raises an ArgumentError if the SSL context does not contain a client cert' do
241
+ stub_request(:post, url)
242
+ expect { subject.post_certificate_renewal(ssl_context) }.to raise_error(ArgumentError, 'SSL context must contain a client certificate.')
243
+ end
244
+
245
+ it 'raises response error if unsuccessful' do
246
+ stub_request(:post, url).to_return(status: [400, 'Bad Request'])
247
+
248
+ expect {
249
+ subject.post_certificate_renewal(cert_context)
250
+ }.to raise_error do |err|
251
+ expect(err).to be_an_instance_of(Puppet::HTTP::ResponseError)
252
+ expect(err.message).to eq('Bad Request')
253
+ expect(err.response.code).to eq(400)
254
+ end
255
+ end
256
+
257
+ it 'raises a response error if unsuccessful' do
258
+ stub_request(:post, url).to_return(status: [404, 'Not Found'])
259
+
260
+ expect {
261
+ subject.post_certificate_renewal(cert_context)
262
+ }.to raise_error do |err|
263
+ expect(err).to be_an_instance_of(Puppet::HTTP::ResponseError)
264
+ expect(err.message).to eq("Not Found")
265
+ expect(err.response.code).to eq(404)
266
+ end
267
+ end
268
+
269
+ it 'raises a response error if unsuccessful' do
270
+ stub_request(:post, url).to_return(status: [404, 'Forbidden'])
271
+
272
+ expect {
273
+ subject.post_certificate_renewal(cert_context)
274
+ }.to raise_error do |err|
275
+ expect(err).to be_an_instance_of(Puppet::HTTP::ResponseError)
276
+ expect(err.message).to eq("Forbidden")
277
+ expect(err.response.code).to eq(404)
278
+ end
279
+ end
280
+ end
210
281
  end
@@ -47,7 +47,7 @@ describe "Puppet::InfoService" do
47
47
  :content => metadata.to_json}]]})
48
48
  File.write("#{modpath}/#{mod_name}/tasks/atask.json", "NOT JSON")
49
49
 
50
- expect(Puppet).to receive(:send_log).with(:err, 'Failed to validate task')
50
+ expect(Puppet).to receive(:send_log).with(:err, /unexpected token at 'NOT JSON'/)
51
51
 
52
52
  @tasks = Puppet::InfoService.tasks_per_environment(env_name)
53
53
  expect(@tasks.map{|t| t[:name]}).to contain_exactly('test1::btask', 'test1::ctask')
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe Puppet::SSL::CertificateSigner do
4
+ include PuppetSpec::Files
5
+
6
+ let(:wrong_key) { OpenSSL::PKey::RSA.new(512) }
7
+ let(:client_cert) { cert_fixture('signed.pem') }
8
+
9
+ # jruby-openssl >= 0.13.0 (JRuby >= 9.3.5.0) raises an error when signing a
10
+ # certificate when there is a discrepancy between the certificate and key.
11
+ it 'raises if client cert signature is invalid', if: Puppet::Util::Platform.jruby? && RUBY_VERSION.to_f >= 2.6 do
12
+ expect {
13
+ client_cert.sign(wrong_key, OpenSSL::Digest::SHA256.new)
14
+ }.to raise_error(OpenSSL::X509::CertificateError,
15
+ 'invalid public key data')
16
+ end
17
+ end
@@ -338,7 +338,7 @@ describe Puppet::SSL::SSLProvider do
338
338
  end
339
339
  end
340
340
 
341
- it 'raises if intermediate CA signature is invalid' do
341
+ it 'raises if intermediate CA signature is invalid', unless: Puppet::Util::Platform.jruby? && RUBY_VERSION.to_f >= 2.6 do
342
342
  int = global_cacerts.last
343
343
  int.public_key = wrong_key.public_key if Puppet::Util::Platform.jruby?
344
344
  int.sign(wrong_key, OpenSSL::Digest::SHA256.new)
@@ -634,4 +634,24 @@ describe Puppet::SSL::SSLProvider do
634
634
  "The CSR for host 'CN=signed' does not match the public key")
635
635
  end
636
636
  end
637
+
638
+ context 'printing' do
639
+ let(:client_cert) { cert_fixture('signed.pem') }
640
+ let(:private_key) { key_fixture('signed-key.pem') }
641
+ let(:config) { { cacerts: global_cacerts, crls: global_crls, client_cert: client_cert, private_key: private_key } }
642
+
643
+ it 'prints in debug' do
644
+ Puppet[:log_level] = 'debug'
645
+
646
+ ctx = subject.create_context(**config)
647
+ subject.print(ctx)
648
+ expect(@logs.map(&:message)).to include(
649
+ /Verified CA certificate 'CN=Test CA' fingerprint/,
650
+ /Verified CA certificate 'CN=Test CA Subauthority' fingerprint/,
651
+ /Verified client certificate 'CN=signed' fingerprint/,
652
+ /Using CRL 'CN=Test CA' authorityKeyIdentifier '(keyid:)?[A-Z0-9:]{59}' crlNumber '0'/,
653
+ /Using CRL 'CN=Test CA Subauthority' authorityKeyIdentifier '(keyid:)?[A-Z0-9:]{59}' crlNumber '0'/
654
+ )
655
+ end
656
+ end
637
657
  end
@@ -487,7 +487,7 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
487
487
  expect(state.next_state.ssl_context.cacerts.map(&:to_pem)).to eq(new_ca_bundle)
488
488
  end
489
489
 
490
- it 'updates the `last_update` time' do
490
+ it 'updates the `last_update` time on successful CA refresh' do
491
491
  stub_request(:get, %r{puppet-ca/v1/certificate/ca}).to_return(status: 200, body: new_ca_bundle.join)
492
492
 
493
493
  expect_any_instance_of(Puppet::X509::CertProvider).to receive(:ca_last_update=).with(be_within(60).of(Time.now))
@@ -495,6 +495,14 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
495
495
  state.next_state
496
496
  end
497
497
 
498
+ it "does not update the `last_update` time when CA refresh fails" do
499
+ stub_request(:get, %r{puppet-ca/v1/certificate/ca}).to_raise(Errno::ECONNREFUSED)
500
+
501
+ expect_any_instance_of(Puppet::X509::CertProvider).to receive(:ca_last_update=).never
502
+
503
+ state.next_state
504
+ end
505
+
498
506
  it 'forces the NeedCRLs to refresh' do
499
507
  stub_request(:get, %r{puppet-ca/v1/certificate/ca}).to_return(status: 200, body: new_ca_bundle.join)
500
508
 
@@ -737,6 +745,26 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
737
745
  state.next_state
738
746
  }.to raise_error(OpenSSL::PKey::RSAError)
739
747
  end
748
+
749
+ it "transitions to Done if current time plus renewal interval is less than cert's \"NotAfter\" time" do
750
+ allow(cert_provider).to receive(:load_private_key).and_return(private_key)
751
+ allow(cert_provider).to receive(:load_client_cert).and_return(client_cert)
752
+
753
+ st = state.next_state
754
+ expect(st).to be_instance_of(Puppet::SSL::StateMachine::Done)
755
+ end
756
+
757
+ it "returns NeedRenewedCert if current time plus renewal interval is greater than cert's \"NotAfter\" time" do
758
+ client_cert.not_after=(Time.now + 300)
759
+ allow(cert_provider).to receive(:load_private_key).and_return(private_key)
760
+ allow(cert_provider).to receive(:load_client_cert).and_return(client_cert)
761
+
762
+ ssl_context = Puppet::SSL::SSLContext.new(cacerts: [cacert], client_cert: client_cert, crls: [crl])
763
+ state = Puppet::SSL::StateMachine::NeedKey.new(machine, ssl_context)
764
+
765
+ st = state.next_state
766
+ expect(st).to be_instance_of(Puppet::SSL::StateMachine::NeedRenewedCert)
767
+ end
740
768
  end
741
769
 
742
770
  context 'in state NeedSubmitCSR' do
@@ -778,7 +806,7 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
778
806
  state.next_state
779
807
  end
780
808
 
781
- it 'includes CSR attributes' do
809
+ it 'includes CSR attributes', :unless => RUBY_PLATFORM == 'java' do
782
810
  Puppet[:csr_attributes] = write_csr_attributes(
783
811
  'custom_attributes' => {
784
812
  '1.3.6.1.4.1.34380.1.2.1' => 'CSR specific info',
@@ -792,7 +820,8 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
792
820
  csr.custom_attributes
793
821
  ).to contain_exactly(
794
822
  {'oid' => '1.3.6.1.4.1.34380.1.2.1', 'value' => 'CSR specific info'},
795
- {'oid' => '1.3.6.1.4.1.34380.1.2.2', 'value' => 'more CSR specific info'}
823
+ {'oid' => '1.3.6.1.4.1.34380.1.2.2', 'value' => 'more CSR specific info'},
824
+ {'oid' => 'pp_auth_auto_renew', 'value' => 'true'}
796
825
  )
797
826
  end.to_return(status: 200)
798
827
 
@@ -1041,5 +1070,48 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
1041
1070
  expect(state.next_state).to be_an_instance_of(Puppet::SSL::StateMachine::LockFailure)
1042
1071
  end
1043
1072
  end
1073
+
1074
+ context 'in state NeedRenewedCert' do
1075
+ before :each do
1076
+ client_cert.not_after=(Time.now + 300)
1077
+ end
1078
+
1079
+ let(:ssl_context) { Puppet::SSL::SSLContext.new(cacerts: cacerts, client_cert: client_cert, crls: crls,)}
1080
+ let(:state) { Puppet::SSL::StateMachine::NeedRenewedCert.new(machine, ssl_context, private_key) }
1081
+ let(:renewed_cert) { cert_fixture('renewed.pem') }
1082
+
1083
+ it 'returns Done with renewed cert when successful' do
1084
+ allow(cert_provider).to receive(:save_client_cert)
1085
+ stub_request(:post, %r{puppet-ca/v1/certificate_renewal}).to_return(status: 200, body: renewed_cert.to_pem)
1086
+
1087
+ st = state.next_state
1088
+ expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Done)
1089
+ expect(st.ssl_context[:client_cert]).to eq(renewed_cert)
1090
+ end
1091
+
1092
+ it 'logs a warning message when failing with a non-404 status' do
1093
+ stub_request(:post, %r{puppet-ca/v1/certificate_renewal}).to_return(status: 400, body: 'Failed to automatically renew certificate: 400 Bad request')
1094
+
1095
+ expect(Puppet).to receive(:warning).with(/Failed to automatically renew certificate/)
1096
+ st = state.next_state
1097
+ expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Done)
1098
+ end
1099
+
1100
+ it 'logs an info message when failing with 404' do
1101
+ stub_request(:post, %r{puppet-ca/v1/certificate_renewal}).to_return(status: 404, body: 'Certificate autorenewal has not been enabled on the server.')
1102
+
1103
+ expect(Puppet).to receive(:info).with('Certificate autorenewal has not been enabled on the server.')
1104
+ st = state.next_state
1105
+ expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Done)
1106
+ end
1107
+
1108
+ it 'logs a warning message when failing with no HTTP status' do
1109
+ stub_request(:post, %r{puppet-ca/v1/certificate_renewal}).to_raise(Errno::ECONNREFUSED)
1110
+
1111
+ expect(Puppet).to receive(:warning).with(/Unable to automatically renew certificate:/)
1112
+ st = state.next_state
1113
+ expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Done)
1114
+ end
1115
+ end
1044
1116
  end
1045
1117
  end
@@ -29,6 +29,7 @@ describe Puppet::Util::Execution, if: !Puppet::Util::Platform.jruby? do
29
29
  allow(FFI::WIN32).to receive(:CloseHandle).with(thread_handle)
30
30
  else
31
31
  allow(Process).to receive(:waitpid2).with(pid, Process::WNOHANG).and_return(nil, [pid, double('child_status', :exitstatus => exitstatus)])
32
+ allow(Process).to receive(:waitpid2).with(pid, 0).and_return(nil, [pid, double('child_status', :exitstatus => exitstatus)])
32
33
  allow(Process).to receive(:waitpid2).with(pid).and_return([pid, double('child_status', :exitstatus => exitstatus)])
33
34
  end
34
35
  end
@@ -2,6 +2,48 @@ require 'spec_helper'
2
2
 
3
3
  require 'puppet/util/monkey_patches'
4
4
 
5
+ describe Dir do
6
+ describe '.exists?' do
7
+ it 'returns false if the directory does not exist' do
8
+ expect(Dir.exists?('/madeupdirectory')).to be false
9
+ end
10
+
11
+ it 'returns true if the directory exists' do
12
+ expect(Dir.exists?(__dir__)).to be true
13
+ end
14
+
15
+ if RUBY_VERSION >= '3.2'
16
+ it 'logs a warning message' do
17
+ expect(Dir).to receive(:warn).with("Dir.exists?('#{__dir__}') is deprecated, use Dir.exist? instead")
18
+ with_verbose_enabled do
19
+ Dir.exists?(__dir__)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ describe File do
27
+ describe '.exists?' do
28
+ it 'returns false if the directory does not exist' do
29
+ expect(File.exists?('spec/unit/util/made_up_file')).to be false
30
+ end
31
+
32
+ it 'returns true if the file exists' do
33
+ expect(File.exists?(__FILE__)).to be true
34
+ end
35
+
36
+ if RUBY_VERSION >= '3.2'
37
+ it 'logs a warning message' do
38
+ expect(File).to receive(:warn).with("File.exists?('#{__FILE__}') is deprecated, use File.exist? instead")
39
+ with_verbose_enabled do
40
+ File.exists?(__FILE__)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+
5
47
  describe Symbol do
6
48
  after :all do
7
49
  $unique_warnings.delete('symbol_comparison') if $unique_warnings
@@ -95,6 +95,31 @@ describe Puppet::Util::Windows::ADSI, :if => Puppet::Util::Platform.windows? do
95
95
  end
96
96
  end
97
97
 
98
+ describe '.get_sids' do
99
+ it 'returns an array of SIDs given two an array of ADSI children' do
100
+ child1 = double('child1', name: 'Administrator', sid: 'S-1-5-21-3882680660-671291151-3888264257-500')
101
+ child2 = double('child2', name: 'Guest', sid: 'S-1-5-21-3882680660-671291151-3888264257-501')
102
+ allow(Puppet::Util::Windows::SID).to receive(:ads_to_principal).with(child1).and_return('Administrator')
103
+ allow(Puppet::Util::Windows::SID).to receive(:ads_to_principal).with(child2).and_return('Guest')
104
+ sids = Puppet::Util::Windows::ADSI::ADSIObject.get_sids([child1, child2])
105
+ expect(sids).to eq(['Administrator', 'Guest'])
106
+ end
107
+
108
+ it 'returns an array of SIDs given an ADSI child and ads_to_principal returning domain failure' do
109
+ child = double('child1', name: 'Administrator', sid: 'S-1-5-21-3882680660-671291151-3888264257-500')
110
+ allow(Puppet::Util::Windows::SID).to receive(:ads_to_principal).with(child).and_raise(Puppet::Util::Windows::Error.new('', Puppet::Util::Windows::SID::ERROR_TRUSTED_DOMAIN_FAILURE))
111
+ sids = Puppet::Util::Windows::ADSI::ADSIObject.get_sids([child])
112
+ expect(sids[0]).to eq(Puppet::Util::Windows::SID::Principal.new(child.name, child.sid, child.name, nil, :SidTypeUnknown))
113
+ end
114
+
115
+ it 'returns an array of SIDs given an ADSI child and ads_to_principal returning relationship failure' do
116
+ child = double('child1', name: 'Administrator', sid: 'S-1-5-21-3882680660-671291151-3888264257-500')
117
+ allow(Puppet::Util::Windows::SID).to receive(:ads_to_principal).with(child).and_raise(Puppet::Util::Windows::Error.new('', Puppet::Util::Windows::SID::ERROR_TRUSTED_RELATIONSHIP_FAILURE))
118
+ sids = Puppet::Util::Windows::ADSI::ADSIObject.get_sids([child])
119
+ expect(sids[0]).to eq(Puppet::Util::Windows::SID::Principal.new(child.name, child.sid, child.name, nil, :SidTypeUnknown))
120
+ end
121
+ end
122
+
98
123
  describe Puppet::Util::Windows::ADSI::User do
99
124
  let(:username) { 'testuser' }
100
125
  let(:domain) { 'DOMAIN' }
@@ -586,6 +586,29 @@ describe Puppet::X509::CertProvider do
586
586
  end
587
587
  end
588
588
 
589
+ context 'when creating', :unless => RUBY_PLATFORM == 'java' do
590
+ context 'requests' do
591
+ let(:name) { 'tom' }
592
+ let(:requestdir) { tmpdir('cert_provider') }
593
+ let(:provider) { create_provider(requestdir: requestdir) }
594
+ let(:key) { OpenSSL::PKey::RSA.new(Puppet[:keylength]) }
595
+
596
+ it 'has the auto-renew attribute by default for agents that support automatic renewal' do
597
+ csr = provider.create_request(name, key)
598
+ # need to create CertificateRequest instance from csr in order to view CSR attributes
599
+ wrapped_csr = Puppet::SSL::CertificateRequest.from_instance csr
600
+ expect(wrapped_csr.custom_attributes).to include('oid' => 'pp_auth_auto_renew', 'value' => 'true')
601
+ end
602
+
603
+ it 'does not have the auto-renew attribute for agents that do not support automatic renewal' do
604
+ Puppet[:hostcert_renewal_interval] = 0
605
+ csr = provider.create_request(name, key)
606
+ wrapped_csr = Puppet::SSL::CertificateRequest.from_instance csr
607
+ expect(wrapped_csr.custom_attributes.length).to eq(0)
608
+ end
609
+ end
610
+ end
611
+
589
612
  context 'CA last update time' do
590
613
  let(:ca_path) { tmpfile('pem_ca') }
591
614
 
@@ -94,6 +94,10 @@ task(:gen_cert_fixtures) do
94
94
  save(dir, 'signed.pem', signed[:cert])
95
95
  save(dir, 'signed-key.pem', signed[:private_key])
96
96
 
97
+ # Create a cert for host "renewed" and issued by "Test CA Subauthority"
98
+ renewed = ca.create_cert('renewed', inter[:cert], inter[:private_key], reuse_key: signed[:private_key])
99
+ save(dir, 'renewed.pem', renewed[:cert])
100
+
97
101
  # Create an encrypted version of the above private key for host "signed"
98
102
  save(dir, 'encrypted-key.pem', signed[:private_key]) do |x509|
99
103
  # private key password was chosen at random