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[:certificate_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:


84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/puppet/ssl/ssl_provider.rb', line 84

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[:certificate_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: Puppet[:certificate_revocation])

    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:) ⇒ 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:

Returns:

Raises:


52
53
54
55
56
57
# File 'lib/puppet/ssl/ssl_provider.rb', line 52

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

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

#load_context(certname: Puppet[:certname], revocation: Puppet[:certificate_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: Puppet[:certname])

    Which cert & key to load

  • revocation (:chain, :leaf, false) (defaults to: Puppet[:certificate_revocation])

    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:


123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/puppet/ssl/ssl_provider.rb', line 123

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.


149
150
151
152
153
154
155
# File 'lib/puppet/ssl/ssl_provider.rb', line 149

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