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.
- checksums.yaml +5 -5
- data/lib/bolt/applicator.rb +56 -0
- data/lib/bolt/error.rb +6 -0
- data/lib/bolt/pal.rb +8 -1
- data/lib/bolt/transport/winrm.rb +4 -1
- data/lib/bolt/version.rb +1 -1
- data/libexec/apply_catalog.rb +61 -0
- data/{exe → libexec}/bolt_catalog +0 -0
- data/vendored/puppet/lib/puppet/application.rb +8 -1
- data/vendored/puppet/lib/puppet/application/device.rb +24 -28
- data/vendored/puppet/lib/puppet/application/doc.rb +4 -2
- data/vendored/puppet/lib/puppet/configurer/plugin_handler.rb +1 -2
- data/vendored/puppet/lib/puppet/datatypes.rb +1 -1
- data/vendored/puppet/lib/puppet/defaults.rb +2 -6
- data/vendored/puppet/lib/puppet/environments.rb +4 -10
- data/vendored/puppet/lib/puppet/error.rb +1 -1
- data/vendored/puppet/lib/puppet/etc.rb +4 -5
- data/vendored/puppet/lib/puppet/face/config.rb +1 -1
- data/vendored/puppet/lib/puppet/face/module/build.rb +5 -55
- data/vendored/puppet/lib/puppet/face/module/generate.rb +5 -247
- data/vendored/puppet/lib/puppet/gettext/config.rb +28 -5
- data/vendored/puppet/lib/puppet/indirector/catalog/compiler.rb +5 -7
- data/vendored/puppet/lib/puppet/indirector/rest.rb +7 -56
- data/vendored/puppet/lib/puppet/indirector/terminus.rb +1 -1
- data/vendored/puppet/lib/puppet/interface.rb +1 -1
- data/vendored/puppet/lib/puppet/interface/face_collection.rb +3 -1
- data/vendored/puppet/lib/puppet/metatype/manager.rb +2 -2
- data/vendored/puppet/lib/puppet/module_tool/applications.rb +0 -1
- data/vendored/puppet/lib/puppet/module_tool/applications/application.rb +1 -1
- data/vendored/puppet/lib/puppet/network/http/connection.rb +2 -23
- data/vendored/puppet/lib/puppet/network/http/factory.rb +2 -6
- data/vendored/puppet/lib/puppet/node.rb +1 -2
- data/vendored/puppet/lib/puppet/node/environment.rb +5 -1
- data/vendored/puppet/lib/puppet/parser/functions.rb +35 -3
- data/vendored/puppet/lib/puppet/pops/evaluator/evaluator_impl.rb +12 -0
- data/vendored/puppet/lib/puppet/pops/loader/static_loader.rb +0 -5
- data/vendored/puppet/lib/puppet/pops/model/ast.rb +107 -0
- data/vendored/puppet/lib/puppet/pops/model/factory.rb +11 -0
- data/vendored/puppet/lib/puppet/pops/model/model_label_provider.rb +2 -0
- data/vendored/puppet/lib/puppet/pops/parser/eparser.rb +1519 -1485
- data/vendored/puppet/lib/puppet/pops/parser/lexer2.rb +1 -1
- data/vendored/puppet/lib/puppet/pops/puppet_stack.rb +1 -1
- data/vendored/puppet/lib/puppet/pops/serialization/to_data_converter.rb +1 -1
- data/vendored/puppet/lib/puppet/pops/types/p_binary_type.rb +1 -2
- data/vendored/puppet/lib/puppet/pops/types/types.rb +1 -24
- data/vendored/puppet/lib/puppet/pops/validation/checker4_0.rb +5 -0
- data/vendored/puppet/lib/puppet/pops/validation/tasks_checker.rb +31 -4
- data/vendored/puppet/lib/puppet/provider.rb +12 -1
- data/vendored/puppet/lib/puppet/provider/package/dnf.rb +2 -1
- data/vendored/puppet/lib/puppet/provider/selmodule/semodule.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/service/base.rb +1 -1
- data/vendored/puppet/lib/puppet/provider/service/systemd.rb +3 -1
- data/vendored/puppet/lib/puppet/provider/service/upstart.rb +2 -0
- data/vendored/puppet/lib/puppet/reference/configuration.rb +6 -0
- data/vendored/puppet/lib/puppet/reports.rb +2 -2
- data/vendored/puppet/lib/puppet/resource/status.rb +2 -0
- data/vendored/puppet/lib/puppet/resource/type_collection.rb +1 -1
- data/vendored/puppet/lib/puppet/rest/client.rb +28 -24
- data/vendored/puppet/lib/puppet/rest/response.rb +5 -0
- data/vendored/puppet/lib/puppet/rest/route.rb +13 -31
- data/vendored/puppet/lib/puppet/rest/routes.rb +65 -5
- data/vendored/puppet/lib/puppet/rest/ssl_context.rb +13 -0
- data/vendored/puppet/lib/puppet/settings.rb +6 -0
- data/vendored/puppet/lib/puppet/settings/config_file.rb +1 -2
- data/vendored/puppet/lib/puppet/ssl/certificate_request.rb +5 -1
- data/vendored/puppet/lib/puppet/ssl/host.rb +148 -43
- data/vendored/puppet/lib/puppet/ssl/oids.rb +1 -1
- data/vendored/puppet/lib/puppet/test/test_helper.rb +3 -0
- data/vendored/puppet/lib/puppet/transaction/event_manager.rb +3 -1
- data/vendored/puppet/lib/puppet/transaction/report.rb +1 -1
- data/vendored/puppet/lib/puppet/type.rb +2 -2
- data/vendored/puppet/lib/puppet/type/file/content.rb +2 -3
- data/vendored/puppet/lib/puppet/type/schedule.rb +33 -84
- data/vendored/puppet/lib/puppet/type/user.rb +1 -1
- data/vendored/puppet/lib/puppet/util.rb +5 -0
- data/vendored/puppet/lib/puppet/util/autoload.rb +39 -31
- data/vendored/puppet/lib/puppet/util/character_encoding.rb +0 -22
- data/vendored/puppet/lib/puppet/util/command_line.rb +0 -1
- data/vendored/puppet/lib/puppet/util/connection.rb +74 -0
- data/vendored/puppet/lib/puppet/util/feature.rb +2 -2
- data/vendored/puppet/lib/puppet/util/instance_loader.rb +1 -19
- data/vendored/puppet/lib/puppet/util/json.rb +0 -8
- data/vendored/puppet/lib/puppet/util/log/destinations.rb +1 -1
- data/vendored/puppet/lib/puppet/util/network_device/base.rb +1 -1
- data/vendored/puppet/lib/puppet/util/platform.rb +3 -0
- data/vendored/puppet/lib/puppet/util/rdoc/parser/puppet_parser_core.rb +1 -1
- data/vendored/puppet/lib/puppet/util/reference.rb +2 -2
- data/vendored/puppet/lib/puppet/util/rubygems.rb +1 -13
- data/vendored/puppet/lib/puppet/util/ssl.rb +40 -1
- data/vendored/puppet/lib/puppet/util/windows.rb +1 -0
- data/vendored/puppet/lib/puppet/util/windows/file.rb +18 -0
- data/vendored/puppet/lib/puppet/util/windows/security.rb +26 -14
- metadata +8 -73
- data/vendored/puppet/lib/puppet/module_tool/applications/builder.rb +0 -152
- data/vendored/puppet/lib/puppet/module_tool/skeleton/templates/generator/spec/spec_helper.rb +0 -1
- data/vendored/puppet/lib/puppet/provider/mailalias/aliases.rb +0 -50
- data/vendored/puppet/lib/puppet/provider/maillist/mailman.rb +0 -108
- data/vendored/puppet/lib/puppet/provider/zfs/zfs.rb +0 -108
- data/vendored/puppet/lib/puppet/provider/zone/solaris.rb +0 -364
- data/vendored/puppet/lib/puppet/provider/zpool/zpool.rb +0 -125
- data/vendored/puppet/lib/puppet/type/mailalias.rb +0 -46
- data/vendored/puppet/lib/puppet/type/maillist.rb +0 -62
- data/vendored/puppet/lib/puppet/type/zfs.rb +0 -154
- data/vendored/puppet/lib/puppet/type/zone.rb +0 -382
- 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
|
-
|
10
|
-
|
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 |
|
22
|
-
header = { 'Accept' => 'text/plain', '
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
#
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
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
|
-
|
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
|
475
|
+
def process_crl_string(crl_string)
|
422
476
|
delimiters = /-----BEGIN X509 CRL-----.*?-----END X509 CRL-----/m
|
423
|
-
|
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
|
-
|
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
|
-
|
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(
|
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
|
509
|
-
#
|
510
|
-
# @param [
|
511
|
-
def
|
512
|
-
Puppet::Util.replace_file(
|
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(
|
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
|
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
|