Class: Puppet::X509::CertProvider Private

Inherits:
Object
  • Object
show all
Includes:
PemStore
Defined in:
lib/puppet/x509/cert_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.

Class for loading and saving cert related objects.

Constant Summary collapse

VALID_CERTNAME =

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

Only allow printing ascii characters, excluding /

/\A[ -.0-~]+\Z/
CERT_DELIMITERS =

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

/-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----/m
CRL_DELIMITERS =

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

/-----BEGIN X509 CRL-----.*?-----END X509 CRL-----/m

Instance Method Summary collapse

Methods included from PemStore

#delete_pem, #load_pem, #save_pem

Constructor Details

#initialize(capath: Puppet[:localcacert], crlpath: Puppet[:hostcrl], privatekeydir: Puppet[:privatekeydir], certdir: Puppet[:certdir], requestdir: Puppet[:requestdir]) ⇒ CertProvider

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 a new instance of CertProvider.



14
15
16
17
18
19
20
21
22
23
24
# File 'lib/puppet/x509/cert_provider.rb', line 14

def initialize(capath: Puppet[:localcacert],
               crlpath: Puppet[:hostcrl],
               privatekeydir: Puppet[:privatekeydir],
               certdir: Puppet[:certdir],
               requestdir: Puppet[:requestdir])
  @capath = capath
  @crlpath = crlpath
  @privatekeydir = privatekeydir
  @certdir = certdir
  @requestdir = requestdir
end

Instance Method Details

#create_request(name, private_key) ⇒ Puppet::X509::Request

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 a certificate signing request (CSR).

Parameters:

  • name (String)

    the request identity

  • private_key (OpenSSL::PKey::RSA)

    private key

Returns:

  • (Puppet::X509::Request)

    The request



207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/puppet/x509/cert_provider.rb', line 207

def create_request(name, private_key)
  options = {}

  if Puppet[:dns_alt_names] && Puppet[:dns_alt_names] != ''
    options[:dns_alt_names] = Puppet[:dns_alt_names]
  end

  csr_attributes = Puppet::SSL::CertificateRequestAttributes.new(Puppet[:csr_attributes])
  if csr_attributes.load
    options[:csr_attributes] = csr_attributes.custom_attributes
    options[:extension_requests] = csr_attributes.extension_requests
  end

  csr = Puppet::SSL::CertificateRequest.new(name)
  csr.generate(private_key, options)
end

#delete_request(name) ⇒ 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.

Delete a named certificate signing request (CSR) from the configured ‘requestdir`.

Parameters:

  • name (String)

    The request identity

Returns:

  • (Boolean)

    true if the CSR was deleted



256
257
258
259
260
261
# File 'lib/puppet/x509/cert_provider.rb', line 256

def delete_request(name)
  path = to_path(@requestdir, name)
  delete_pem(path)
rescue SystemCallError => e
  raise Puppet::Error.new(_("Failed to delete certificate request for '%{name}'") % {name: name}, e)
end

#load_cacerts(required: false) ⇒ Array<OpenSSL::X509::Certificate>

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 CA certs from the configured ‘capath`.

Parameters:

  • required (Boolean) (defaults to: false)

    If true, raise if they are missing

Returns:

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

    Array of CA certs

Raises:

  • (Puppet::Error)

    if the certs cannot be loaded

  • (OpenSSL::X509::CertificateError)

    The ‘pem` text does not contain a valid cert



44
45
46
47
48
49
50
51
52
# File 'lib/puppet/x509/cert_provider.rb', line 44

def load_cacerts(required: false)
  pem = load_pem(@capath)
  if !pem && required
    raise Puppet::Error, _("The CA certificates are missing from '%{path}'") % { path: @capath }
  end
  pem ? load_cacerts_from_pem(pem) : nil
rescue SystemCallError => e
  raise Puppet::Error.new(_("Failed to load CA certificates from '%{capath}'") % {capath: @capath}, e)
end

#load_cacerts_from_pem(pem) ⇒ Array<OpenSSL::X509::Certificate>

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 PEM encoded CA certificates.

Parameters:

  • pem (String)

    PEM encoded certificate(s)

Returns:

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

    Array of CA certs

Raises:

  • (OpenSSL::X509::CertificateError)

    The ‘pem` text does not contain a valid cert



60
61
62
63
64
65
66
67
# File 'lib/puppet/x509/cert_provider.rb', line 60

def load_cacerts_from_pem(pem)
  # TRANSLATORS 'PEM' is an acronym and shouldn't be translated
  raise OpenSSL::X509::CertificateError, _("Failed to parse CA certificates as PEM") if pem !~ CERT_DELIMITERS

  pem.scan(CERT_DELIMITERS).map do |text|
    OpenSSL::X509::Certificate.new(text)
  end
end

#load_client_cert(name, required: false) ⇒ OpenSSL::X509::Request

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 a named client cert from the configured ‘certdir`.

Parameters:

  • name (String)

    The client cert identity

  • required (Boolean) (defaults to: false)

    If true, raise it is missing

Returns:

  • (OpenSSL::X509::Request)

    the request

Raises:

  • (Puppet::Error)

    if the client cert cannot be loaded

  • (OpenSSL::X509::CertificateError)

    The ‘pem` text does not contain a valid cert



180
181
182
183
184
185
186
187
188
189
# File 'lib/puppet/x509/cert_provider.rb', line 180

def load_client_cert(name, required: false)
  path = to_path(@certdir, name)
  pem = load_pem(path)
  if !pem && required
    raise Puppet::Error, _("The client certificate is missing from '%{path}'") % { path: path }
  end
  pem ? load_client_cert_from_pem(pem) : nil
rescue SystemCallError => e
  raise Puppet::Error.new(_("Failed to load client certificate for '%{name}'") % {name: name}, e)
end

#load_client_cert_from_pem(pem) ⇒ OpenSSL::X509::Certificate

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 a PEM encoded certificate.

Parameters:

  • pem (String)

    PEM encoded cert

Returns:

  • (OpenSSL::X509::Certificate)

    the certificate

Raises:

  • (OpenSSL::X509::CertificateError)

    The ‘pem` text does not contain a valid cert



197
198
199
# File 'lib/puppet/x509/cert_provider.rb', line 197

def load_client_cert_from_pem(pem)
  OpenSSL::X509::Certificate.new(pem)
end

#load_crls(required: false) ⇒ Array<OpenSSL::X509::CRL>

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 CRLs from the configured ‘crlpath` path.

Parameters:

  • required (Boolean) (defaults to: false)

    If true, raise if they are missing

Returns:

  • (Array<OpenSSL::X509::CRL>)

    Array of CRLs

Raises:

  • (Puppet::Error)

    if the CRLs cannot be loaded

  • (OpenSSL::X509::CRLError)

    The ‘pem` text does not contain a valid CRL



87
88
89
90
91
92
93
94
95
# File 'lib/puppet/x509/cert_provider.rb', line 87

def load_crls(required: false)
  pem = load_pem(@crlpath)
  if !pem && required
    raise Puppet::Error, _("The CRL is missing from '%{path}'") % { path: @crlpath }
  end
  pem ? load_crls_from_pem(pem) : nil
rescue SystemCallError => e
  raise Puppet::Error.new(_("Failed to load CRLs from '%{crlpath}'") % {crlpath: @crlpath}, e)
end

#load_crls_from_pem(pem) ⇒ Array<OpenSSL::X509::CRL>

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 PEM encoded CRL(s).

Parameters:

  • pem (String)

    PEM encoded CRL(s)

Returns:

  • (Array<OpenSSL::X509::CRL>)

    Array of CRLs

Raises:

  • (OpenSSL::X509::CRLError)

    The ‘pem` text does not contain a valid CRL



103
104
105
106
107
108
109
110
# File 'lib/puppet/x509/cert_provider.rb', line 103

def load_crls_from_pem(pem)
  # TRANSLATORS 'PEM' is an acronym and shouldn't be translated
  raise OpenSSL::X509::CRLError, _("Failed to parse CRLs as PEM") if pem !~ CRL_DELIMITERS

  pem.scan(CRL_DELIMITERS).map do |text|
    OpenSSL::X509::CRL.new(text)
  end
end

#load_private_key(name, required: false) ⇒ OpenSSL::PKey::RSA

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 a private key from the configured ‘privatekeydir`. For historical reasons, names are case-insensitive.

Parameters:

  • name (String)

    The private key identity

  • required (Boolean) (defaults to: false)

    If true, raise if it is missing

Returns:

  • (OpenSSL::PKey::RSA)

    The private key

Raises:

  • (Puppet::Error)

    if the private key cannot be loaded

  • (OpenSSL::PKey::RSAError)

    The ‘pem` text does not contain a valid key



135
136
137
138
139
140
141
142
143
144
# File 'lib/puppet/x509/cert_provider.rb', line 135

def load_private_key(name, required: false)
  path = to_path(@privatekeydir, name)
  pem = load_pem(path)
  if !pem && required
    raise Puppet::Error, _("The private key is missing from '%{path}'") % { path: path }
  end
  pem ? load_private_key_from_pem(pem) : nil
rescue SystemCallError => e
  raise Puppet::Error.new(_("Failed to load private key for '%{name}'") % {name: name}, e)
end

#load_private_key_from_pem(pem) ⇒ OpenSSL::PKey::RSA

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 a PEM encoded private key.

Parameters:

  • pem (String)

    PEM encoded private key

Returns:

  • (OpenSSL::PKey::RSA)

    The private key

Raises:

  • (OpenSSL::PKey::RSAError)

    The ‘pem` text does not contain a valid key



152
153
154
155
156
157
# File 'lib/puppet/x509/cert_provider.rb', line 152

def load_private_key_from_pem(pem)
  # set a non-nil passphrase to ensure openssl doesn't prompt
  # but ruby 2.4.0 & 2.4.1 require at least 4 bytes, see
  # https://github.com/ruby/ruby/commit/f012932218fd609f75f9268812df61fb26e2d0f1#diff-40e4270ec386990ac60d7ab5ff8045a4
  OpenSSL::PKey::RSA.new(pem, '    ')
end

#load_request(name) ⇒ OpenSSL::X509::Request

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 a named certificate signing request (CSR) from the configured ‘requestdir`.

Parameters:

  • name (String)

    The request identity

Returns:

  • (OpenSSL::X509::Request)

    the request

Raises:

  • (Puppet::Error)

    if the cert request cannot be saved

  • (OpenSSL::X509::RequestError)

    The ‘pem` text does not contain a valid request



244
245
246
247
248
249
250
# File 'lib/puppet/x509/cert_provider.rb', line 244

def load_request(name)
  path = to_path(@requestdir, name)
  pem = load_pem(path)
  pem ? load_request_from_pem(pem) : nil
rescue SystemCallError => e
  raise Puppet::Error.new(_("Failed to load certificate request for '%{name}'") % {name: name}, e)
end

#load_request_from_pem(pem) ⇒ OpenSSL::X509::Request

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 a PEM encoded certificate signing request (CSR).

Parameters:

  • pem (String)

    PEM encoded request

Returns:

  • (OpenSSL::X509::Request)

    the request

Raises:

  • (OpenSSL::X509::RequestError)

    The ‘pem` text does not contain a valid request



269
270
271
# File 'lib/puppet/x509/cert_provider.rb', line 269

def load_request_from_pem(pem)
  OpenSSL::X509::Request.new(pem)
end

#save_cacerts(certs) ⇒ 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.

Save ‘certs` to the configured `capath`.

Parameters:

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

    Array of CA certs to save

Raises:



31
32
33
34
35
# File 'lib/puppet/x509/cert_provider.rb', line 31

def save_cacerts(certs)
  save_pem(certs.map(&:to_pem).join, @capath, **permissions_for_setting(:localcacert))
rescue SystemCallError => e
  raise Puppet::Error.new(_("Failed to save CA certificates to '%{capath}'") % {capath: @capath}, e)
end

#save_client_cert(name, cert) ⇒ 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.

Save a named client cert to the configured ‘certdir`.

Parameters:

  • name (String)

    The client cert identity

  • cert (OpenSSL::X509::Certificate)

    The cert to save

Raises:



165
166
167
168
169
170
# File 'lib/puppet/x509/cert_provider.rb', line 165

def save_client_cert(name, cert)
  path = to_path(@certdir, name)
  save_pem(cert.to_pem, path, **permissions_for_setting(:hostcert))
rescue SystemCallError => e
  raise Puppet::Error.new(_("Failed to save client certificate for '%{name}'") % {name: name}, e)
end

#save_crls(crls) ⇒ 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.

Save ‘crls` to the configured `crlpath`.

Parameters:

  • crls (Array<OpenSSL::X509::CRL>)

    Array of CRLs to save

Raises:



74
75
76
77
78
# File 'lib/puppet/x509/cert_provider.rb', line 74

def save_crls(crls)
  save_pem(crls.map(&:to_pem).join, @crlpath, **permissions_for_setting(:hostcrl))
rescue SystemCallError => e
  raise Puppet::Error.new(_("Failed to save CRLs to '%{crlpath}'") % {crlpath: @crlpath}, e)
end

#save_private_key(name, 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.

Save named private key in the configured ‘privatekeydir`. For historical reasons, names are case insensitive.

Parameters:

  • name (String)

    The private key identity

  • key (OpenSSL::PKey::RSA)

    private key

Raises:



119
120
121
122
123
124
# File 'lib/puppet/x509/cert_provider.rb', line 119

def save_private_key(name, key)
  path = to_path(@privatekeydir, name)
  save_pem(key.to_pem, path, **permissions_for_setting(:hostprivkey))
rescue SystemCallError => e
  raise Puppet::Error.new(_("Failed to save private key for '%{name}'") % {name: name}, e)
end

#save_request(name, csr) ⇒ 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.

Save a certificate signing request (CSR) to the configured ‘requestdir`.

Parameters:

  • name (String)

    the request identity

  • csr (OpenSSL::X509::Request)

    the request

Raises:



230
231
232
233
234
235
# File 'lib/puppet/x509/cert_provider.rb', line 230

def save_request(name, csr)
  path = to_path(@requestdir, name)
  save_pem(csr.to_pem, path, **permissions_for_setting(:hostcsr))
rescue SystemCallError => e
  raise Puppet::Error.new(_("Failed to save certificate request for '%{name}'") % {name: name}, e)
end