Class: Puppet::SSL::CertificateRequest
- Extended by:
- Indirector
- Defined in:
- lib/puppet/ssl/certificate_request.rb
Overview
This class creates and manages X509 certificate signing requests.
## CSR attributes
CSRs may contain a set of attributes that includes supplementary information about the CSR or information for the signed certificate.
PKCS#9/RFC 2985 section 5.4 formally defines the “Challenge password”, “Extension request”, and “Extended-certificate attributes”, but this implementation only handles the “Extension request” attribute. Other attributes may be defined on a CSR, but the RFC doesn’t define behavior for any other attributes so we treat them as only informational.
## CSR Extension request attribute
CSRs may contain an optional set of extension requests, which allow CSRs to include additional information that may be included in the signed certificate. Any additional information that should be copied from the CSR to the signed certificate MUST be included in this attribute.
This behavior is dictated by PKCS#9/RFC 2985 section 5.4.2.
Defined Under Namespace
Modules: AutoSigner Classes: Ca, DisabledCa, File, Memory, Rest
Constant Summary
Constants included from Indirector
Constants inherited from Base
Base::SEPARATOR, Base::VALID_CERTNAME
Instance Attribute Summary
Attributes inherited from Base
Class Method Summary collapse
-
.supported_formats ⇒ Object
Because of how the format handler class is included, this can’t be in the base class.
Instance Method Summary collapse
-
#custom_attributes ⇒ Hash<String, String>
Return all user specified attributes attached to this CSR as a hash.
- #ext_value_to_ruby_value(asn1_arr) ⇒ Object
- #extension_factory ⇒ Object
-
#generate(key, options = {}) ⇒ OpenSSL::X509::Request
Create a certificate request with our system settings.
-
#request_extensions ⇒ Array<Hash{String => String}>
Return the set of extensions requested on this CSR, in a form designed to be useful to Ruby: an array of hashes.
- #subject_alt_names ⇒ Object
Methods included from Indirector
Methods inherited from Base
#ca?, #digest, #digest_algorithm, #fingerprint, from_instance, from_multiple_s, from_s, #initialize, name_from_subject, #read, #to_data_hash, to_multiple_s, #to_s, #to_text, validate_certname, wrapped_class, wraps
Constructor Details
This class inherits a constructor from Puppet::SSL::Base
Class Method Details
.supported_formats ⇒ Object
Because of how the format handler class is included, this can’t be in the base class.
52 53 54 |
# File 'lib/puppet/ssl/certificate_request.rb', line 52 def self.supported_formats [:s] end |
Instance Method Details
#custom_attributes ⇒ Hash<String, String>
Return all user specified attributes attached to this CSR as a hash. IF an OID has a single value it is returned as a string, otherwise all values are returned as an array.
The format of CSR attributes is specified in PKCS#10/RFC 2986
201 202 203 204 205 206 207 208 209 |
# File 'lib/puppet/ssl/certificate_request.rb', line 201 def custom_attributes x509_attributes = @content.attributes.reject do |attr| PRIVATE_CSR_ATTRIBUTES.include? attr.oid end x509_attributes.map do |attr| {"oid" => attr.oid, "value" => attr.value.value.first.value} end end |
#ext_value_to_ruby_value(asn1_arr) ⇒ Object
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/puppet/ssl/certificate_request.rb', line 110 def ext_value_to_ruby_value(asn1_arr) # A list of ASN1 types than can't be directly converted to a Ruby type @non_convertable ||= [OpenSSL::ASN1::EndOfContent, OpenSSL::ASN1::BitString, OpenSSL::ASN1::Null, OpenSSL::ASN1::Enumerated, OpenSSL::ASN1::UTCTime, OpenSSL::ASN1::GeneralizedTime, OpenSSL::ASN1::Sequence, OpenSSL::ASN1::Set] begin # Attempt to decode the extension's DER data located in the original OctetString asn1_val = OpenSSL::ASN1.decode(asn1_arr.last.value) rescue OpenSSL::ASN1::ASN1Error # This is to allow supporting the old-style of not DER encoding trusted facts return asn1_arr.last.value end # If the extension value can not be directly converted to an atomic Ruby # type, use the original ASN1 value. This is needed to work around a bug # in Ruby's OpenSSL library which doesn't convert the value of unknown # extension OIDs properly. See PUP-3560 if @non_convertable.include?(asn1_val.class) then # Allows OpenSSL to take the ASN1 value and turn it into something Ruby understands OpenSSL::X509::Extension.new(asn1_arr.first.value, asn1_val.to_der).value else asn1_val.value end end |
#extension_factory ⇒ Object
56 57 58 |
# File 'lib/puppet/ssl/certificate_request.rb', line 56 def extension_factory @ef ||= OpenSSL::X509::ExtensionFactory.new end |
#generate(key, options = {}) ⇒ OpenSSL::X509::Request
Create a certificate request with our system settings.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/puppet/ssl/certificate_request.rb', line 76 def generate(key, = {}) Puppet.info _("Creating a new SSL certificate request for %{name}") % { name: name } # Support either an actual SSL key, or a Puppet key. key = key.content if key.is_a?(Puppet::SSL::Key) # If we're a CSR for the CA, then use the real ca_name, rather than the # fake 'ca' name. This is mostly for backward compatibility with 0.24.x, # but it's also just a good idea. common_name = name == Puppet::SSL::CA_NAME ? Puppet.settings[:ca_name] : name csr = OpenSSL::X509::Request.new csr.version = 0 csr.subject = OpenSSL::X509::Name.new([["CN", common_name]]) csr.public_key = key.public_key if [:csr_attributes] add_csr_attributes(csr, [:csr_attributes]) end if (ext_req_attribute = extension_request_attribute()) csr.add_attribute(ext_req_attribute) end signer = Puppet::SSL::CertificateSigner.new signer.sign(csr, key) raise Puppet::Error, _("CSR sign verification failed; you need to clean the certificate request for %{name} on the server") % { name: name } unless csr.verify(key.public_key) @content = csr Puppet.info _("Certificate Request fingerprint (%{digest}): %{hex_digest}") % { digest: digest.name, hex_digest: digest.to_hex } @content end |
#request_extensions ⇒ Array<Hash{String => String}>
Return the set of extensions requested on this CSR, in a form designed to be useful to Ruby: an array of hashes. Which, not coincidentally, you can pass successfully to the OpenSSL constructor later, if you want.
hashes, with key/value pairs for the extension’s oid, its value, and optionally its critical state.
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/puppet/ssl/certificate_request.rb', line 148 def request_extensions raise Puppet::Error, _("CSR needs content to extract fields") unless @content # Prefer the standard extReq, but accept the Microsoft specific version as # a fallback, if the standard version isn't found. attribute = @content.attributes.find {|x| x.oid == "extReq" } attribute ||= @content.attributes.find {|x| x.oid == "msExtReq" } return [] unless attribute extensions = unpack_extension_request(attribute) index = -1 extensions.map do |ext_values| index += 1 value = ext_value_to_ruby_value(ext_values) # OK, turn that into an extension, to unpack the content. Lovely that # we have to swap the order of arguments to the underlying method, or # perhaps that the ASN.1 representation chose to pack them in a # strange order where the optional component comes *earlier* than the # fixed component in the sequence. case ext_values.length when 2 {"oid" => ext_values[0].value, "value" => value} when 3 {"oid" => ext_values[0].value, "value" => value, "critical" => ext_values[1].value} else raise Puppet::Error, _("In %{attr}, expected extension record %{index} to have two or three items, but found %{count}") % { attr: attribute.oid, index: index, count: ext_values.length } end end end |
#subject_alt_names ⇒ Object
181 182 183 184 185 186 187 188 |
# File 'lib/puppet/ssl/certificate_request.rb', line 181 def subject_alt_names @subject_alt_names ||= request_extensions. select {|x| x["oid"] == "subjectAltName" }. map {|x| x["value"].split(/\s*,\s*/) }. flatten. sort. uniq end |