vendored/puppet/lib/puppet/ssl/validator/default_validator.rb in bolt-0.20.3 vs vendored/puppet/lib/puppet/ssl/validator/default_validator.rb in bolt-0.20.5
- old
+ new
@@ -7,31 +7,24 @@
# @api private
#
class Puppet::SSL::Validator::DefaultValidator #< class Puppet::SSL::Validator
attr_reader :peer_certs
attr_reader :verify_errors
- attr_reader :ssl_configuration
FIVE_MINUTES_AS_SECONDS = 5 * 60
# Creates a new DefaultValidator, optionally with an SSL Configuration and SSL Host.
#
- # @param ssl_configuration [Puppet::SSL::Configuration] (a default configuration) ssl_configuration the SSL configuration to use
- # @param ssl_host [Puppet::SSL::Host] The SSL host to use
+ # @param ca_path [String] Filepath for the cacert
#
# @api private
#
def initialize(
- ssl_configuration = Puppet::SSL::Configuration.new(
- Puppet[:localcacert], {
- :ca_auth_file => Puppet[:ssl_client_ca_auth]
- }),
- ssl_host = Puppet.lookup(:ssl_host))
+ ca_path = Puppet[:ssl_client_ca_auth] || Puppet[:localcacert])
reset!
- @ssl_configuration = ssl_configuration
- @ssl_host = ssl_host
+ @ca_path = ca_path
end
# Resets this validator to its initial validation state. The ssl configuration is not changed.
#
@@ -68,11 +61,11 @@
#
# @api private
#
def call(preverify_ok, store_context)
current_cert = store_context.current_cert
- @peer_certs << Puppet::SSL::Certificate.from_instance(current_cert)
+ @peer_certs << current_cert
# We must make a copy since the scope of the store_context will be lost
# across invocations of this method.
if preverify_ok
# If we've copied all of the certs in the chain out of the SSL library
@@ -111,34 +104,55 @@
# Registers the instance's call method with the connection.
#
# @param [Net::HTTP] connection The connection to validate
#
+ # @param [Puppet::SSL::Host] host The host object containing SSL data
# @return [void]
#
# @api private
#
- def setup_connection(connection)
+ def setup_connection(connection, ssl_host = Puppet.lookup(:ssl_host))
if ssl_certificates_are_present?
- connection.cert_store = @ssl_host.ssl_store
- connection.ca_file = @ssl_configuration.ca_auth_file
- connection.cert = @ssl_host.certificate.content
- connection.key = @ssl_host.key.content
+ connection.cert_store = ssl_host.ssl_store
+ connection.ca_file = @ca_path
+ connection.cert = ssl_host.certificate.content
+ connection.key = ssl_host.key.content
connection.verify_mode = OpenSSL::SSL::VERIFY_PEER
connection.verify_callback = self
else
connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
end
+ ##
+ # Decode a string of concatenated certificates
+ #
+ # @return [Array<OpenSSL::X509::Certificate>]
+ def decode_cert_bundle(bundle_str)
+ re = /-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----/m
+ pem_ary = bundle_str.scan(re)
+ pem_ary.map do |pem_str|
+ OpenSSL::X509::Certificate.new(pem_str)
+ end
+ end
+
+ # read_file makes testing easier.
+ def read_file(path)
+ # https://www.ietf.org/rfc/rfc2459.txt defines the x509 V3 certificate format
+ # CA bundles are concatenated X509 certificates, but may also include
+ # comments, which could have UTF-8 characters
+ Puppet::FileSystem.read(path, :encoding => Encoding::UTF_8)
+ end
+
# Validates the peer certificates against the authorized certificates.
#
# @api private
#
def valid_peer?
- descending_cert_chain = @peer_certs.reverse.map {|c| c.content }
- authz_ca_certs = ssl_configuration.ca_auth_certificates
+ descending_cert_chain = @peer_certs.reverse
+ authz_ca_certs = decode_cert_bundle(read_file(@ca_path))
if not has_authz_peer_cert(descending_cert_chain, authz_ca_certs)
msg = "The server presented a SSL certificate chain which does not include a " <<
"CA listed in the ssl_client_ca_auth file. "
msg << "Authorized Issuers: #{authz_ca_certs.collect {|c| c.subject}.join(', ')} " <<
@@ -166,8 +180,8 @@
end
# @api private
#
def ssl_certificates_are_present?
- Puppet::FileSystem.exist?(Puppet[:hostcert]) && Puppet::FileSystem.exist?(@ssl_configuration.ca_auth_file)
+ Puppet::FileSystem.exist?(Puppet[:hostcert]) && Puppet::FileSystem.exist?(@ca_path)
end
end