puppet 6.4.2 → 6.4.3

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.

Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +17 -17
  3. data/ext/solaris/smf/puppet.xml +2 -0
  4. data/lib/hiera/scope.rb +7 -0
  5. data/lib/puppet.rb +1 -1
  6. data/lib/puppet/application/agent.rb +16 -5
  7. data/lib/puppet/application/device.rb +12 -3
  8. data/lib/puppet/application/ssl.rb +2 -0
  9. data/lib/puppet/configurer.rb +1 -1
  10. data/lib/puppet/network/http/factory.rb +5 -0
  11. data/lib/puppet/pops/types/types.rb +5 -3
  12. data/lib/puppet/provider.rb +1 -2
  13. data/lib/puppet/provider/package.rb +2 -0
  14. data/lib/puppet/provider/package/dpkg.rb +15 -2
  15. data/lib/puppet/provider/package/gem.rb +65 -29
  16. data/lib/puppet/provider/package/pip.rb +135 -111
  17. data/lib/puppet/provider/package/pip3.rb +1 -1
  18. data/lib/puppet/provider/package/puppet_gem.rb +1 -1
  19. data/lib/puppet/provider/package/rpm.rb +27 -16
  20. data/lib/puppet/provider/package/yum.rb +1 -1
  21. data/lib/puppet/provider/package_targetable.rb +68 -0
  22. data/lib/puppet/provider/service/upstart.rb +5 -3
  23. data/lib/puppet/provider/user/useradd.rb +16 -13
  24. data/lib/puppet/settings/server_list_setting.rb +9 -0
  25. data/lib/puppet/ssl/host.rb +1 -1
  26. data/lib/puppet/ssl/state_machine.rb +99 -28
  27. data/lib/puppet/type/package.rb +46 -9
  28. data/lib/puppet/util/pidlock.rb +3 -2
  29. data/lib/puppet/util/windows/process.rb +8 -8
  30. data/lib/puppet/util/windows/registry.rb +7 -1
  31. data/lib/puppet/util/windows/user.rb +14 -4
  32. data/lib/puppet/version.rb +1 -1
  33. data/locales/puppet.pot +115 -103
  34. data/man/man5/puppet.conf.5 +2 -2
  35. data/man/man8/puppet-agent.8 +1 -1
  36. data/man/man8/puppet-apply.8 +1 -1
  37. data/man/man8/puppet-catalog.8 +1 -1
  38. data/man/man8/puppet-config.8 +1 -1
  39. data/man/man8/puppet-describe.8 +1 -1
  40. data/man/man8/puppet-device.8 +1 -1
  41. data/man/man8/puppet-doc.8 +1 -1
  42. data/man/man8/puppet-epp.8 +1 -1
  43. data/man/man8/puppet-facts.8 +1 -1
  44. data/man/man8/puppet-filebucket.8 +1 -1
  45. data/man/man8/puppet-generate.8 +1 -1
  46. data/man/man8/puppet-help.8 +1 -1
  47. data/man/man8/puppet-key.8 +1 -1
  48. data/man/man8/puppet-lookup.8 +1 -1
  49. data/man/man8/puppet-man.8 +1 -1
  50. data/man/man8/puppet-module.8 +1 -1
  51. data/man/man8/puppet-node.8 +1 -1
  52. data/man/man8/puppet-parser.8 +1 -1
  53. data/man/man8/puppet-plugin.8 +1 -1
  54. data/man/man8/puppet-report.8 +1 -1
  55. data/man/man8/puppet-resource.8 +1 -1
  56. data/man/man8/puppet-script.8 +1 -1
  57. data/man/man8/puppet-ssl.8 +1 -1
  58. data/man/man8/puppet-status.8 +1 -1
  59. data/man/man8/puppet.8 +2 -2
  60. data/spec/integration/type/package_spec.rb +1 -1
  61. data/spec/integration/util/windows/registry_spec.rb +52 -0
  62. data/spec/integration/util/windows/user_spec.rb +19 -0
  63. data/spec/unit/application/agent_spec.rb +53 -32
  64. data/spec/unit/application/ssl_spec.rb +13 -0
  65. data/spec/unit/configurer_spec.rb +1 -1
  66. data/spec/unit/functions/new_spec.rb +15 -0
  67. data/spec/unit/hiera/scope_spec.rb +7 -0
  68. data/spec/unit/network/http/factory_spec.rb +6 -0
  69. data/spec/unit/provider/package/dpkg_spec.rb +18 -1
  70. data/spec/unit/provider/package/gem_spec.rb +101 -48
  71. data/spec/unit/provider/package/pip3_spec.rb +17 -0
  72. data/spec/unit/provider/package/pip_spec.rb +57 -67
  73. data/spec/unit/provider/package/puppet_gem_spec.rb +22 -6
  74. data/spec/unit/provider/package/rpm_spec.rb +116 -27
  75. data/spec/unit/provider/service/upstart_spec.rb +3 -22
  76. data/spec/unit/settings/server_list_setting_spec.rb +21 -0
  77. data/spec/unit/ssl/state_machine_spec.rb +206 -83
  78. data/spec/unit/util/pidlock_spec.rb +26 -0
  79. 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
- assert_upstart_daemon_existence_confine_is(true)
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
- assert_upstart_daemon_existence_confine_is(false)
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
- before(:each) do
11
- WebMock.disable_net_connect!
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
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_cacerts).and_return(cacerts)
39
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_crls).and_return(crls)
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
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_cacerts).and_return(cacerts)
52
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_crls).and_return(crls)
53
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_private_key).and_return(private_key)
54
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_client_cert).and_return(client_cert)
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
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_cacerts).and_return(cacerts)
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
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_cacerts).and_return(cacerts)
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
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_cacerts).and_return(nil)
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
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_cacerts).and_return(nil)
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
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:save_cacerts)
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 'raises if the server returns 404' do
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
- expect {
109
- state.next_state
110
- }.to raise_error(Puppet::Error, /CA certificate is missing from the server/)
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 'raises if there is a different error' do
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
- expect {
117
- state.next_state
118
- }.to raise_error(Puppet::Error, /Could not download CA certificate: Internal Server Error/)
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 'raises if CA certs are invalid' do
122
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_cacerts).and_return(nil)
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
- expect {
126
- state.next_state
127
- }.to raise_error(OpenSSL::X509::CertificateError)
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
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_crls).and_return(crls)
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
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_crls).and_return(crls)
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
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_crls).and_return(nil)
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
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_crls).and_return(nil)
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
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:save_crls)
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 'raises if the server returns 404' do
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
- expect {
186
- state.next_state
187
- }.to raise_error(Puppet::Error, /CRL is missing from the server/)
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 'raises if there is a different error' do
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
- expect {
194
- state.next_state
195
- }.to raise_error(Puppet::Error, /Could not download CRLs: Internal Server Error/)
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 'raises if CRLs are invalid' do
199
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_crls).and_return(nil)
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
- expect {
203
- state.next_state
204
- }.to raise_error(OpenSSL::X509::CRLError)
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
- expect_any_instance_of(Puppet::X509::CertProvider).not_to receive(:load_crls)
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
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_private_key).and_return(private_key)
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
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_private_key).and_return(private_key)
245
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_client_cert).and_return(client_cert)
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
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_private_key).and_return(private_key)
253
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_client_cert).and_return(cert_fixture('tampered-cert.pem'))
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
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_private_key).and_return(nil)
262
- expect_any_instance_of(Puppet::X509::CertProvider).to receive(:save_private_key)
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
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:load_private_key).and_raise(OpenSSL::PKey::RSAError)
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
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:save_request)
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
- expect_any_instance_of(Puppet::X509::CertProvider).to receive(:save_request).with(Puppet[:certname], instance_of(OpenSSL::X509::Request))
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
- expect {
385
- state.next_state
386
- }.to raise_error(Puppet::SSL::SSLError, /Failed to submit the CSR, HTTP response was 500/)
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
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:save_client_cert)
406
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:save_request)
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 'transitions to Wait if the cert does not match our private key' do
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
- expect(state.next_state).to be_an_instance_of(Puppet::SSL::StateMachine::Wait)
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
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:save_client_cert)
429
- allow_any_instance_of(Puppet::X509::CertProvider).to receive(:save_request)
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(@logs).to include(an_object_having_attributes(message: /Failed to parse certificate: /))
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(@logs).to include(an_object_having_attributes(message: %r{The certificate for 'CN=127.0.0.1' does not match its private key}))
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(@logs).to include(an_object_having_attributes(message: %r{Certificate 'CN=revoked' is revoked}))
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, ssl_context).next_state
600
+ Puppet::SSL::StateMachine::Wait.new(machine).next_state
478
601
  }.to exit_with(1)
479
- }.to output(/Couldn't fetch certificate from CA server; you might still need to sign this agent's certificate \(.*\). Exiting now because the waitforcert setting is set to 0./).to_stdout
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, ssl_context)
486
- expect(state).to receive(:sleep).with(15)
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(/Couldn't fetch certificate from CA server; you might still need to sign this agent's certificate \(.*\). Will try again in 15 seconds./)
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