Class: Puppet::SSL::SSLProvider Private

Inherits:
Object
  • Object
show all
Defined in:
lib/puppet/ssl/ssl_provider.rb

Overview

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

SSL Provider creates SSLContext objects that can be used to create secure connections.

Instance Method Summary collapse

Instance Method Details

#create_context(cacerts:, crls:, private_key:, client_cert:, revocation: ) ⇒ Puppet::SSL::SSLContext

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.

Create an SSLContext using the trusted cacerts, crls, private_key, client_cert, and revocation mode. Connections made from the returned context will be mutually authenticated.

The crls parameter must contain CRLs corresponding to each CA in cacerts depending on the revocation mode:

  • :chain - crls must contain a CRL for every CA in cacerts

  • :leaf - crls must contain (at least) the CRL for the leaf CA in cacerts

  • false - crls can be empty

The private_key and public key from the client_cert must match.

Parameters:

Returns:

Raises:



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/puppet/ssl/ssl_provider.rb', line 103

def create_context(cacerts:, crls:, private_key:, client_cert:, revocation: Puppet[:certificate_revocation])
  raise ArgumentError, _("CA certs are missing") unless cacerts
  raise ArgumentError, _("CRLs are missing") unless crls
  raise ArgumentError, _("Private key is missing") unless private_key
  raise ArgumentError, _("Client cert is missing") unless client_cert

  store = create_x509_store(cacerts, crls, revocation)
  client_chain = verify_cert_with_store(store, client_cert)

  if !private_key.is_a?(OpenSSL::PKey::RSA) && !private_key.is_a?(OpenSSL::PKey::EC)
    raise Puppet::SSL::SSLError, _("Unsupported key '%{type}'") % { type: private_key.class.name }
  end

  unless client_cert.check_private_key(private_key)
    raise Puppet::SSL::SSLError, _("The certificate for '%{name}' does not match its private key") % { name: subject(client_cert) }
  end

  Puppet::SSL::SSLContext.new(
    store: store, cacerts: cacerts, crls: crls,
    private_key: private_key, client_cert: client_cert, client_chain: client_chain,
    revocation: revocation
  ).freeze
end

#create_insecure_contextPuppet::SSL::SSLContext

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.

Create an insecure SSLContext. Connections made from the returned context will not authenticate the server, i.e. VERIFY_NONE, and are vulnerable to MITM. Do not call this method.

Returns:



14
15
16
17
18
# File 'lib/puppet/ssl/ssl_provider.rb', line 14

def create_insecure_context
  store = create_x509_store([], [], false)

  Puppet::SSL::SSLContext.new(store: store, verify_peer: false).freeze
end

#create_root_context(cacerts:, crls: [], revocation: ) ⇒ Puppet::SSL::SSLContext

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.

Create an SSLContext using the trusted cacerts and optional crls. Connections made from the returned context will authenticate the server, i.e. VERIFY_PEER, but will not use a client certificate.

The crls parameter must contain CRLs corresponding to each CA in cacerts depending on the revocation mode. See #create_context.

Parameters:

  • cacerts (Array<OpenSSL::X509::Certificate>)

    Array of trusted CA certs

  • crls (Array<OpenSSL::X509::CRL>) (defaults to: [])

    Array of CRLs

  • revocation (:chain, :leaf, false) (defaults to: )

    revocation mode

Returns:

Raises:



33
34
35
36
37
# File 'lib/puppet/ssl/ssl_provider.rb', line 33

def create_root_context(cacerts:, crls: [], revocation: Puppet[:certificate_revocation])
  store = create_x509_store(cacerts, crls, revocation)

  Puppet::SSL::SSLContext.new(store: store, cacerts: cacerts, crls: crls, revocation: revocation).freeze
end

#create_system_context(cacerts:, path: ) ⇒ Puppet::SSL::SSLContext

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.

Create an SSLContext using the trusted cacerts and any certs in OpenSSL’s default verify path locations. When running puppet as a gem, the location is system dependent. When running puppet from puppet-agent packages, the location refers to the cacerts bundle in the puppet-agent package.

Connections made from the returned context will authenticate the server, i.e. VERIFY_PEER, but will not use a client certificate and will not perform revocation checking.

Parameters:

  • cacerts (Array<OpenSSL::X509::Certificate>)

    Array of trusted CA certs

  • path (String, nil) (defaults to: )

    A file containing additional trusted CA certs.

Returns:

Raises:



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/puppet/ssl/ssl_provider.rb', line 53

def create_system_context(cacerts:, path: Puppet[:ssl_trust_store])
  store = create_x509_store(cacerts, [], false)
  store.set_default_paths

  if path
    stat = Puppet::FileSystem.stat(path)
    if stat
      if stat.ftype == 'file'
        # don't add empty files as ruby/openssl will raise
        if stat.size > 0
          begin
            store.add_file(path)
          rescue => e
            Puppet.err(_("Failed to add '%{path}' as a trusted CA file: %{detail}" % { path: path, detail: e.message }, e))
          end
        end
      else
        Puppet.warning(_("The 'ssl_trust_store' setting does not refer to a file and will be ignored: '%{path}'" % { path: path }))
      end
    end
  end

  Puppet::SSL::SSLContext.new(store: store, cacerts: cacerts, crls: [], revocation: false).freeze
end

#load_context(certname: , revocation: , password: nil) ⇒ Puppet::SSL::SSLContext

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.

Load an SSLContext using available certs and keys. An exception is raised if any component is missing or is invalid, such as a mismatched client cert and private key. Connections made from the returned context will be mutually authenticated.

Parameters:

  • certname (String) (defaults to: )

    Which cert & key to load

  • revocation (:chain, :leaf, false) (defaults to: )

    revocation mode

  • password (String, nil) (defaults to: nil)

    If the private key is encrypted, decrypt it using the password. If the key is encrypted, but a password is not specified, then the key cannot be loaded.

Returns:

Raises:



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/puppet/ssl/ssl_provider.rb', line 142

def load_context(certname: Puppet[:certname], revocation: Puppet[:certificate_revocation], password: nil)
  cert = Puppet::X509::CertProvider.new
  cacerts = cert.load_cacerts(required: true)
  crls = case revocation
         when :chain, :leaf
           cert.load_crls(required: true)
         else
           []
         end
  private_key = cert.load_private_key(certname, required: true, password: password)
  client_cert = cert.load_client_cert(certname, required: true)

  create_context(cacerts: cacerts, crls: crls,  private_key: private_key, client_cert: client_cert, revocation: revocation)
rescue OpenSSL::PKey::PKeyError => e
  raise Puppet::SSL::SSLError.new(_("Failed to load private key for host '%{name}': %{message}") % { name: certname, message: e.message }, e)
end

#verify_request(csr, public_key) ⇒ 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.

Verify the csr was signed with a private key corresponding to the public_key. This ensures the CSR was signed by someone in possession of the private key, and that it hasn’t been tampered with since.

Parameters:

Raises:

  • (Puppet::SSL:SSLError)

    The private_key for the given public_key was not used to sign the CSR.



168
169
170
171
172
173
174
# File 'lib/puppet/ssl/ssl_provider.rb', line 168

def verify_request(csr, public_key)
  unless csr.verify(public_key)
    raise Puppet::SSL::SSLError, _("The CSR for host '%{name}' does not match the public key") % { name: subject(csr) }
  end

  csr
end