puppet 6.4.2-x86-mingw32 → 6.4.3-x86-mingw32
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 +17 -17
- data/ext/solaris/smf/puppet.xml +2 -0
- data/lib/hiera/scope.rb +7 -0
- data/lib/puppet.rb +1 -1
- data/lib/puppet/application/agent.rb +16 -5
- data/lib/puppet/application/device.rb +12 -3
- data/lib/puppet/application/ssl.rb +2 -0
- data/lib/puppet/configurer.rb +1 -1
- data/lib/puppet/network/http/factory.rb +5 -0
- data/lib/puppet/pops/types/types.rb +5 -3
- data/lib/puppet/provider.rb +1 -2
- data/lib/puppet/provider/package.rb +2 -0
- data/lib/puppet/provider/package/dpkg.rb +15 -2
- data/lib/puppet/provider/package/gem.rb +65 -29
- data/lib/puppet/provider/package/pip.rb +135 -111
- data/lib/puppet/provider/package/pip3.rb +1 -1
- data/lib/puppet/provider/package/puppet_gem.rb +1 -1
- data/lib/puppet/provider/package/rpm.rb +27 -16
- data/lib/puppet/provider/package/yum.rb +1 -1
- data/lib/puppet/provider/package_targetable.rb +68 -0
- data/lib/puppet/provider/service/upstart.rb +5 -3
- data/lib/puppet/provider/user/useradd.rb +16 -13
- data/lib/puppet/settings/server_list_setting.rb +9 -0
- data/lib/puppet/ssl/host.rb +1 -1
- data/lib/puppet/ssl/state_machine.rb +99 -28
- data/lib/puppet/type/package.rb +46 -9
- data/lib/puppet/util/pidlock.rb +3 -2
- data/lib/puppet/util/windows/process.rb +8 -8
- data/lib/puppet/util/windows/registry.rb +7 -1
- data/lib/puppet/util/windows/user.rb +14 -4
- data/lib/puppet/version.rb +1 -1
- data/locales/puppet.pot +115 -103
- 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/type/package_spec.rb +1 -1
- data/spec/integration/util/windows/registry_spec.rb +52 -0
- data/spec/integration/util/windows/user_spec.rb +19 -0
- 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/functions/new_spec.rb +15 -0
- data/spec/unit/hiera/scope_spec.rb +7 -0
- data/spec/unit/network/http/factory_spec.rb +6 -0
- data/spec/unit/provider/package/dpkg_spec.rb +18 -1
- data/spec/unit/provider/package/gem_spec.rb +101 -48
- data/spec/unit/provider/package/pip3_spec.rb +17 -0
- data/spec/unit/provider/package/pip_spec.rb +57 -67
- data/spec/unit/provider/package/puppet_gem_spec.rb +22 -6
- data/spec/unit/provider/package/rpm_spec.rb +116 -27
- data/spec/unit/provider/service/upstart_spec.rb +3 -22
- data/spec/unit/settings/server_list_setting_spec.rb +21 -0
- data/spec/unit/ssl/state_machine_spec.rb +206 -83
- data/spec/unit/util/pidlock_spec.rb +26 -0
- metadata +5 -2
@@ -33,35 +33,16 @@ describe 'Puppet::Type::Service::Provider::Upstart', unless: Puppet::Util::Platf
|
|
33
33
|
end
|
34
34
|
|
35
35
|
context "upstart daemon existence confine" do
|
36
|
-
# We have a separate method here because our search for the upstart daemon
|
37
|
-
# confine expects it to be the last confine declared in the upstart provider.
|
38
|
-
# If in the future we add other confines below it or change its order, these
|
39
|
-
# unit tests will fail. Placing knowledge of where this confine is located
|
40
|
-
# in one place makes updating it less painful in case we ever need to do this.
|
41
|
-
def assert_upstart_daemon_existence_confine_is(expected_value)
|
42
|
-
# Reload our provider to evaluate the :confine block
|
43
|
-
provider_class = Puppet::Type.type(:service).provider(:upstart)
|
44
|
-
|
45
|
-
upstart_daemon_existence_confine = provider_class.confine_collection.instance_variable_get(:@confines)[-1]
|
46
|
-
expect(upstart_daemon_existence_confine.valid?).to be(expected_value)
|
47
|
-
end
|
48
|
-
|
49
36
|
let(:initctl_version) { ['/sbin/initctl', 'version', '--quiet'] }
|
50
37
|
|
51
38
|
before(:each) do
|
52
|
-
# Stub out /sbin/initctl
|
53
39
|
allow(Puppet::Util).to receive(:which).with('/sbin/initctl').and_return('/sbin/initctl')
|
54
|
-
|
55
|
-
# Both of our tests are asserting the confine :true block that shells out to
|
56
|
-
# `initctl version --quiet`. Its expression is evaluated at provider load-time.
|
57
|
-
# Hence before each test, we want to reload the upstart provider so that the
|
58
|
-
# confine is re-evaluated.
|
59
|
-
Puppet::Type.type(:service).unprovide(:upstart)
|
60
40
|
end
|
61
41
|
|
62
42
|
it "should return true when the daemon is running" do
|
63
43
|
expect(Puppet::Util::Execution).to receive(:execute).with(initctl_version, instance_of(Hash))
|
64
|
-
|
44
|
+
|
45
|
+
expect(provider_class).to be_has_initctl
|
65
46
|
end
|
66
47
|
|
67
48
|
it "should return false when the daemon is not running" do
|
@@ -69,7 +50,7 @@ describe 'Puppet::Type::Service::Provider::Upstart', unless: Puppet::Util::Platf
|
|
69
50
|
.with(initctl_version, instance_of(Hash))
|
70
51
|
.and_raise(Puppet::ExecutionFailure, "initctl failed!")
|
71
52
|
|
72
|
-
|
53
|
+
expect(provider_class).to_not be_has_initctl
|
73
54
|
end
|
74
55
|
end
|
75
56
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'puppet/settings/server_list_setting'
|
3
|
+
|
4
|
+
describe Puppet::Settings::ServerListSetting do
|
5
|
+
|
6
|
+
it "prints strings as strings" do
|
7
|
+
settings = Puppet::Settings.new
|
8
|
+
settings.define_settings(:main, neptune: {type: :server_list, desc: 'list of servers'})
|
9
|
+
server_list_setting = settings.setting(:neptune)
|
10
|
+
expect(server_list_setting.print("jupiter,mars")).to eq("jupiter,mars")
|
11
|
+
end
|
12
|
+
|
13
|
+
it "prints arrays as strings" do
|
14
|
+
settings = Puppet::Settings.new
|
15
|
+
settings.define_settings(:main, neptune: {type: :server_list, desc: 'list of servers'})
|
16
|
+
server_list_setting = settings.setting(:neptune)
|
17
|
+
expect(server_list_setting.print([["main", 1234],["production", 8140]])).to eq("main:1234,production:8140")
|
18
|
+
expect(server_list_setting.print([])).to eq("")
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -7,14 +7,13 @@ require 'puppet/ssl'
|
|
7
7
|
describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
8
8
|
include PuppetSpec::Files
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
allow_any_instance_of(Net::HTTP).to receive(:start)
|
14
|
-
allow_any_instance_of(Net::HTTP).to receive(:finish)
|
15
|
-
end
|
16
|
-
|
10
|
+
let(:privatekeydir) { tmpdir('privatekeydir') }
|
11
|
+
let(:certdir) { tmpdir('certdir') }
|
12
|
+
let(:requestdir) { tmpdir('requestdir') }
|
17
13
|
let(:machine) { described_class.new }
|
14
|
+
let(:cert_provider) { Puppet::X509::CertProvider.new(privatekeydir: privatekeydir, certdir: certdir, requestdir: requestdir) }
|
15
|
+
let(:ssl_provider) { Puppet::SSL::SSLProvider.new }
|
16
|
+
let(:machine) { described_class.new(cert_provider: cert_provider, ssl_provider: ssl_provider) }
|
18
17
|
let(:cacert_pem) { cacert.to_pem }
|
19
18
|
let(:cacert) { cert_fixture('ca.pem') }
|
20
19
|
let(:cacerts) { [cacert] }
|
@@ -26,17 +25,21 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
26
25
|
let(:private_key) { key_fixture('signed-key.pem') }
|
27
26
|
let(:client_cert) { cert_fixture('signed.pem') }
|
28
27
|
|
28
|
+
let(:refused_message) { %r{Connection refused|No connection could be made because the target machine actively refused it} }
|
29
|
+
|
29
30
|
before(:each) do
|
30
31
|
WebMock.disable_net_connect!
|
31
32
|
|
32
33
|
allow_any_instance_of(Net::HTTP).to receive(:start)
|
33
34
|
allow_any_instance_of(Net::HTTP).to receive(:finish)
|
35
|
+
|
36
|
+
allow(Kernel).to receive(:sleep)
|
34
37
|
end
|
35
38
|
|
36
39
|
context 'when ensuring CA certs and CRLs' do
|
37
40
|
it 'returns an SSLContext with the loaded CA certs and CRLs' do
|
38
|
-
|
39
|
-
|
41
|
+
allow(cert_provider).to receive(:load_cacerts).and_return(cacerts)
|
42
|
+
allow(cert_provider).to receive(:load_crls).and_return(crls)
|
40
43
|
|
41
44
|
ssl_context = machine.ensure_ca_certificates
|
42
45
|
|
@@ -44,14 +47,56 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
44
47
|
expect(ssl_context[:crls]).to eq(crls)
|
45
48
|
expect(ssl_context[:verify_peer]).to eq(true)
|
46
49
|
end
|
50
|
+
|
51
|
+
context 'when exceptions occur' do
|
52
|
+
it 'raises in onetime mode' do
|
53
|
+
stub_request(:get, %r{puppet-ca/v1/certificate/ca})
|
54
|
+
.to_raise(Errno::ECONNREFUSED)
|
55
|
+
|
56
|
+
machine = described_class.new(cert_provider: cert_provider, ssl_provider: ssl_provider, onetime: true)
|
57
|
+
expect {
|
58
|
+
machine.ensure_ca_certificates
|
59
|
+
}.to raise_error(Puppet::Error, refused_message)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'retries CA cert download' do
|
63
|
+
# allow cert to be saved to disk
|
64
|
+
FileUtils.mkdir_p(Puppet[:certdir])
|
65
|
+
allow(cert_provider).to receive(:load_crls).and_return(crls)
|
66
|
+
|
67
|
+
req = stub_request(:get, %r{puppet-ca/v1/certificate/ca})
|
68
|
+
.to_raise(Errno::ECONNREFUSED).then
|
69
|
+
.to_return(status: 200, body: cacert_pem)
|
70
|
+
|
71
|
+
machine.ensure_ca_certificates
|
72
|
+
|
73
|
+
expect(req).to have_been_made.twice
|
74
|
+
expect(@logs).to include(an_object_having_attributes(message: refused_message))
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'retries CRL download' do
|
78
|
+
# allow crl to be saved to disk
|
79
|
+
FileUtils.mkdir_p(Puppet[:ssldir])
|
80
|
+
allow(cert_provider).to receive(:load_cacerts).and_return(cacerts)
|
81
|
+
|
82
|
+
req = stub_request(:get, %r{puppet-ca/v1/certificate_revocation_list/ca})
|
83
|
+
.to_raise(Errno::ECONNREFUSED).then
|
84
|
+
.to_return(status: 200, body: crl_pem)
|
85
|
+
|
86
|
+
machine.ensure_ca_certificates
|
87
|
+
|
88
|
+
expect(req).to have_been_made.twice
|
89
|
+
expect(@logs).to include(an_object_having_attributes(message: refused_message))
|
90
|
+
end
|
91
|
+
end
|
47
92
|
end
|
48
93
|
|
49
94
|
context 'when ensuring a client cert' do
|
50
95
|
it 'returns an SSLContext with the loaded CA certs, CRLs, private key and client cert' do
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
96
|
+
allow(cert_provider).to receive(:load_cacerts).and_return(cacerts)
|
97
|
+
allow(cert_provider).to receive(:load_crls).and_return(crls)
|
98
|
+
allow(cert_provider).to receive(:load_private_key).and_return(private_key)
|
99
|
+
allow(cert_provider).to receive(:load_client_cert).and_return(client_cert)
|
55
100
|
|
56
101
|
ssl_context = machine.ensure_client_certificate
|
57
102
|
|
@@ -61,6 +106,72 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
61
106
|
expect(ssl_context[:private_key]).to eq(private_key)
|
62
107
|
expect(ssl_context[:client_cert]).to eq(client_cert)
|
63
108
|
end
|
109
|
+
|
110
|
+
context 'when exceptions occur' do
|
111
|
+
before :each do
|
112
|
+
allow(cert_provider).to receive(:load_cacerts).and_return(cacerts)
|
113
|
+
allow(cert_provider).to receive(:load_crls).and_return(crls)
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'retries CSR submission' do
|
117
|
+
allow(cert_provider).to receive(:load_private_key).and_return(private_key)
|
118
|
+
allow($stdout).to receive(:puts).with(/Couldn't fetch certificate from CA server; you might still need to sign this agent's certificate/)
|
119
|
+
|
120
|
+
stub_request(:get, %r{puppet-ca/v1/certificate/#{Puppet[:certname]}})
|
121
|
+
.to_return(status: 200, body: client_cert.to_pem)
|
122
|
+
# first request raises, second succeeds
|
123
|
+
req = stub_request(:put, %r{puppet-ca/v1/certificate_request/#{Puppet[:certname]}})
|
124
|
+
.to_raise(Errno::ECONNREFUSED).then
|
125
|
+
.to_return(status: 200)
|
126
|
+
|
127
|
+
machine.ensure_client_certificate
|
128
|
+
|
129
|
+
expect(req).to have_been_made.twice
|
130
|
+
expect(@logs).to include(an_object_having_attributes(message: refused_message))
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'retries client cert download' do
|
134
|
+
allow(cert_provider).to receive(:load_private_key).and_return(private_key)
|
135
|
+
|
136
|
+
# first request raises, second succeeds
|
137
|
+
req = stub_request(:get, %r{puppet-ca/v1/certificate/#{Puppet[:certname]}})
|
138
|
+
.to_raise(Errno::ECONNREFUSED).then
|
139
|
+
.to_return(status: 200, body: client_cert.to_pem)
|
140
|
+
stub_request(:put, %r{puppet-ca/v1/certificate_request/#{Puppet[:certname]}}).to_return(status: 200)
|
141
|
+
|
142
|
+
machine.ensure_client_certificate
|
143
|
+
|
144
|
+
expect(req).to have_been_made.twice
|
145
|
+
expect(@logs).to include(an_object_having_attributes(message: refused_message))
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'retries when client cert and private key are mismatched' do
|
149
|
+
allow(cert_provider).to receive(:load_private_key).and_return(private_key)
|
150
|
+
|
151
|
+
# return mismatched cert the first time, correct cert second time
|
152
|
+
req = stub_request(:get, %r{puppet-ca/v1/certificate/#{Puppet[:certname]}})
|
153
|
+
.to_return(status: 200, body: cert_fixture('pluto.pem').to_pem)
|
154
|
+
.to_return(status: 200, body: client_cert.to_pem)
|
155
|
+
stub_request(:put, %r{puppet-ca/v1/certificate_request/#{Puppet[:certname]}}).to_return(status: 200)
|
156
|
+
|
157
|
+
machine.ensure_client_certificate
|
158
|
+
|
159
|
+
expect(req).to have_been_made.twice
|
160
|
+
expect(@logs).to include(an_object_having_attributes(message: %r{The certificate for 'CN=pluto' does not match its private key}))
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'raises in onetime mode' do
|
164
|
+
stub_request(:get, %r{puppet-ca/v1/certificate/#{Puppet[:certname]}})
|
165
|
+
.to_raise(Errno::ECONNREFUSED)
|
166
|
+
stub_request(:put, %r{puppet-ca/v1/certificate_request/#{Puppet[:certname]}})
|
167
|
+
.to_return(status: 200)
|
168
|
+
|
169
|
+
machine = described_class.new(cert_provider: cert_provider, ssl_provider: ssl_provider, onetime: true)
|
170
|
+
expect {
|
171
|
+
machine.ensure_client_certificate
|
172
|
+
}.to raise_error(Puppet::Error, refused_message)
|
173
|
+
end
|
174
|
+
end
|
64
175
|
end
|
65
176
|
|
66
177
|
context 'NeedCACerts' do
|
@@ -71,20 +182,20 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
71
182
|
end
|
72
183
|
|
73
184
|
it 'transitions to NeedCRLs state' do
|
74
|
-
|
185
|
+
allow(cert_provider).to receive(:load_cacerts).and_return(cacerts)
|
75
186
|
|
76
187
|
expect(state.next_state).to be_an_instance_of(Puppet::SSL::StateMachine::NeedCRLs)
|
77
188
|
end
|
78
189
|
|
79
190
|
it 'loads existing CA certs' do
|
80
|
-
|
191
|
+
allow(cert_provider).to receive(:load_cacerts).and_return(cacerts)
|
81
192
|
|
82
193
|
st = state.next_state
|
83
194
|
expect(st.ssl_context[:cacerts]).to eq(cacerts)
|
84
195
|
end
|
85
196
|
|
86
197
|
it 'fetches and saves CA certs' do
|
87
|
-
|
198
|
+
allow(cert_provider).to receive(:load_cacerts).and_return(nil)
|
88
199
|
stub_request(:get, %r{puppet-ca/v1/certificate/ca}).to_return(status: 200, body: cacert_pem)
|
89
200
|
|
90
201
|
st = state.next_state
|
@@ -93,38 +204,38 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
93
204
|
end
|
94
205
|
|
95
206
|
it "does not verify the server's cert if there are no local CA certs" do
|
96
|
-
|
207
|
+
allow(cert_provider).to receive(:load_cacerts).and_return(nil)
|
97
208
|
stub_request(:get, %r{puppet-ca/v1/certificate/ca}).to_return(status: 200, body: cacert_pem)
|
98
|
-
|
209
|
+
allow(cert_provider).to receive(:save_cacerts)
|
99
210
|
|
100
211
|
expect_any_instance_of(Net::HTTP).to receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
|
101
212
|
|
102
213
|
state.next_state
|
103
214
|
end
|
104
215
|
|
105
|
-
it '
|
216
|
+
it 'returns an Error if the server returns 404' do
|
106
217
|
stub_request(:get, %r{puppet-ca/v1/certificate/ca}).to_return(status: 404)
|
107
218
|
|
108
|
-
|
109
|
-
|
110
|
-
|
219
|
+
st = state.next_state
|
220
|
+
expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Error)
|
221
|
+
expect(st.message).to eq("CA certificate is missing from the server")
|
111
222
|
end
|
112
223
|
|
113
|
-
it '
|
224
|
+
it 'returns an Error if there is a different exception' do
|
114
225
|
stub_request(:get, %r{puppet-ca/v1/certificate/ca}).to_return(status: [500, 'Internal Server Error'])
|
115
226
|
|
116
|
-
|
117
|
-
|
118
|
-
|
227
|
+
st = state.next_state
|
228
|
+
expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Error)
|
229
|
+
expect(st.message).to eq("Could not download CA certificate: Internal Server Error")
|
119
230
|
end
|
120
231
|
|
121
|
-
it '
|
122
|
-
|
232
|
+
it 'returns an Error if CA certs are invalid' do
|
233
|
+
allow(cert_provider).to receive(:load_cacerts).and_return(nil)
|
123
234
|
stub_request(:get, %r{puppet-ca/v1/certificate/ca}).to_return(status: 200, body: '')
|
124
235
|
|
125
|
-
|
126
|
-
|
127
|
-
|
236
|
+
st = state.next_state
|
237
|
+
expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Error)
|
238
|
+
expect(st.error).to be_an_instance_of(OpenSSL::X509::CertificateError)
|
128
239
|
end
|
129
240
|
|
130
241
|
it 'does not save invalid CA certs' do
|
@@ -148,20 +259,20 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
148
259
|
end
|
149
260
|
|
150
261
|
it 'transitions to NeedKey state' do
|
151
|
-
|
262
|
+
allow(cert_provider).to receive(:load_crls).and_return(crls)
|
152
263
|
|
153
264
|
expect(state.next_state).to be_an_instance_of(Puppet::SSL::StateMachine::NeedKey)
|
154
265
|
end
|
155
266
|
|
156
267
|
it 'loads existing CRLs' do
|
157
|
-
|
268
|
+
allow(cert_provider).to receive(:load_crls).and_return(crls)
|
158
269
|
|
159
270
|
st = state.next_state
|
160
271
|
expect(st.ssl_context[:crls]).to eq(crls)
|
161
272
|
end
|
162
273
|
|
163
274
|
it 'fetches and saves CRLs' do
|
164
|
-
|
275
|
+
allow(cert_provider).to receive(:load_crls).and_return(nil)
|
165
276
|
stub_request(:get, %r{puppet-ca/v1/certificate_revocation_list/ca}).to_return(status: 200, body: crl_pem)
|
166
277
|
|
167
278
|
st = state.next_state
|
@@ -170,38 +281,38 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
170
281
|
end
|
171
282
|
|
172
283
|
it "verifies the server's certificate when fetching the CRL" do
|
173
|
-
|
284
|
+
allow(cert_provider).to receive(:load_crls).and_return(nil)
|
174
285
|
stub_request(:get, %r{puppet-ca/v1/certificate_revocation_list/ca}).to_return(status: 200, body: crl_pem)
|
175
|
-
|
286
|
+
allow(cert_provider).to receive(:save_crls)
|
176
287
|
|
177
288
|
expect_any_instance_of(Net::HTTP).to receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_PEER)
|
178
289
|
|
179
290
|
state.next_state
|
180
291
|
end
|
181
292
|
|
182
|
-
it '
|
293
|
+
it 'returns an Error if the server returns 404' do
|
183
294
|
stub_request(:get, %r{puppet-ca/v1/certificate_revocation_list/ca}).to_return(status: 404)
|
184
295
|
|
185
|
-
|
186
|
-
|
187
|
-
|
296
|
+
st = state.next_state
|
297
|
+
expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Error)
|
298
|
+
expect(st.message).to eq("CRL is missing from the server")
|
188
299
|
end
|
189
300
|
|
190
|
-
it '
|
301
|
+
it 'returns an Error if there is a different exception' do
|
191
302
|
stub_request(:get, %r{puppet-ca/v1/certificate_revocation_list/ca}).to_return(status: [500, 'Internal Server Error'])
|
192
303
|
|
193
|
-
|
194
|
-
|
195
|
-
|
304
|
+
st = state.next_state
|
305
|
+
expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Error)
|
306
|
+
expect(st.message).to eq("Could not download CRLs: Internal Server Error")
|
196
307
|
end
|
197
308
|
|
198
|
-
it '
|
199
|
-
|
309
|
+
it 'returns an Error if CRLs are invalid' do
|
310
|
+
allow(cert_provider).to receive(:load_crls).and_return(nil)
|
200
311
|
stub_request(:get, %r{puppet-ca/v1/certificate_revocation_list/ca}).to_return(status: 200, body: '')
|
201
312
|
|
202
|
-
|
203
|
-
|
204
|
-
|
313
|
+
st = state.next_state
|
314
|
+
expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Error)
|
315
|
+
expect(st.error).to be_an_instance_of(OpenSSL::X509::CRLError)
|
205
316
|
end
|
206
317
|
|
207
318
|
it 'does not save invalid CRLs' do
|
@@ -218,7 +329,7 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
218
329
|
it 'skips CRL download when revocation is disabled' do
|
219
330
|
Puppet[:certificate_revocation] = false
|
220
331
|
|
221
|
-
|
332
|
+
expect(cert_provider).not_to receive(:load_crls)
|
222
333
|
expect(Puppet::Rest::Routes).not_to receive(:get_crls)
|
223
334
|
|
224
335
|
state.next_state
|
@@ -233,7 +344,7 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
233
344
|
let(:state) { Puppet::SSL::StateMachine::NeedKey.new(machine, ssl_context) }
|
234
345
|
|
235
346
|
it 'loads an existing private key and passes it to the next state' do
|
236
|
-
|
347
|
+
allow(cert_provider).to receive(:load_private_key).and_return(private_key)
|
237
348
|
|
238
349
|
st = state.next_state
|
239
350
|
expect(st).to be_instance_of(Puppet::SSL::StateMachine::NeedSubmitCSR)
|
@@ -241,16 +352,16 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
241
352
|
end
|
242
353
|
|
243
354
|
it 'loads a matching private key and cert' do
|
244
|
-
|
245
|
-
|
355
|
+
allow(cert_provider).to receive(:load_private_key).and_return(private_key)
|
356
|
+
allow(cert_provider).to receive(:load_client_cert).and_return(client_cert)
|
246
357
|
|
247
358
|
st = state.next_state
|
248
359
|
expect(st).to be_instance_of(Puppet::SSL::StateMachine::Done)
|
249
360
|
end
|
250
361
|
|
251
362
|
it 'raises if the client cert is mismatched' do
|
252
|
-
|
253
|
-
|
363
|
+
allow(cert_provider).to receive(:load_private_key).and_return(private_key)
|
364
|
+
allow(cert_provider).to receive(:load_client_cert).and_return(cert_fixture('tampered-cert.pem'))
|
254
365
|
|
255
366
|
expect {
|
256
367
|
state.next_state
|
@@ -258,16 +369,17 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
258
369
|
end
|
259
370
|
|
260
371
|
it 'generates a new private key, saves it and passes it to the next state' do
|
261
|
-
|
262
|
-
|
372
|
+
allow(cert_provider).to receive(:load_private_key).and_return(nil)
|
373
|
+
expect(cert_provider).to receive(:save_private_key)
|
263
374
|
|
264
375
|
st = state.next_state
|
265
376
|
expect(st).to be_instance_of(Puppet::SSL::StateMachine::NeedSubmitCSR)
|
266
377
|
expect(st.private_key).to be_instance_of(OpenSSL::PKey::RSA)
|
378
|
+
expect(st.private_key).to be_private
|
267
379
|
end
|
268
380
|
|
269
381
|
it 'raises an error if it fails to load the key' do
|
270
|
-
|
382
|
+
allow(cert_provider).to receive(:load_private_key).and_raise(OpenSSL::PKey::RSAError)
|
271
383
|
|
272
384
|
expect {
|
273
385
|
state.next_state
|
@@ -286,7 +398,7 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
286
398
|
end
|
287
399
|
|
288
400
|
before :each do
|
289
|
-
|
401
|
+
allow(cert_provider).to receive(:save_request)
|
290
402
|
end
|
291
403
|
|
292
404
|
it 'submits the CSR and transitions to NeedCert' do
|
@@ -298,7 +410,7 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
298
410
|
it 'saves the CSR and transitions to NeedCert' do
|
299
411
|
stub_request(:put, %r{puppet-ca/v1/certificate_request/#{Puppet[:certname]}}).to_return(status: 200)
|
300
412
|
|
301
|
-
|
413
|
+
expect(cert_provider).to receive(:save_request).with(Puppet[:certname], instance_of(OpenSSL::X509::Request))
|
302
414
|
|
303
415
|
state.next_state
|
304
416
|
end
|
@@ -381,9 +493,9 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
381
493
|
it 'raises if the server errors' do
|
382
494
|
stub_request(:put, %r{puppet-ca/v1/certificate_request/#{Puppet[:certname]}}).to_return(status: 500)
|
383
495
|
|
384
|
-
|
385
|
-
|
386
|
-
|
496
|
+
st = state.next_state
|
497
|
+
expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Error)
|
498
|
+
expect(st.message).to eq("Failed to submit the CSR, HTTP response was 500")
|
387
499
|
end
|
388
500
|
|
389
501
|
it "verifies the server's certificate when submitting the CSR" do
|
@@ -402,31 +514,42 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
402
514
|
let(:state) { Puppet::SSL::StateMachine::NeedCert.new(machine, ssl_context, private_key) }
|
403
515
|
|
404
516
|
it 'transitions to Done if the cert is signed and matches our private key' do
|
405
|
-
|
406
|
-
|
517
|
+
allow(cert_provider).to receive(:save_client_cert)
|
518
|
+
allow(cert_provider).to receive(:save_request)
|
407
519
|
|
408
520
|
stub_request(:get, %r{puppet-ca/v1/certificate/#{Puppet[:certname]}}).to_return(status: 200, body: client_cert.to_pem)
|
409
521
|
|
410
522
|
expect(state.next_state).to be_an_instance_of(Puppet::SSL::StateMachine::Done)
|
411
523
|
end
|
412
524
|
|
413
|
-
it
|
525
|
+
it "prints a message if the cert isn't signed yet" do
|
526
|
+
stub_request(:get, %r{puppet-ca/v1/certificate/#{Puppet[:certname]}}).to_return(status: 404)
|
527
|
+
|
528
|
+
expect {
|
529
|
+
state.next_state
|
530
|
+
}.to output(/Couldn't fetch certificate from CA server; you might still need to sign this agent's certificate \(#{Puppet[:certname]}\)/).to_stdout
|
531
|
+
end
|
532
|
+
|
533
|
+
it 'transitions to Error if the cert does not match our private key' do
|
414
534
|
wrong_cert = cert_fixture('127.0.0.1.pem')
|
415
535
|
stub_request(:get, %r{puppet-ca/v1/certificate/#{Puppet[:certname]}}).to_return(status: 200, body: wrong_cert.to_pem)
|
416
536
|
|
417
|
-
|
537
|
+
st = state.next_state
|
538
|
+
expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Error)
|
539
|
+
expect(st.message).to eq("The certificate for 'CN=127.0.0.1' does not match its private key")
|
418
540
|
end
|
419
541
|
|
420
542
|
it 'transitions to Wait if the server returns non-200' do
|
421
543
|
stub_request(:get, %r{puppet-ca/v1/certificate/#{Puppet[:certname]}}).to_return(status: 404)
|
422
544
|
|
545
|
+
allow($stdout).to receive(:puts).with(/Couldn't fetch certificate from CA server; you might still need to sign this agent's certificate/)
|
423
546
|
expect(state.next_state).to be_an_instance_of(Puppet::SSL::StateMachine::Wait)
|
424
547
|
end
|
425
548
|
|
426
549
|
it "verifies the server's certificate when getting the client cert" do
|
427
550
|
stub_request(:get, %r{puppet-ca/v1/certificate/#{Puppet[:certname]}}).to_return(status: 200, body: client_cert.to_pem)
|
428
|
-
|
429
|
-
|
551
|
+
allow(cert_provider).to receive(:save_client_cert)
|
552
|
+
allow(cert_provider).to receive(:save_request)
|
430
553
|
|
431
554
|
expect_any_instance_of(Net::HTTP).to receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_PEER)
|
432
555
|
|
@@ -439,9 +562,9 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
439
562
|
MIIBpDCCAQ2gAwIBAgIBAjANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBRUZXN0
|
440
563
|
END
|
441
564
|
|
442
|
-
state.next_state
|
443
|
-
|
444
|
-
expect(
|
565
|
+
st = state.next_state
|
566
|
+
expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Error)
|
567
|
+
expect(st.message).to match(/Failed to parse certificate:/)
|
445
568
|
expect(File).to_not exist(Puppet[:hostcert])
|
446
569
|
end
|
447
570
|
|
@@ -449,9 +572,9 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
449
572
|
wrong_cert = cert_fixture('127.0.0.1.pem').to_pem
|
450
573
|
stub_request(:get, %r{puppet-ca/v1/certificate/#{Puppet[:certname]}}).to_return(status: 200, body: wrong_cert)
|
451
574
|
|
452
|
-
state.next_state
|
453
|
-
|
454
|
-
expect(
|
575
|
+
st = state.next_state
|
576
|
+
expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Error)
|
577
|
+
expect(st.message).to eq("The certificate for 'CN=127.0.0.1' does not match its private key")
|
455
578
|
expect(File).to_not exist(Puppet[:hostcert])
|
456
579
|
end
|
457
580
|
|
@@ -459,9 +582,9 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
459
582
|
revoked_cert = cert_fixture('revoked.pem').to_pem
|
460
583
|
stub_request(:get, %r{puppet-ca/v1/certificate/#{Puppet[:certname]}}).to_return(status: 200, body: revoked_cert)
|
461
584
|
|
462
|
-
state.next_state
|
463
|
-
|
464
|
-
expect(
|
585
|
+
st = state.next_state
|
586
|
+
expect(st).to be_an_instance_of(Puppet::SSL::StateMachine::Error)
|
587
|
+
expect(st.message).to eq("Certificate 'CN=revoked' is revoked")
|
465
588
|
expect(File).to_not exist(Puppet[:hostcert])
|
466
589
|
end
|
467
590
|
end
|
@@ -474,18 +597,18 @@ describe Puppet::SSL::StateMachine, unless: Puppet::Util::Platform.jruby? do
|
|
474
597
|
|
475
598
|
expect {
|
476
599
|
expect {
|
477
|
-
Puppet::SSL::StateMachine::Wait.new(machine
|
600
|
+
Puppet::SSL::StateMachine::Wait.new(machine).next_state
|
478
601
|
}.to exit_with(1)
|
479
|
-
}.to output(/
|
602
|
+
}.to output(/Exiting now because the waitforcert setting is set to 0./).to_stdout
|
480
603
|
end
|
481
604
|
|
482
605
|
it 'sleeps and transitions to NeedCACerts' do
|
483
606
|
machine = described_class.new(waitforcert: 15)
|
484
607
|
|
485
|
-
state = Puppet::SSL::StateMachine::Wait.new(machine
|
486
|
-
expect(
|
608
|
+
state = Puppet::SSL::StateMachine::Wait.new(machine)
|
609
|
+
expect(Kernel).to receive(:sleep).with(15)
|
487
610
|
|
488
|
-
expect(Puppet).to receive(:info).with(/
|
611
|
+
expect(Puppet).to receive(:info).with(/Will try again in 15 seconds./)
|
489
612
|
|
490
613
|
expect(state.next_state).to be_an_instance_of(Puppet::SSL::StateMachine::NeedCACerts)
|
491
614
|
end
|