bolt 0.21.1 → 0.21.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bolt might be problematic. Click here for more details.

Files changed (105) hide show
  1. checksums.yaml +5 -5
  2. data/lib/bolt/applicator.rb +56 -0
  3. data/lib/bolt/error.rb +6 -0
  4. data/lib/bolt/pal.rb +8 -1
  5. data/lib/bolt/transport/winrm.rb +4 -1
  6. data/lib/bolt/version.rb +1 -1
  7. data/libexec/apply_catalog.rb +61 -0
  8. data/{exe → libexec}/bolt_catalog +0 -0
  9. data/vendored/puppet/lib/puppet/application.rb +8 -1
  10. data/vendored/puppet/lib/puppet/application/device.rb +24 -28
  11. data/vendored/puppet/lib/puppet/application/doc.rb +4 -2
  12. data/vendored/puppet/lib/puppet/configurer/plugin_handler.rb +1 -2
  13. data/vendored/puppet/lib/puppet/datatypes.rb +1 -1
  14. data/vendored/puppet/lib/puppet/defaults.rb +2 -6
  15. data/vendored/puppet/lib/puppet/environments.rb +4 -10
  16. data/vendored/puppet/lib/puppet/error.rb +1 -1
  17. data/vendored/puppet/lib/puppet/etc.rb +4 -5
  18. data/vendored/puppet/lib/puppet/face/config.rb +1 -1
  19. data/vendored/puppet/lib/puppet/face/module/build.rb +5 -55
  20. data/vendored/puppet/lib/puppet/face/module/generate.rb +5 -247
  21. data/vendored/puppet/lib/puppet/gettext/config.rb +28 -5
  22. data/vendored/puppet/lib/puppet/indirector/catalog/compiler.rb +5 -7
  23. data/vendored/puppet/lib/puppet/indirector/rest.rb +7 -56
  24. data/vendored/puppet/lib/puppet/indirector/terminus.rb +1 -1
  25. data/vendored/puppet/lib/puppet/interface.rb +1 -1
  26. data/vendored/puppet/lib/puppet/interface/face_collection.rb +3 -1
  27. data/vendored/puppet/lib/puppet/metatype/manager.rb +2 -2
  28. data/vendored/puppet/lib/puppet/module_tool/applications.rb +0 -1
  29. data/vendored/puppet/lib/puppet/module_tool/applications/application.rb +1 -1
  30. data/vendored/puppet/lib/puppet/network/http/connection.rb +2 -23
  31. data/vendored/puppet/lib/puppet/network/http/factory.rb +2 -6
  32. data/vendored/puppet/lib/puppet/node.rb +1 -2
  33. data/vendored/puppet/lib/puppet/node/environment.rb +5 -1
  34. data/vendored/puppet/lib/puppet/parser/functions.rb +35 -3
  35. data/vendored/puppet/lib/puppet/pops/evaluator/evaluator_impl.rb +12 -0
  36. data/vendored/puppet/lib/puppet/pops/loader/static_loader.rb +0 -5
  37. data/vendored/puppet/lib/puppet/pops/model/ast.rb +107 -0
  38. data/vendored/puppet/lib/puppet/pops/model/factory.rb +11 -0
  39. data/vendored/puppet/lib/puppet/pops/model/model_label_provider.rb +2 -0
  40. data/vendored/puppet/lib/puppet/pops/parser/eparser.rb +1519 -1485
  41. data/vendored/puppet/lib/puppet/pops/parser/lexer2.rb +1 -1
  42. data/vendored/puppet/lib/puppet/pops/puppet_stack.rb +1 -1
  43. data/vendored/puppet/lib/puppet/pops/serialization/to_data_converter.rb +1 -1
  44. data/vendored/puppet/lib/puppet/pops/types/p_binary_type.rb +1 -2
  45. data/vendored/puppet/lib/puppet/pops/types/types.rb +1 -24
  46. data/vendored/puppet/lib/puppet/pops/validation/checker4_0.rb +5 -0
  47. data/vendored/puppet/lib/puppet/pops/validation/tasks_checker.rb +31 -4
  48. data/vendored/puppet/lib/puppet/provider.rb +12 -1
  49. data/vendored/puppet/lib/puppet/provider/package/dnf.rb +2 -1
  50. data/vendored/puppet/lib/puppet/provider/selmodule/semodule.rb +1 -1
  51. data/vendored/puppet/lib/puppet/provider/service/base.rb +1 -1
  52. data/vendored/puppet/lib/puppet/provider/service/systemd.rb +3 -1
  53. data/vendored/puppet/lib/puppet/provider/service/upstart.rb +2 -0
  54. data/vendored/puppet/lib/puppet/reference/configuration.rb +6 -0
  55. data/vendored/puppet/lib/puppet/reports.rb +2 -2
  56. data/vendored/puppet/lib/puppet/resource/status.rb +2 -0
  57. data/vendored/puppet/lib/puppet/resource/type_collection.rb +1 -1
  58. data/vendored/puppet/lib/puppet/rest/client.rb +28 -24
  59. data/vendored/puppet/lib/puppet/rest/response.rb +5 -0
  60. data/vendored/puppet/lib/puppet/rest/route.rb +13 -31
  61. data/vendored/puppet/lib/puppet/rest/routes.rb +65 -5
  62. data/vendored/puppet/lib/puppet/rest/ssl_context.rb +13 -0
  63. data/vendored/puppet/lib/puppet/settings.rb +6 -0
  64. data/vendored/puppet/lib/puppet/settings/config_file.rb +1 -2
  65. data/vendored/puppet/lib/puppet/ssl/certificate_request.rb +5 -1
  66. data/vendored/puppet/lib/puppet/ssl/host.rb +148 -43
  67. data/vendored/puppet/lib/puppet/ssl/oids.rb +1 -1
  68. data/vendored/puppet/lib/puppet/test/test_helper.rb +3 -0
  69. data/vendored/puppet/lib/puppet/transaction/event_manager.rb +3 -1
  70. data/vendored/puppet/lib/puppet/transaction/report.rb +1 -1
  71. data/vendored/puppet/lib/puppet/type.rb +2 -2
  72. data/vendored/puppet/lib/puppet/type/file/content.rb +2 -3
  73. data/vendored/puppet/lib/puppet/type/schedule.rb +33 -84
  74. data/vendored/puppet/lib/puppet/type/user.rb +1 -1
  75. data/vendored/puppet/lib/puppet/util.rb +5 -0
  76. data/vendored/puppet/lib/puppet/util/autoload.rb +39 -31
  77. data/vendored/puppet/lib/puppet/util/character_encoding.rb +0 -22
  78. data/vendored/puppet/lib/puppet/util/command_line.rb +0 -1
  79. data/vendored/puppet/lib/puppet/util/connection.rb +74 -0
  80. data/vendored/puppet/lib/puppet/util/feature.rb +2 -2
  81. data/vendored/puppet/lib/puppet/util/instance_loader.rb +1 -19
  82. data/vendored/puppet/lib/puppet/util/json.rb +0 -8
  83. data/vendored/puppet/lib/puppet/util/log/destinations.rb +1 -1
  84. data/vendored/puppet/lib/puppet/util/network_device/base.rb +1 -1
  85. data/vendored/puppet/lib/puppet/util/platform.rb +3 -0
  86. data/vendored/puppet/lib/puppet/util/rdoc/parser/puppet_parser_core.rb +1 -1
  87. data/vendored/puppet/lib/puppet/util/reference.rb +2 -2
  88. data/vendored/puppet/lib/puppet/util/rubygems.rb +1 -13
  89. data/vendored/puppet/lib/puppet/util/ssl.rb +40 -1
  90. data/vendored/puppet/lib/puppet/util/windows.rb +1 -0
  91. data/vendored/puppet/lib/puppet/util/windows/file.rb +18 -0
  92. data/vendored/puppet/lib/puppet/util/windows/security.rb +26 -14
  93. metadata +8 -73
  94. data/vendored/puppet/lib/puppet/module_tool/applications/builder.rb +0 -152
  95. data/vendored/puppet/lib/puppet/module_tool/skeleton/templates/generator/spec/spec_helper.rb +0 -1
  96. data/vendored/puppet/lib/puppet/provider/mailalias/aliases.rb +0 -50
  97. data/vendored/puppet/lib/puppet/provider/maillist/mailman.rb +0 -108
  98. data/vendored/puppet/lib/puppet/provider/zfs/zfs.rb +0 -108
  99. data/vendored/puppet/lib/puppet/provider/zone/solaris.rb +0 -364
  100. data/vendored/puppet/lib/puppet/provider/zpool/zpool.rb +0 -125
  101. data/vendored/puppet/lib/puppet/type/mailalias.rb +0 -46
  102. data/vendored/puppet/lib/puppet/type/maillist.rb +0 -62
  103. data/vendored/puppet/lib/puppet/type/zfs.rb +0 -154
  104. data/vendored/puppet/lib/puppet/type/zone.rb +0 -382
  105. data/vendored/puppet/lib/puppet/type/zpool.rb +0 -91
@@ -2,12 +2,13 @@ require 'puppet/rest/route'
2
2
 
3
3
  module Puppet::Rest
4
4
  module Routes
5
+
5
6
  ACCEPT_ENCODING = 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3'
6
7
 
7
8
  def self.ca
8
9
  @ca ||= Route.new(api: '/puppet-ca/v1/',
9
- default_server: Puppet[:ca_server],
10
- default_port: Puppet[:ca_port],
10
+ server_setting: :ca_server,
11
+ port_setting: :ca_port,
11
12
  srv_service: :ca)
12
13
  end
13
14
 
@@ -18,12 +19,71 @@ module Puppet::Rest
18
19
  # @raise [Puppet::Rest::ResponseError] if the response status is not OK
19
20
  # @return [String] the PEM-encoded certificate or certificate bundle
20
21
  def self.get_certificate(client, name)
21
- ca.with_base_url(client.dns_resolver) do |base_url|
22
- header = { 'Accept' => 'text/plain', 'accept-encoding' => ACCEPT_ENCODING }
22
+ ca.with_base_url(client.dns_resolver) do |url|
23
+ header = { 'Accept' => 'text/plain', 'Accept-Encoding' => ACCEPT_ENCODING }
24
+ body = ''
25
+ url.path += "certificate/#{name}"
26
+ client.get(url, header: header) do |chunk|
27
+ body << chunk
28
+ end
29
+ Puppet.info _("Downloaded certificate for %{name} from %{server}") % { name: name, server: ca.server }
30
+ body
31
+ end
32
+ end
33
+
34
+ # Make an HTTP request to fetch the named crl, using the given
35
+ # HTTP client. Accepts a block to stream responses to disk.
36
+ # @param [Puppet::Rest::Client] client the HTTP client to use to make the request
37
+ # @param [String] name the crl to fetch
38
+ # @raise [Puppet::Rest::ResponseError] if the response status is not OK
39
+ # @return nil
40
+ def self.get_crls(client, name, &block)
41
+ ca.with_base_url(client.dns_resolver) do |url|
42
+ header = { 'Accept' => 'text/plain', 'Accept-Encoding' => ACCEPT_ENCODING }
43
+ url.path += "certificate_revocation_list/#{name}"
44
+ client.get(url, header: header) do |chunk|
45
+ block.call(chunk)
46
+ end
47
+ Puppet.debug _("Downloaded certificate revocation list for %{name} from %{server}") % { name: name, server: ca.server }
48
+ end
49
+ end
50
+
51
+ # Make an HTTP request to send the named CSR, using the given
52
+ # HTTP client.
53
+ # @param [Puppet::Rest::Client] client the HTTP client to use to make the request
54
+ # @param [String] csr_pem the contents of the CSR to sent to the CA
55
+ # @param [String] name the name of the host whose CSR is being submitted
56
+ # @rasies [Puppet::Rest::ResponseError] if the response status is not OK
57
+ def self.put_certificate_request(client, csr_pem, name)
58
+ ca.with_base_url(client.dns_resolver) do |url|
59
+ header = { 'Accept' => 'text/plain',
60
+ 'Accept-Encoding' => ACCEPT_ENCODING,
61
+ 'Content-Type' => 'text/plain' }
62
+ url.path += "certificate_request/#{name}"
63
+ response = client.put(url, body: csr_pem, header: header)
64
+ if response.ok?
65
+ Puppet.debug "Submitted certificate request to server."
66
+ else
67
+ raise response.to_exception
68
+ end
69
+ end
70
+ end
71
+
72
+ # Make an HTTP request to get the named CSR, using the given
73
+ # HTTP client.
74
+ # @param [Puppet::Rest::Client] client the HTTP client to use to make the request
75
+ # @param [String] name the name of the host whose CSR is being queried
76
+ # @rasies [Puppet::Rest::ResponseError] if the response status is not OK
77
+ # @return [String] the PEM encoded certificate request
78
+ def self.get_certificate_request(client, name)
79
+ ca.with_base_url(client.dns_resolver) do |url|
80
+ header = { 'Accept' => 'text/plain', 'Accept-Encoding' => ACCEPT_ENCODING }
23
81
  body = ''
24
- client.get(base_url + "certificate/#{name}", header: header) do |chunk|
82
+ url.path += "certificate_request/#{name}"
83
+ client.get(url, header: header) do |chunk|
25
84
  body << chunk
26
85
  end
86
+ Puppet.debug _("Downloaded existing certificate request for %{name} from %{server}") % { name: name, server: ca.server }
27
87
  body
28
88
  end
29
89
  end
@@ -0,0 +1,13 @@
1
+ module Puppet::Rest
2
+ class SSLContext
3
+
4
+ attr_reader :verify_mode, :cert_store
5
+
6
+ # @param [OpenSSL::SSL::VERIFY_NONE, OpenSSL::SSL::VERIFY_PEER] verify_mode
7
+ # @param [OpenSSL::X509::SSLStore] cert_store
8
+ def initialize(verify_mode, cert_store = OpenSSL::X509::Store.new)
9
+ @verify_mode = verify_mode
10
+ @cert_store = cert_store
11
+ end
12
+ end
13
+ end
@@ -452,6 +452,12 @@ class Puppet::Settings
452
452
  # Prints the contents of a config file with the available config settings, or it
453
453
  # prints a single value of a config setting.
454
454
  def print_config_options
455
+ if Puppet::Util::Log.sendlevel?(:info)
456
+ Puppet::Util::Log.newdestination(:console)
457
+ message = (_("Using --configprint is deprecated. Use 'puppet config <subcommand>' instead."))
458
+ Puppet.deprecation_warning(message)
459
+ end
460
+
455
461
  env = value(:environment)
456
462
  val = value(:configprint)
457
463
  if val == "all"
@@ -25,8 +25,7 @@ class Puppet::Settings::ConfigFile
25
25
  allowed_section_names << 'main' unless allowed_section_names.include?('main')
26
26
  end
27
27
 
28
- # in Ruby 1.9.3 strings are not UTF-8 by default, so ensure text is treated properly
29
- ini = Puppet::Settings::IniFile.parse(StringIO.new(text).set_encoding(Encoding::UTF_8))
28
+ ini = Puppet::Settings::IniFile.parse(text.encode(Encoding::UTF_8))
30
29
  unique_sections_in(ini, file, allowed_section_names).each do |section_name|
31
30
  section = Section.new(section_name.to_sym)
32
31
  result.with_section(section)
@@ -103,7 +103,11 @@ DOC
103
103
  raise Puppet::Error, _("CSR sign verification failed; you need to clean the certificate request for %{name} on the server") % { name: name } unless csr.verify(key.public_key)
104
104
 
105
105
  @content = csr
106
- Puppet.info _("Certificate Request fingerprint (%{digest}): %{hex_digest}") % { digest: digest.name, hex_digest: digest.to_hex }
106
+
107
+ # we won't be able to get the digest on jruby
108
+ if @content.signature_algorithm
109
+ Puppet.info _("Certificate Request fingerprint (%{digest}): %{hex_digest}") % { digest: digest.name, hex_digest: digest.to_hex }
110
+ end
107
111
  @content
108
112
  end
109
113
 
@@ -7,6 +7,14 @@ require 'puppet/ssl/certificate_revocation_list'
7
7
  require 'puppet/ssl/certificate_request_attributes'
8
8
  require 'puppet/rest/errors'
9
9
  require 'puppet/rest/routes'
10
+ require 'puppet/rest/ssl_context'
11
+ begin
12
+ # This may fail when being loaded from Puppet Server. However loading the
13
+ # client monkey patches the SSL Store and we need to have those monkey
14
+ # patches in as soon as possible on the agent.
15
+ require 'puppet/rest/client'
16
+ rescue LoadError
17
+ end
10
18
 
11
19
  # The class that manages all aspects of our SSL certificates --
12
20
  # private keys, public keys, requests, etc.
@@ -158,10 +166,6 @@ DOC
158
166
  true
159
167
  end
160
168
 
161
- def certificate_request
162
- @certificate_request ||= CertificateRequest.indirection.find(name)
163
- end
164
-
165
169
  # Our certificate request requires the key but that's all.
166
170
  def generate_certificate_request(options = {})
167
171
  generate_key unless key
@@ -185,7 +189,7 @@ DOC
185
189
  @certificate_request = CertificateRequest.new(name)
186
190
  @certificate_request.generate(key.content, options)
187
191
  begin
188
- CertificateRequest.indirection.save(@certificate_request)
192
+ submit_certificate_request(@certificate_request)
189
193
  rescue
190
194
  @certificate_request = nil
191
195
  raise
@@ -194,11 +198,8 @@ DOC
194
198
  true
195
199
  end
196
200
 
197
- def http_client
198
- # This can't be required top-level because Puppetserver uses the Host class too,
199
- # and we don't ship the gem in that context.
200
- require 'puppet/rest/client'
201
- @http_client ||= Puppet::Rest::Client.new
201
+ def http_client(ssl_context)
202
+ Puppet::Rest::Client.new(ssl_context: ssl_context)
202
203
  end
203
204
 
204
205
  def certificate
@@ -237,10 +238,26 @@ ERROR_STRING
237
238
  end
238
239
  end
239
240
 
241
+ # Search for an existing CSR for this host either cached on
242
+ # disk or stored by the CA. Returns nil if no request exists.
243
+ # @return [Puppet::SSL::CertificateRequest, nil]
244
+ def certificate_request
245
+ unless @certificate_request
246
+ if csr = load_certificate_request_from_file
247
+ @certificate_request = csr
248
+ elsif Puppet::SSL::Host.ca_location == :remote
249
+ if csr = download_csr_from_ca
250
+ @certificate_request = csr
251
+ end
252
+ end
253
+ end
254
+ @certificate_request
255
+ end
256
+
240
257
  # Generate all necessary parts of our ssl host.
241
258
  def generate
242
259
  generate_key unless key
243
- # ask indirector to find any existing requests and download them
260
+
244
261
  existing_request = certificate_request
245
262
 
246
263
  # if CSR downloaded from master, but the local keypair was just generated and
@@ -298,7 +315,6 @@ ERROR_STRING
298
315
  # connections.
299
316
  def ssl_store(purpose = OpenSSL::X509::PURPOSE_ANY)
300
317
  if @ssl_store.nil?
301
- ensure_crl_if_needed
302
318
  @ssl_store = build_ssl_store(purpose)
303
319
  end
304
320
  @ssl_store
@@ -395,43 +411,88 @@ ERROR_STRING
395
411
 
396
412
  private
397
413
 
398
- # Ensures that CRL is either on disk, or that CRL checking has been disabled
399
- def ensure_crl_if_needed
400
- if use_crl? && !Puppet::FileSystem.exist?(crl_path)
401
- # The CertificateRevocationList indirector will attempt to download the
402
- # CRL from the CA if it does not exist on disk. It will ask host for
403
- # its ssl_store again, but expect crl checking to be disabled for that
404
- # store. This is not thread safe, and should be replaced as soon as we
405
- # no longer need to use the indirector to download the CRL (PUP-8654).
406
- old_crl_usage = @crl_usage
407
- @crl_usage = false
408
- Puppet.debug _("Disabling certificate revocation checking when fetching the CRL and no CRL is present")
409
- if !CertificateRevocationList.indirection.find(CA_NAME)
410
- raise Puppet::Error,
411
- _("Certificate revocation checking is enabled but a CRL cannot be found; CRL checking will not be performed.")
414
+ # Load a previously generated CSR either from memory or from disk
415
+ # @return [Puppet::SSL::CertificateRequest, nil]
416
+ def load_certificate_request_from_file
417
+ if Puppet::SSL::CertificateRequest.indirection.terminus_class == :memory
418
+ return Puppet::SSL::CertificateRequest.indirection.find(cert_name)
419
+ end
420
+
421
+ request_path = certificate_request_location(name)
422
+ if Puppet::FileSystem.exist?(request_path)
423
+ Puppet::SSL::CertificateRequest.from_s(Puppet::FileSystem.read(request_path))
424
+ end
425
+ end
426
+
427
+ # Download the CSR for this host from the CA. Returns nil if the CA
428
+ # has no saved CSR for this host.
429
+ # @raises [Puppet::Error] if the response from the server is not a valid
430
+ # CSR or an error occurs while fetching.
431
+ # @return [Puppet::SSL::CertificateRequest, nil]
432
+ def download_csr_from_ca
433
+ begin
434
+ body = Puppet::Rest::Routes.get_certificate_request(
435
+ http_client(Puppet::Rest::SSLContext.new(OpenSSL::SSL::VERIFY_PEER, ssl_store)),
436
+ name)
437
+ begin
438
+ Puppet::SSL::CertificateRequest.from_s(body)
439
+ rescue OpenSSL::X509::RequestError => e
440
+ raise Puppet::Error, _("Response from the CA did not contain a valid certificate request: %{message}") % { message: e.message }
441
+ end
442
+ rescue Puppet::Rest::ResponseError => e
443
+ if e.response.status_code == 404
444
+ nil
445
+ else
446
+ raise Puppet::Error, _('Could not download certificate request: %{message}') % { message: e.message }
412
447
  end
413
- @crl_usage = old_crl_usage
414
448
  end
415
449
  end
450
+ # Submit the CSR to the CA, either via an HTTP PUT request, or when testing,
451
+ # via the indirector (needed for both memory and CA terminii). This also
452
+ # caches a copy of the CSR on disk.
453
+ # @param [Puppet::SSL::CertificateRequest] csr the request to submit
454
+ def submit_certificate_request(csr)
455
+ if Puppet::SSL::CertificateRequest.indirection.terminus_class == :memory ||
456
+ Puppet::SSL::CertificateRequest.indirection.terminus_class == :ca
457
+ Puppet::SSL::CertificateRequest.indirection.save(csr)
458
+ return
459
+ end
416
460
 
417
- # @param path [String] Path to CRL Chain
461
+ if Puppet::SSL::Host.ca_location == :remote
462
+ Puppet::Rest::Routes.put_certificate_request(
463
+ http_client(Puppet::Rest::SSLContext.new(OpenSSL::SSL::VERIFY_PEER, ssl_store)),
464
+ csr.render, name)
465
+ end
466
+
467
+ Puppet::Util.replace_file(certificate_request_location(name), 0644) do |file|
468
+ file.write(csr.render)
469
+ end
470
+ end
471
+
472
+ # @param crl_string [String] CRLs read from disk or obtained from server
418
473
  # @return [Array<OpenSSL::X509::CRL>] CRLs from chain
419
- # @raise [Errno::ENOENT] if file does not exist
420
474
  # @raise [Puppet::Error<OpenSSL::X509::CRLError>] if the CRL chain is malformed
421
- def load_crls(path)
475
+ def process_crl_string(crl_string)
422
476
  delimiters = /-----BEGIN X509 CRL-----.*?-----END X509 CRL-----/m
423
- crls_pems = Puppet::FileSystem.read(path, encoding: Encoding::UTF_8)
424
- crls_pems.scan(delimiters).map do |crl|
477
+ crl_string.scan(delimiters).map do |crl|
425
478
  begin
426
479
  OpenSSL::X509::CRL.new(crl)
427
480
  rescue OpenSSL::X509::CRLError => e
428
481
  raise Puppet::Error.new(
429
- _("Failed attempting to load CRL from %{crl_path}! The CRL below caused the error '%{error}':\n%{crl}" % {crl_path: crl_path, error: e.message, crl: crl}),
482
+ _("Failed attempting to load CRL from %{crl_path}! The CRL below caused the error '%{error}':\n%{crl}" % {crl_path: crl_path, error: e.message, crl: crl}),
430
483
  e)
431
484
  end
432
485
  end
433
486
  end
434
487
 
488
+ # @param path [String] Path to CRL Chain
489
+ # @return [Array<OpenSSL::X509::CRL>] CRLs from chain
490
+ # @raise [Puppet::Error<OpenSSL::X509::CRLError>] if the CRL chain is malformed
491
+ def load_crls(path)
492
+ crls_pems = Puppet::FileSystem.read(path, encoding: Encoding::UTF_8)
493
+ process_crl_string(crls_pems)
494
+ end
495
+
435
496
  # Ensures that the CA certificate is available for either generating or
436
497
  # validating the host's cert.
437
498
  # It will first check if the cert is present in memory (used for testing),
@@ -454,7 +515,7 @@ ERROR_STRING
454
515
  else
455
516
  bundle = download_ca_certificate_bundle
456
517
  if bundle
457
- save_certificate_bundle(bundle)
518
+ save_bundle(bundle, certificate_location(CA_NAME))
458
519
  true
459
520
  else
460
521
  false
@@ -484,6 +545,30 @@ ERROR_STRING
484
545
  end
485
546
  end
486
547
 
548
+ # Fetches and saves the crl bundle from the CA server without validating
549
+ # its contents. Takes an optional store to use with the http_client,
550
+ # necessary for initial download of the CRL because `build_ssl_store`
551
+ # calls this `download_and_save_crl_bundle`. If there is an error during
552
+ # this downloading process, the file should not be replaced at all. This
553
+ # streams the file directly to disk to avoid loading the entire CRL in memory.
554
+ # @param [OpenSSL::X509::Store] store optional ssl_store to use with http_client
555
+ # @raise [Puppet::Error<Puppet::Rest::ResponseError>] if bad response from server
556
+ # @return nil
557
+ def download_and_save_crl_bundle(store=nil)
558
+ begin
559
+ # If no SSL store was suppoed, use this host's SSL store
560
+ store ||= ssl_store
561
+ client = http_client(Puppet::Rest::SSLContext.new(OpenSSL::SSL::VERIFY_PEER, store))
562
+ Puppet::Util.replace_file(crl_path, 0644) do |file|
563
+ Puppet::Rest::Routes.get_crls(client, CA_NAME) do |chunk|
564
+ file.write(chunk)
565
+ end
566
+ end
567
+ rescue Puppet::Rest::ResponseError => e
568
+ raise Puppet::Error, _('Could not download CRLs: %{message}') % { message: e.message }
569
+ end
570
+ end
571
+
487
572
  # Fetches the CA certificate bundle from the CA server
488
573
  # @raise [Puppet::Error] if response from the server is not a valid certificate
489
574
  # bundle
@@ -492,7 +577,9 @@ ERROR_STRING
492
577
  return nil if Puppet::SSL::Host.ca_location != :remote
493
578
 
494
579
  begin
495
- cert_bundle = Puppet::Rest::Routes.get_certificate(http_client, CA_NAME)
580
+ cert_bundle = Puppet::Rest::Routes.get_certificate(
581
+ http_client(Puppet::Rest::SSLContext.new(OpenSSL::SSL::VERIFY_NONE)),
582
+ CA_NAME)
496
583
  # This load ensures that the response body is a valid cert bundle.
497
584
  # If the text is malformed, load_certificate_bundle will raise.
498
585
  begin
@@ -505,11 +592,11 @@ ERROR_STRING
505
592
  end
506
593
  end
507
594
 
508
- # Saves the given certs to disc, to a location determined based
509
- # on this host's configuration.
510
- # @param [[OpenSSL::X509::Certificate]] the certs to save
511
- def save_certificate_bundle(cert_bundle)
512
- Puppet::Util.replace_file(certificate_location(CA_NAME), 0644) do |f|
595
+ # Saves the given bundle to disk to a specified file path.
596
+ # @param bundle [[OpenSSL::X509::Certificate/CRL]] the certs to save
597
+ # @param location [String] place on disk to save bundle
598
+ def save_bundle(cert_bundle, location)
599
+ Puppet::Util.replace_file(location, 0644) do |f|
513
600
  bundle_string = cert_bundle.map(&:to_pem).join("\n")
514
601
  f.write(bundle_string)
515
602
  end
@@ -569,7 +656,9 @@ ERROR_STRING
569
656
  return nil if Puppet::SSL::Host.ca_location != :remote
570
657
 
571
658
  begin
572
- cert = Puppet::Rest::Routes.get_certificate(http_client, cert_name)
659
+ cert = Puppet::Rest::Routes.get_certificate(
660
+ http_client(Puppet::Rest::SSLContext.new(OpenSSL::SSL::VERIFY_PEER, ssl_store)),
661
+ cert_name)
573
662
  begin
574
663
  Puppet::SSL::Certificate.from_s(cert)
575
664
  rescue OpenSSL::X509::CertificateError
@@ -598,7 +687,7 @@ ERROR_STRING
598
687
  # Returns the file path for the named certificate, based on this host's
599
688
  # configuration.
600
689
  # @param [String] name the name of the cert to find
601
- # @return [String] file path to the certs location
690
+ # @return [String] file path to the cert's location
602
691
  def certificate_location(cert_name)
603
692
  if Puppet::SSL::Host.ca_location == :only
604
693
  cert_name == CA_NAME ? Puppet[:cacert] : File.join(Puppet[:signeddir], "#{cert_name}.pem")
@@ -607,13 +696,25 @@ ERROR_STRING
607
696
  end
608
697
  end
609
698
 
699
+ # Returns the file path for the named CSR, based on this host's configuration.
700
+ # @param [String] name the name of the CSR to find
701
+ # @return [String] file path to the CSR's location
702
+ def certificate_request_location(cert_name)
703
+ if Puppet::SSL::Host.ca_location == :only ||
704
+ Puppet::SSL::Host.ca_location == :local
705
+ File.join(Puppet[:csrdir], "#{cert_name}.pem")
706
+ else
707
+ File.join(Puppet[:requestdir], "#{cert_name}.pem")
708
+ end
709
+ end
710
+
610
711
  # @param [OpenSSL::X509::PURPOSE_*] constant defining the kinds of certs
611
712
  # this store can verify
612
713
  # @return [OpenSSL::X509::Store]
613
714
  # @raise [OpenSSL::X509::StoreError] if localcacert is malformed or non-existant
614
715
  # @raise [Puppet::Error] if the CRL chain is malformed
615
716
  # @raise [Errno::ENOENT] if the CRL does not exist on disk but use_crl? is true
616
- def build_ssl_store(purpose)
717
+ def build_ssl_store(purpose=OpenSSL::X509::PURPOSE_ANY)
617
718
  store = OpenSSL::X509::Store.new
618
719
  store.purpose = purpose
619
720
 
@@ -622,6 +723,10 @@ ERROR_STRING
622
723
  store.add_file(Puppet.settings[:localcacert])
623
724
 
624
725
  if use_crl?
726
+ if !Puppet::FileSystem.exist?(crl_path)
727
+ download_and_save_crl_bundle(store)
728
+ end
729
+
625
730
  crls = load_crls(crl_path)
626
731
 
627
732
  flags = OpenSSL::X509::V_FLAG_CRL_CHECK