Module: Puppet::Util::SSL Private

Defined in:
lib/puppet/util/ssl.rb

Overview

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

SSL is a private module with class methods that help work with x.509 subjects and errors.

Constant Summary collapse

@@dn_parsers =

This classvariable is part of a private API. You should avoid using this classvariable if possible, as it may be removed or be changed in the future.

nil
@@no_name =

This classvariable is part of a private API. You should avoid using this classvariable if possible, as it may be removed or be changed in the future.

nil

Class Method Summary collapse

Class Method Details

.cn_from_subject(subject) ⇒ String?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

cn_from_subject extracts the CN from the given OpenSSL certificate subject.

Parameters:

  • subject (OpenSSL::X509::Name)

    the subject to extract the CN field from

Returns:

  • (String, nil)

    the CN, or nil if not found



46
47
48
49
50
# File 'lib/puppet/util/ssl.rb', line 46

def self.cn_from_subject(subject)
  if subject.respond_to? :to_a
    (subject.to_a.assoc('CN') || [])[1]
  end
end

.handle_connection_error(error, verifier, host) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Extract and format meaningful error messages from OpenSSL::OpenSSLErrors and a Validator. Re-raises the error if unknown.

Parameters:

  • error (OpenSSL::OpenSSLError)

    An error thrown during creating a connection

  • verifier (Puppet::SSL::DefaultValidator)

    A Validator who may have invalidated the connection

  • host (String)

    The DNS name of the other end of the SSL connection



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/puppet/util/ssl.rb', line 69

def self.handle_connection_error(error, verifier, host)
  # can be nil
  peer_cert = verifier.peer_certs.last

  if error.message.include? "certificate verify failed"
    msg = error.message
    msg << ": [" + verifier.verify_errors.join('; ') + "]"
    raise Puppet::Error, msg, error.backtrace
  elsif peer_cert && !OpenSSL::SSL.verify_certificate_identity(peer_cert, host)
    valid_certnames = [peer_cert.subject.to_s.sub(/.*=/, ''),
                       *Puppet::SSL::Certificate.subject_alt_names_for(peer_cert)].uniq
    if valid_certnames.size > 1
      expected_certnames = _("expected one of %{certnames}") % { certnames: valid_certnames.join(', ') }
    else
      expected_certnames = _("expected %{certname}") % { certname: valid_certnames.first }
    end

    msg = _("Server hostname '%{host}' did not match server certificate; %{expected_certnames}") % { host: host, expected_certnames: expected_certnames }
    raise Puppet::Error, msg, error.backtrace
  else
    raise error
  end
end

.is_possibly_valid_dn?(dn) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


52
53
54
# File 'lib/puppet/util/ssl.rb', line 52

def self.is_possibly_valid_dn?(dn)
  dn =~ /=/
end

.subject_from_dn(dn) ⇒ OpenSSL::X509::Name

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Given a DN string, parse it into an OpenSSL certificate subject. This method will flexibly handle both OpenSSL and RFC2253 formats, as given by nginx and Apache, respectively.

Parameters:

  • dn (String)

    the x.509 Distinguished Name (DN) string.

Returns:

  • (OpenSSL::X509::Name)

    the certificate subject



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/puppet/util/ssl.rb', line 20

def self.subject_from_dn(dn)
  if is_possibly_valid_dn?(dn)
    parsers = @@dn_parsers ||= [
          OpenSSL::X509::Name.method(:parse_rfc2253),
          OpenSSL::X509::Name.method(:parse_openssl)
      ]
    parsers.each do |parser|
      begin
        return parser.call(dn)
      rescue OpenSSL::X509::NameError
      end
    end
  end

  @@no_name ||= OpenSSL::X509::Name.new
end