puppet 6.5.0 → 6.6.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 +4 -4
- data/lib/puppet/application/agent.rb +16 -5
- data/lib/puppet/application/ssl.rb +2 -0
- data/lib/puppet/provider/package.rb +2 -0
- data/lib/puppet/provider/package/pip.rb +1 -2
- data/lib/puppet/provider/package/puppet_gem.rb +1 -1
- data/lib/puppet/provider/package_targetable.rb +2 -0
- data/lib/puppet/ssl/host.rb +1 -1
- data/lib/puppet/ssl/state_machine.rb +92 -24
- data/lib/puppet/transaction.rb +5 -1
- data/lib/puppet/util/pidlock.rb +3 -2
- data/lib/puppet/util/windows/process.rb +8 -8
- data/lib/puppet/version.rb +1 -1
- data/locales/puppet.pot +68 -60
- data/man/man5/puppet.conf.5 +1 -1
- data/man/man8/puppet.8 +1 -1
- data/spec/unit/application/agent_spec.rb +53 -32
- data/spec/unit/application/ssl_spec.rb +13 -0
- data/spec/unit/configurer_spec.rb +1 -1
- data/spec/unit/provider/package/pip_spec.rb +2 -2
- data/spec/unit/ssl/state_machine_spec.rb +175 -48
- data/spec/unit/util/pidlock_spec.rb +26 -0
- metadata +2 -2
data/man/man5/puppet.conf.5
CHANGED
@@ -889,7 +889,7 @@ The time to wait for data to be read from an HTTP connection\. If nothing is rea
|
|
889
889
|
The HTTP User\-Agent string to send when making network requests\.
|
890
890
|
.
|
891
891
|
.IP "\(bu" 4
|
892
|
-
\fIDefault\fR: Puppet/6\.
|
892
|
+
\fIDefault\fR: Puppet/6\.6\.0 Ruby/2\.4\.1\-p111 (x86_64\-linux)
|
893
893
|
.
|
894
894
|
.IP "" 0
|
895
895
|
.
|
data/man/man8/puppet.8
CHANGED
@@ -25,4 +25,4 @@ Specialized:
|
|
25
25
|
catalog Compile, save, view, and convert catalogs\. describe Display help about resource types device Manage remote network devices doc Generate Puppet references epp Interact directly with the EPP template parser/renderer\. facts Retrieve and store facts\. filebucket Store and retrieve files in a filebucket generate Generates Puppet code from Ruby definitions\. node View and manage node definitions\. parser Interact directly with the parser\. script Run a puppet manifests as a script without compiling a catalog ssl Manage SSL keys and certificates for puppet SSL clients
|
26
26
|
.
|
27
27
|
.P
|
28
|
-
See \'puppet help \fIsubcommand\fR \fIaction\fR\' for help on a specific subcommand action\. See \'puppet help \fIsubcommand\fR\' for help on a specific subcommand\. Puppet v6\.
|
28
|
+
See \'puppet help \fIsubcommand\fR \fIaction\fR\' for help on a specific subcommand action\. See \'puppet help \fIsubcommand\fR\' for help on a specific subcommand\. Puppet v6\.6\.0
|
@@ -7,6 +7,8 @@ require 'puppet/daemon'
|
|
7
7
|
describe Puppet::Application::Agent do
|
8
8
|
include PuppetSpec::Files
|
9
9
|
|
10
|
+
let(:machine) { double(ensure_client_certificate: nil) }
|
11
|
+
|
10
12
|
before :each do
|
11
13
|
@puppetd = Puppet::Application[:agent]
|
12
14
|
|
@@ -27,8 +29,6 @@ describe Puppet::Application::Agent do
|
|
27
29
|
allow(Puppet::Node.indirection).to receive(:cache_class=)
|
28
30
|
allow(Puppet::Node::Facts.indirection).to receive(:terminus_class=)
|
29
31
|
|
30
|
-
expect($stderr).not_to receive(:puts)
|
31
|
-
|
32
32
|
allow(Puppet.settings).to receive(:use)
|
33
33
|
end
|
34
34
|
|
@@ -125,7 +125,7 @@ describe Puppet::Application::Agent do
|
|
125
125
|
allow(@agent).to receive(:run).and_return(2)
|
126
126
|
Puppet[:onetime] = true
|
127
127
|
|
128
|
-
expect(Puppet::SSL::StateMachine).to receive(:new).with(waitforcert: 0).and_return(
|
128
|
+
expect(Puppet::SSL::StateMachine).to receive(:new).with(waitforcert: 0).and_return(machine)
|
129
129
|
|
130
130
|
expect { execute_agent }.to exit_with 0
|
131
131
|
end
|
@@ -135,13 +135,20 @@ describe Puppet::Application::Agent do
|
|
135
135
|
Puppet[:onetime] = true
|
136
136
|
@puppetd.handle_waitforcert(60)
|
137
137
|
|
138
|
-
expect(Puppet::SSL::StateMachine).to receive(:new).with(waitforcert: 60).and_return(
|
138
|
+
expect(Puppet::SSL::StateMachine).to receive(:new).with(waitforcert: 60).and_return(machine)
|
139
139
|
|
140
140
|
expect { execute_agent }.to exit_with 0
|
141
141
|
end
|
142
142
|
|
143
143
|
it "should use a default value for waitforcert when --onetime and --waitforcert are not specified" do
|
144
|
+
expect(Puppet::SSL::StateMachine).to receive(:new).with(waitforcert: 120).and_return(machine)
|
145
|
+
|
146
|
+
execute_agent
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should register ssl OIDs" do
|
144
150
|
expect(Puppet::SSL::StateMachine).to receive(:new).with(waitforcert: 120).and_return(double(ensure_client_certificate: nil))
|
151
|
+
expect(Puppet::SSL::Oids).to receive(:register_puppet_oids)
|
145
152
|
|
146
153
|
execute_agent
|
147
154
|
end
|
@@ -149,7 +156,7 @@ describe Puppet::Application::Agent do
|
|
149
156
|
it "should use the waitforcert setting when checking for a signed certificate" do
|
150
157
|
Puppet[:waitforcert] = 10
|
151
158
|
|
152
|
-
expect(Puppet::SSL::StateMachine).to receive(:new).with(waitforcert: 10).and_return(
|
159
|
+
expect(Puppet::SSL::StateMachine).to receive(:new).with(waitforcert: 10).and_return(machine)
|
153
160
|
|
154
161
|
execute_agent
|
155
162
|
end
|
@@ -386,7 +393,7 @@ describe Puppet::Application::Agent do
|
|
386
393
|
it "should inform the daemon about our agent if :client is set to 'true'" do
|
387
394
|
@puppetd.options[:client] = true
|
388
395
|
|
389
|
-
allow(Puppet::SSL::StateMachine).to receive(:new).and_return(
|
396
|
+
allow(Puppet::SSL::StateMachine).to receive(:new).and_return(machine)
|
390
397
|
|
391
398
|
execute_agent
|
392
399
|
|
@@ -398,7 +405,7 @@ describe Puppet::Application::Agent do
|
|
398
405
|
Puppet[:daemonize] = true
|
399
406
|
allow(Signal).to receive(:trap)
|
400
407
|
|
401
|
-
allow(Puppet::SSL::StateMachine).to receive(:new).and_return(
|
408
|
+
allow(Puppet::SSL::StateMachine).to receive(:new).and_return(machine)
|
402
409
|
|
403
410
|
expect(@daemon).to receive(:daemonize)
|
404
411
|
|
@@ -408,22 +415,7 @@ describe Puppet::Application::Agent do
|
|
408
415
|
it "should wait for a certificate" do
|
409
416
|
@puppetd.options[:waitforcert] = 123
|
410
417
|
|
411
|
-
expect(Puppet::SSL::StateMachine).to receive(:new).with(waitforcert: 123).and_return(
|
412
|
-
|
413
|
-
execute_agent
|
414
|
-
end
|
415
|
-
|
416
|
-
it "should not wait for a certificate in fingerprint mode" do
|
417
|
-
@puppetd.options[:fingerprint] = true
|
418
|
-
@puppetd.options[:waitforcert] = 123
|
419
|
-
@puppetd.options[:digest] = 'MD5'
|
420
|
-
|
421
|
-
certificate = double('certificate')
|
422
|
-
allow(certificate).to receive(:to_der).and_return('ABCDE')
|
423
|
-
ssl_context = double('ssl_context', client_cert: certificate)
|
424
|
-
allow(Puppet::SSL::StateMachine).to receive(:new).with(onetime: true).and_return(double(ensure_client_certificate: ssl_context))
|
425
|
-
|
426
|
-
expect(@puppetd).to receive(:puts).with('(MD5) 2E:CD:DE:39:59:05:1D:91:3F:61:B1:45:79:EA:13:6D')
|
418
|
+
expect(Puppet::SSL::StateMachine).to receive(:new).with(waitforcert: 123).and_return(machine)
|
427
419
|
|
428
420
|
execute_agent
|
429
421
|
end
|
@@ -478,7 +470,7 @@ describe Puppet::Application::Agent do
|
|
478
470
|
|
479
471
|
it "should dispatch to onetime if --onetime is used" do
|
480
472
|
Puppet[:onetime] = true
|
481
|
-
allow(Puppet::SSL::StateMachine).to receive(:new).and_return(
|
473
|
+
allow(Puppet::SSL::StateMachine).to receive(:new).and_return(machine)
|
482
474
|
|
483
475
|
expect(@puppetd).to receive(:onetime)
|
484
476
|
|
@@ -487,7 +479,7 @@ describe Puppet::Application::Agent do
|
|
487
479
|
|
488
480
|
it "should dispatch to main if --onetime and --fingerprint are not used" do
|
489
481
|
Puppet[:onetime] = false
|
490
|
-
allow(Puppet::SSL::StateMachine).to receive(:new).and_return(
|
482
|
+
allow(Puppet::SSL::StateMachine).to receive(:new).and_return(machine)
|
491
483
|
|
492
484
|
expect(@puppetd).to receive(:main)
|
493
485
|
|
@@ -501,7 +493,7 @@ describe Puppet::Application::Agent do
|
|
501
493
|
@puppetd.options[:client] = :client
|
502
494
|
@puppetd.options[:detailed_exitcodes] = false
|
503
495
|
|
504
|
-
allow(Puppet::SSL::StateMachine).to receive(:new).and_return(
|
496
|
+
allow(Puppet::SSL::StateMachine).to receive(:new).and_return(machine)
|
505
497
|
end
|
506
498
|
|
507
499
|
it "should setup traps" do
|
@@ -552,26 +544,55 @@ describe Puppet::Application::Agent do
|
|
552
544
|
|
553
545
|
describe "with --fingerprint" do
|
554
546
|
before :each do
|
555
|
-
@cert = double('cert')
|
556
547
|
@puppetd.options[:fingerprint] = true
|
557
548
|
@puppetd.options[:digest] = :MD5
|
558
549
|
end
|
559
550
|
|
560
551
|
it "should fingerprint the certificate if it exists" do
|
561
|
-
|
562
|
-
|
563
|
-
allow(Puppet::SSL::StateMachine).to receive(:new).with(onetime: true).and_return(double(ensure_client_certificate: ssl_context))
|
552
|
+
cert = cert_fixture('signed.pem')
|
553
|
+
allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_client_cert).and_return(cert)
|
564
554
|
|
565
|
-
expect(@puppetd).to receive(:puts).with('(MD5)
|
555
|
+
expect(@puppetd).to receive(:puts).with('(MD5) E2:BA:9A:EF:20:A8:7D:10:8D:82:9A:61:5D:FD:5B:33')
|
566
556
|
|
567
557
|
@puppetd.fingerprint
|
568
558
|
end
|
559
|
+
|
560
|
+
it "should fingerprint the request if it exists" do
|
561
|
+
request = request_fixture('request.pem')
|
562
|
+
allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_client_cert).and_return(nil)
|
563
|
+
allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_request).and_return(request)
|
564
|
+
|
565
|
+
expect(@puppetd).to receive(:puts).with('(MD5) B8:4C:FB:31:AE:17:86:E3:AD:53:97:CA:F6:3C:4A:CB')
|
566
|
+
|
567
|
+
@puppetd.fingerprint
|
568
|
+
end
|
569
|
+
|
570
|
+
it "should print an error to stderr if neither exist" do
|
571
|
+
allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_client_cert).and_return(nil)
|
572
|
+
allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_request).and_return(nil)
|
573
|
+
|
574
|
+
expect {
|
575
|
+
expect {
|
576
|
+
@puppetd.fingerprint
|
577
|
+
}.to exit_with(1)
|
578
|
+
}.to output(/Fingerprint asked but neither the certificate, nor the certificate request have been issued/).to_stderr
|
579
|
+
end
|
580
|
+
|
581
|
+
it "should log an error if an exception occurs" do
|
582
|
+
allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_client_cert).and_raise(Puppet::Error, "Invalid PEM")
|
583
|
+
|
584
|
+
expect {
|
585
|
+
@puppetd.fingerprint
|
586
|
+
}.to exit_with(1)
|
587
|
+
|
588
|
+
expect(@logs).to include(an_object_having_attributes(message: /Failed to generate fingerprint: Invalid PEM/))
|
589
|
+
end
|
569
590
|
end
|
570
591
|
|
571
592
|
describe "without --onetime and --fingerprint" do
|
572
593
|
before :each do
|
573
594
|
allow(Puppet).to receive(:notice)
|
574
|
-
allow(Puppet::SSL::StateMachine).to receive(:new).and_return(
|
595
|
+
allow(Puppet::SSL::StateMachine).to receive(:new).and_return(machine)
|
575
596
|
end
|
576
597
|
|
577
598
|
it "should start our daemon" do
|
@@ -125,6 +125,11 @@ describe Puppet::Application::Ssl, unless: Puppet::Util::Platform.jruby? do
|
|
125
125
|
expects_command_to_pass(%r{Submitted certificate request for '#{name}' to https://.*})
|
126
126
|
end
|
127
127
|
|
128
|
+
it 'registers OIDs' do
|
129
|
+
expect(Puppet::SSL::Oids).to receive(:register_puppet_oids)
|
130
|
+
expects_command_to_fail(%r{Failed to submit certificate request})
|
131
|
+
end
|
132
|
+
|
128
133
|
it 'submits the CSR and saves it locally' do
|
129
134
|
stub_request(:put, %r{puppet-ca/v1/certificate_request/#{name}}).to_return(status: 200)
|
130
135
|
stub_request(:get, %r{puppet-ca/v1/certificate/#{name}}).to_return(status: 404)
|
@@ -401,6 +406,14 @@ describe Puppet::Application::Ssl, unless: Puppet::Util::Platform.jruby? do
|
|
401
406
|
ssl.command_line.args << 'bootstrap'
|
402
407
|
end
|
403
408
|
|
409
|
+
it 'registers the OIDs' do
|
410
|
+
expect_any_instance_of(Puppet::SSL::StateMachine).to receive(:ensure_client_certificate).and_return(
|
411
|
+
double('ssl_context')
|
412
|
+
)
|
413
|
+
expect(Puppet::SSL::Oids).to receive(:register_puppet_oids)
|
414
|
+
expects_command_to_pass
|
415
|
+
end
|
416
|
+
|
404
417
|
it 'returns an SSLContext with the loaded CA certs, CRLs, private key and client cert' do
|
405
418
|
expect_any_instance_of(Puppet::SSL::StateMachine).to receive(:ensure_client_certificate).and_return(
|
406
419
|
double('ssl_context')
|
@@ -1005,7 +1005,7 @@ describe Puppet::Configurer do
|
|
1005
1005
|
@agent.run :catalog => catalog
|
1006
1006
|
end
|
1007
1007
|
|
1008
|
-
it "should select a server when
|
1008
|
+
it "should select a server when it receives 200 OK response" do
|
1009
1009
|
Puppet.settings[:server_list] = ["myserver:123"]
|
1010
1010
|
response = Net::HTTPOK.new(nil, 200, 'OK')
|
1011
1011
|
allow(Puppet::Network::HttpPool).to receive(:connection).with('myserver', 123, anything).and_return(double('request', get: response))
|
@@ -145,7 +145,7 @@ describe Puppet::Type.type(:package).provider(:pip) do
|
|
145
145
|
context "latest" do
|
146
146
|
context "with pip version < 1.5.4" do
|
147
147
|
before :each do
|
148
|
-
allow(
|
148
|
+
allow(described_class).to receive(:pip_version).with("/fake/bin/pip").and_return('1.0.1')
|
149
149
|
allow(described_class).to receive(:which).with('pip').and_return("/fake/bin/pip")
|
150
150
|
allow(described_class).to receive(:which).with('pip-python').and_return("/fake/bin/pip")
|
151
151
|
allow(described_class).to receive(:which).with('pip.exe').and_return("/fake/bin/pip")
|
@@ -203,12 +203,12 @@ describe Puppet::Type.type(:package).provider(:pip) do
|
|
203
203
|
# For Pip 1.5.4 and above, you can get a version list from CLI - which allows for native pip behavior
|
204
204
|
# with regards to custom repositories, proxies and the like
|
205
205
|
before :each do
|
206
|
+
allow(described_class).to receive(:pip_version).with("/fake/bin/pip").and_return('1.5.4')
|
206
207
|
allow(described_class).to receive(:which).with('pip').and_return("/fake/bin/pip")
|
207
208
|
allow(described_class).to receive(:which).with('pip-python').and_return("/fake/bin/pip")
|
208
209
|
allow(described_class).to receive(:which).with('pip.exe').and_return("/fake/bin/pip")
|
209
210
|
allow(described_class).to receive(:provider_command).and_return('/fake/bin/pip')
|
210
211
|
allow(described_class).to receive(:validate_command).with('/fake/bin/pip')
|
211
|
-
allow(@provider).to receive(:pip_version).with("/fake/bin/pip").and_return('1.5.4')
|
212
212
|
end
|
213
213
|
|
214
214
|
it "should find a version number for real_package" do
|
@@ -7,9 +7,14 @@ require 'puppet/ssl'
|
|
7
7
|
describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
8
8
|
include PuppetSpec::Files
|
9
9
|
|
10
|
-
let(:
|
10
|
+
let(:privatekeydir) { tmpdir('privatekeydir') }
|
11
|
+
let(:certdir) { tmpdir('certdir') }
|
12
|
+
let(:requestdir) { tmpdir('requestdir') }
|
13
|
+
let(:machine) { described_class.new }
|
14
|
+
let(:cert_provider) { Puppet::X509::CertProvider.new(privatekeydir: privatekeydir, certdir: certdir, requestdir: requestdir) }
|
11
15
|
let(:ssl_provider) { Puppet::SSL::SSLProvider.new }
|
12
16
|
let(:machine) { described_class.new(cert_provider: cert_provider, ssl_provider: ssl_provider) }
|
17
|
+
|
13
18
|
let(:cacert_pem) { cacert.to_pem }
|
14
19
|
let(:cacert) { cert_fixture('ca.pem') }
|
15
20
|
let(:cacerts) { [cacert] }
|
@@ -21,6 +26,8 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
21
26
|
let(:private_key) { key_fixture('signed-key.pem') }
|
22
27
|
let(:client_cert) { cert_fixture('signed.pem') }
|
23
28
|
|
29
|
+
let(:refused_message) { %r{Connection refused|No connection could be made because the target machine actively refused it} }
|
30
|
+
|
24
31
|
before(:each) do
|
25
32
|
WebMock.disable_net_connect!
|
26
33
|
|
@@ -28,6 +35,7 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
28
35
|
allow_any_instance_of(Net::HTTP).to receive(:finish)
|
29
36
|
|
30
37
|
Puppet[:ssl_lockfile] = tmpfile('ssllock')
|
38
|
+
allow(Kernel).to receive(:sleep)
|
31
39
|
end
|
32
40
|
|
33
41
|
context 'when ensuring CA certs and CRLs' do
|
@@ -41,6 +49,48 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
41
49
|
expect(ssl_context[:crls]).to eq(crls)
|
42
50
|
expect(ssl_context[:verify_peer]).to eq(true)
|
43
51
|
end
|
52
|
+
|
53
|
+
context 'when exceptions occur' do
|
54
|
+
it 'raises in onetime mode' do
|
55
|
+
stub_request(:get, %r{puppet-ca/v1/certificate/ca})
|
56
|
+
.to_raise(Errno::ECONNREFUSED)
|
57
|
+
|
58
|
+
machine = described_class.new(cert_provider: cert_provider, ssl_provider: ssl_provider, onetime: true)
|
59
|
+
expect {
|
60
|
+
machine.ensure_ca_certificates
|
61
|
+
}.to raise_error(Puppet::Error, refused_message)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'retries CA cert download' do
|
65
|
+
# allow cert to be saved to disk
|
66
|
+
FileUtils.mkdir_p(Puppet[:certdir])
|
67
|
+
allow(cert_provider).to receive(:load_crls).and_return(crls)
|
68
|
+
|
69
|
+
req = stub_request(:get, %r{puppet-ca/v1/certificate/ca})
|
70
|
+
.to_raise(Errno::ECONNREFUSED).then
|
71
|
+
.to_return(status: 200, body: cacert_pem)
|
72
|
+
|
73
|
+
machine.ensure_ca_certificates
|
74
|
+
|
75
|
+
expect(req).to have_been_made.twice
|
76
|
+
expect(@logs).to include(an_object_having_attributes(message: refused_message))
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'retries CRL download' do
|
80
|
+
# allow crl to be saved to disk
|
81
|
+
FileUtils.mkdir_p(Puppet[:ssldir])
|
82
|
+
allow(cert_provider).to receive(:load_cacerts).and_return(cacerts)
|
83
|
+
|
84
|
+
req = stub_request(:get, %r{puppet-ca/v1/certificate_revocation_list/ca})
|
85
|
+
.to_raise(Errno::ECONNREFUSED).then
|
86
|
+
.to_return(status: 200, body: crl_pem)
|
87
|
+
|
88
|
+
machine.ensure_ca_certificates
|
89
|
+
|
90
|
+
expect(req).to have_been_made.twice
|
91
|
+
expect(@logs).to include(an_object_having_attributes(message: refused_message))
|
92
|
+
end
|
93
|
+
end
|
44
94
|
end
|
45
95
|
|
46
96
|
context 'when ensuring a client cert' do
|
@@ -58,6 +108,72 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
58
108
|
expect(ssl_context[:private_key]).to eq(private_key)
|
59
109
|
expect(ssl_context[:client_cert]).to eq(client_cert)
|
60
110
|
end
|
111
|
+
|
112
|
+
context 'when exceptions occur' do
|
113
|
+
before :each do
|
114
|
+
allow(cert_provider).to receive(:load_cacerts).and_return(cacerts)
|
115
|
+
allow(cert_provider).to receive(:load_crls).and_return(crls)
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'retries CSR submission' do
|
119
|
+
allow(cert_provider).to receive(:load_private_key).and_return(private_key)
|
120
|
+
allow($stdout).to receive(:puts).with(/Couldn't fetch certificate from CA server; you might still need to sign this agent's certificate/)
|
121
|
+
|
122
|
+
stub_request(:get, %r{puppet-ca/v1/certificate/#{Puppet[:certname]}})
|
123
|
+
.to_return(status: 200, body: client_cert.to_pem)
|
124
|
+
# first request raises, second succeeds
|
125
|
+
req = stub_request(:put, %r{puppet-ca/v1/certificate_request/#{Puppet[:certname]}})
|
126
|
+
.to_raise(Errno::ECONNREFUSED).then
|
127
|
+
.to_return(status: 200)
|
128
|
+
|
129
|
+
machine.ensure_client_certificate
|
130
|
+
|
131
|
+
expect(req).to have_been_made.twice
|
132
|
+
expect(@logs).to include(an_object_having_attributes(message: refused_message))
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'retries client cert download' do
|
136
|
+
allow(cert_provider).to receive(:load_private_key).and_return(private_key)
|
137
|
+
|
138
|
+
# first request raises, second succeeds
|
139
|
+
req = stub_request(:get, %r{puppet-ca/v1/certificate/#{Puppet[:certname]}})
|
140
|
+
.to_raise(Errno::ECONNREFUSED).then
|
141
|
+
.to_return(status: 200, body: client_cert.to_pem)
|
142
|
+
stub_request(:put, %r{puppet-ca/v1/certificate_request/#{Puppet[:certname]}}).to_return(status: 200)
|
143
|
+
|
144
|
+
machine.ensure_client_certificate
|
145
|
+
|
146
|
+
expect(req).to have_been_made.twice
|
147
|
+
expect(@logs).to include(an_object_having_attributes(message: refused_message))
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'retries when client cert and private key are mismatched' do
|
151
|
+
allow(cert_provider).to receive(:load_private_key).and_return(private_key)
|
152
|
+
|
153
|
+
# return mismatched cert the first time, correct cert second time
|
154
|
+
req = stub_request(:get, %r{puppet-ca/v1/certificate/#{Puppet[:certname]}})
|
155
|
+
.to_return(status: 200, body: cert_fixture('pluto.pem').to_pem)
|
156
|
+
.to_return(status: 200, body: client_cert.to_pem)
|
157
|
+
stub_request(:put, %r{puppet-ca/v1/certificate_request/#{Puppet[:certname]}}).to_return(status: 200)
|
158
|
+
|
159
|
+
machine.ensure_client_certificate
|
160
|
+
|
161
|
+
expect(req).to have_been_made.twice
|
162
|
+
expect(@logs).to include(an_object_having_attributes(message: %r{The certificate for 'CN=pluto' does not match its private key}))
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'raises in onetime mode' do
|
166
|
+
stub_request(:get, %r{puppet-ca/v1/certificate/#{Puppet[:certname]}})
|
167
|
+
.to_raise(Errno::ECONNREFUSED)
|
168
|
+
stub_request(:put, %r{puppet-ca/v1/certificate_request/#{Puppet[:certname]}})
|
169
|
+
.to_return(status: 200)
|
170
|
+
|
171
|
+
machine = described_class.new(cert_provider: cert_provider, ssl_provider: ssl_provider, onetime: true)
|
172
|
+
expect {
|
173
|
+
machine.ensure_client_certificate
|
174
|
+
}.to raise_error(Puppet::Error, refused_message)
|
175
|
+
end
|
176
|
+
end
|
61
177
|
end
|
62
178
|
|
63
179
|
context 'when locking' do
|
@@ -167,29 +283,29 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
167
283
|
state.next_state
|
168
284
|
end
|
169
285
|
|
170
|
-
it '
|
286
|
+
it 'returns an Error if the server returns 404' do
|
171
287
|
stub_request(:get, %r{puppet-ca/v1/certificate/ca}).to_return(status: 404)
|
172
288
|
|
173
|
-
|
174
|
-
|
175
|
-
|
289
|
+
st = state.next_state
|
290
|
+
expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Error)
|
291
|
+
expect(st.message).to eq("CA certificate is missing from the server")
|
176
292
|
end
|
177
293
|
|
178
|
-
it '
|
294
|
+
it 'returns an Error if there is a different exception' do
|
179
295
|
stub_request(:get, %r{puppet-ca/v1/certificate/ca}).to_return(status: [500, 'Internal Server Error'])
|
180
296
|
|
181
|
-
|
182
|
-
|
183
|
-
|
297
|
+
st = state.next_state
|
298
|
+
expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Error)
|
299
|
+
expect(st.message).to eq("Could not download CA certificate: Internal Server Error")
|
184
300
|
end
|
185
301
|
|
186
|
-
it '
|
302
|
+
it 'returns an Error if CA certs are invalid' do
|
187
303
|
allow(cert_provider).to receive(:load_cacerts).and_return(nil)
|
188
304
|
stub_request(:get, %r{puppet-ca/v1/certificate/ca}).to_return(status: 200, body: '')
|
189
305
|
|
190
|
-
|
191
|
-
|
192
|
-
|
306
|
+
st = state.next_state
|
307
|
+
expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Error)
|
308
|
+
expect(st.error).to be_an_instance_of(OpenSSL::X509::CertificateError)
|
193
309
|
end
|
194
310
|
|
195
311
|
it 'does not save invalid CA certs' do
|
@@ -244,29 +360,29 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
244
360
|
state.next_state
|
245
361
|
end
|
246
362
|
|
247
|
-
it '
|
363
|
+
it 'returns an Error if the server returns 404' do
|
248
364
|
stub_request(:get, %r{puppet-ca/v1/certificate_revocation_list/ca}).to_return(status: 404)
|
249
365
|
|
250
|
-
|
251
|
-
|
252
|
-
|
366
|
+
st = state.next_state
|
367
|
+
expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Error)
|
368
|
+
expect(st.message).to eq("CRL is missing from the server")
|
253
369
|
end
|
254
370
|
|
255
|
-
it '
|
371
|
+
it 'returns an Error if there is a different exception' do
|
256
372
|
stub_request(:get, %r{puppet-ca/v1/certificate_revocation_list/ca}).to_return(status: [500, 'Internal Server Error'])
|
257
373
|
|
258
|
-
|
259
|
-
|
260
|
-
|
374
|
+
st = state.next_state
|
375
|
+
expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Error)
|
376
|
+
expect(st.message).to eq("Could not download CRLs: Internal Server Error")
|
261
377
|
end
|
262
378
|
|
263
|
-
it '
|
379
|
+
it 'returns an Error if CRLs are invalid' do
|
264
380
|
allow(cert_provider).to receive(:load_crls).and_return(nil)
|
265
381
|
stub_request(:get, %r{puppet-ca/v1/certificate_revocation_list/ca}).to_return(status: 200, body: '')
|
266
382
|
|
267
|
-
|
268
|
-
|
269
|
-
|
383
|
+
st = state.next_state
|
384
|
+
expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Error)
|
385
|
+
expect(st.error).to be_an_instance_of(OpenSSL::X509::CRLError)
|
270
386
|
end
|
271
387
|
|
272
388
|
it 'does not save invalid CRLs' do
|
@@ -543,9 +659,9 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
543
659
|
it 'raises if the server errors' do
|
544
660
|
stub_request(:put, %r{puppet-ca/v1/certificate_request/#{Puppet[:certname]}}).to_return(status: 500)
|
545
661
|
|
546
|
-
|
547
|
-
|
548
|
-
|
662
|
+
st = state.next_state
|
663
|
+
expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Error)
|
664
|
+
expect(st.message).to eq("Failed to submit the CSR, HTTP response was 500")
|
549
665
|
end
|
550
666
|
|
551
667
|
it "verifies the server's certificate when submitting the CSR" do
|
@@ -572,16 +688,27 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
572
688
|
expect(state.next_state).to be_an_instance_of(Puppet::SSL::StateMachine::Done)
|
573
689
|
end
|
574
690
|
|
575
|
-
it
|
691
|
+
it "prints a message if the cert isn't signed yet" do
|
692
|
+
stub_request(:get, %r{puppet-ca/v1/certificate/#{Puppet[:certname]}}).to_return(status: 404)
|
693
|
+
|
694
|
+
expect {
|
695
|
+
state.next_state
|
696
|
+
}.to output(/Couldn't fetch certificate from CA server; you might still need to sign this agent's certificate \(#{Puppet[:certname]}\)/).to_stdout
|
697
|
+
end
|
698
|
+
|
699
|
+
it 'transitions to Error if the cert does not match our private key' do
|
576
700
|
wrong_cert = cert_fixture('127.0.0.1.pem')
|
577
701
|
stub_request(:get, %r{puppet-ca/v1/certificate/#{Puppet[:certname]}}).to_return(status: 200, body: wrong_cert.to_pem)
|
578
702
|
|
579
|
-
|
703
|
+
st = state.next_state
|
704
|
+
expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Error)
|
705
|
+
expect(st.message).to eq("The certificate for 'CN=127.0.0.1' does not match its private key")
|
580
706
|
end
|
581
707
|
|
582
708
|
it 'transitions to Wait if the server returns non-200' do
|
583
709
|
stub_request(:get, %r{puppet-ca/v1/certificate/#{Puppet[:certname]}}).to_return(status: 404)
|
584
710
|
|
711
|
+
allow($stdout).to receive(:puts).with(/Couldn't fetch certificate from CA server; you might still need to sign this agent's certificate/)
|
585
712
|
expect(state.next_state).to be_an_instance_of(Puppet::SSL::StateMachine::Wait)
|
586
713
|
end
|
587
714
|
|
@@ -601,9 +728,9 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
601
728
|
MIIBpDCCAQ2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRUZXN0
|
602
729
|
END
|
603
730
|
|
604
|
-
state.next_state
|
605
|
-
|
606
|
-
expect(
|
731
|
+
st = state.next_state
|
732
|
+
expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Error)
|
733
|
+
expect(st.message).to match(/Failed to parse certificate:/)
|
607
734
|
expect(File).to_not exist(Puppet[:hostcert])
|
608
735
|
end
|
609
736
|
|
@@ -611,9 +738,9 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
611
738
|
wrong_cert = cert_fixture('127.0.0.1.pem').to_pem
|
612
739
|
stub_request(:get, %r{puppet-ca/v1/certificate/#{Puppet[:certname]}}).to_return(status: 200, body: wrong_cert)
|
613
740
|
|
614
|
-
state.next_state
|
615
|
-
|
616
|
-
expect(
|
741
|
+
st = state.next_state
|
742
|
+
expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Error)
|
743
|
+
expect(st.message).to eq("The certificate for 'CN=127.0.0.1' does not match its private key")
|
617
744
|
expect(File).to_not exist(Puppet[:hostcert])
|
618
745
|
end
|
619
746
|
|
@@ -621,9 +748,9 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
621
748
|
revoked_cert = cert_fixture('revoked.pem').to_pem
|
622
749
|
stub_request(:get, %r{puppet-ca/v1/certificate/#{Puppet[:certname]}}).to_return(status: 200, body: revoked_cert)
|
623
750
|
|
624
|
-
state.next_state
|
625
|
-
|
626
|
-
expect(
|
751
|
+
st = state.next_state
|
752
|
+
expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Error)
|
753
|
+
expect(st.message).to eq("Certificate 'CN=revoked' is revoked")
|
627
754
|
expect(File).to_not exist(Puppet[:hostcert])
|
628
755
|
end
|
629
756
|
end
|
@@ -636,18 +763,18 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
636
763
|
|
637
764
|
expect {
|
638
765
|
expect {
|
639
|
-
Puppet::SSL::StateMachine::Wait.new(machine
|
766
|
+
Puppet::SSL::StateMachine::Wait.new(machine).next_state
|
640
767
|
}.to exit_with(1)
|
641
|
-
}.to output(/
|
768
|
+
}.to output(/Exiting now because the waitforcert setting is set to 0./).to_stdout
|
642
769
|
end
|
643
770
|
|
644
771
|
it 'sleeps and transitions to NeedCACerts' do
|
645
772
|
machine = described_class.new(waitforcert: 15)
|
646
773
|
|
647
|
-
state = Puppet::SSL::StateMachine::Wait.new(machine
|
648
|
-
expect(
|
774
|
+
state = Puppet::SSL::StateMachine::Wait.new(machine)
|
775
|
+
expect(Kernel).to receive(:sleep).with(15)
|
649
776
|
|
650
|
-
expect(Puppet).to receive(:info).with(/
|
777
|
+
expect(Puppet).to receive(:info).with(/Will try again in 15 seconds./)
|
651
778
|
|
652
779
|
expect(state.next_state).to be_an_instance_of(Puppet::SSL::StateMachine::NeedCACerts)
|
653
780
|
end
|
@@ -655,10 +782,10 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
655
782
|
it 'sleeps and transitions to NeedCACerts when maxwaitforcert is set' do
|
656
783
|
machine = described_class.new(waitforcert: 15, maxwaitforcert: 30)
|
657
784
|
|
658
|
-
state = Puppet::SSL::StateMachine::Wait.new(machine
|
659
|
-
expect(
|
785
|
+
state = Puppet::SSL::StateMachine::Wait.new(machine)
|
786
|
+
expect(Kernel).to receive(:sleep).with(15)
|
660
787
|
|
661
|
-
expect(Puppet).to receive(:info).with(/
|
788
|
+
expect(Puppet).to receive(:info).with(/Will try again in 15 seconds./)
|
662
789
|
|
663
790
|
expect(state.next_state).to be_an_instance_of(Puppet::SSL::StateMachine::NeedCACerts)
|
664
791
|
end
|
@@ -677,7 +804,7 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
677
804
|
|
678
805
|
expect {
|
679
806
|
expect {
|
680
|
-
Puppet::SSL::StateMachine::Wait.new(machine
|
807
|
+
Puppet::SSL::StateMachine::Wait.new(machine).next_state
|
681
808
|
}.to exit_with(1)
|
682
809
|
}.to output(/Couldn't fetch certificate from CA server; you might still need to sign this agent's certificate \(.*\). Exiting now because the maxwaitforcert timeout has been exceeded./).to_stdout
|
683
810
|
end
|