James -- you may already be onto this, but one thing I found last time I did a home-rolled PKI (attempting chained CA certs for puppet) was that the CA needs to be explicitly configured to accept extended attributes from the CSR and put them into the issued certificate. This is controlled by the 'copy_extensions' option in the openssl ca config, but I'm not sure how that wends its way down into libcrypto or the ruby openssl bindings.
HTH from a fellow ssl hair-puller. -=Eric On Jun 29, 2011, at 5:54 PM, James Turnbull wrote: > This adds the ability to add arbitrary attributes to Puppet certificate > requests. It is controlled by setting the allow_csr_attributes setting > in the puppet.conf configuration file on the Puppet agent. > > allow_csr_attributes = true > > This option defaults to false. If set to true it looks for a YAML file, > csrattributes.yaml, located by default in /etc/puppet but location is > controllable via the csr_attributes_file option in puppet.conf. > > Inside this file you can speicfy a list of OIDs and values in the form > of a YAML hash, for example: > > --- > 1.3.6.1.4.1.34380.2.1: 'attrval1' > 1.3.6.1.4.1.34380.2.2: 'attrval2' > > When the Puppet CSR is generated these values will be added to the CSR > that is passed to the Puppet master. You can then inspect them using: > > openssl req -in name.of.csr.file.pem -noout -text > > This will return the detailed certificate request and you should see in > the attributes section: > > Attributes: > testoid1 :unable to print attribute > testoid2 :unable to print attribute > > This is entirely prototype code and I've fixed any tests broken by its > introduction but not added any new tests. > > This patch also adds the contents of certdnsnames to the CSR being generated > on the Puppet agent as Extensions. > > Signed-off-by: James Turnbull <[email protected]> > --- > Local-branch: tickets/master/7243 > lib/puppet/defaults.rb | 4 +++ > lib/puppet/ssl/certificate_request.rb | 36 +++++++++++++++++++++++++++++ > spec/unit/ssl/certificate_request_spec.rb | 2 + > 3 files changed, 42 insertions(+), 0 deletions(-) > > diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb > index 07442d0..ff4eb8a 100644 > --- a/lib/puppet/defaults.rb > +++ b/lib/puppet/defaults.rb > @@ -354,6 +354,10 @@ module Puppet > autosigns any key request, and is a very bad idea), false (which > never autosigns any key request), and the path to a file, which > uses that configuration file to determine which keys to sign."}, > + :allow_csr_attributes => [false, "Whether to allow CSR attributes."], > + :csr_attributes_file => { :default => "$confdir/csrattributes.yaml", > + :mode => 0644, > + :desc => "YAML File to hold any attributes that should be added to the > CSR."}, > :allow_duplicate_certs => [false, "Whether to allow a new certificate > request to overwrite an existing certificate."], > :ca_days => ["", "How long a certificate should be valid. > diff --git a/lib/puppet/ssl/certificate_request.rb > b/lib/puppet/ssl/certificate_request.rb > index 8c83339..4ae7f56 100644 > --- a/lib/puppet/ssl/certificate_request.rb > +++ b/lib/puppet/ssl/certificate_request.rb > @@ -51,6 +51,42 @@ class Puppet::SSL::CertificateRequest < Puppet::SSL::Base > csr.version = 0 > csr.subject = OpenSSL::X509::Name.new([["CN", common_name]]) > csr.public_key = key.public_key > + > + dnsnames = Puppet[:certdnsnames] > + subject_alt_name = [] > + if dnsnames != "" > + dnsnames.split(':').each { |d| subject_alt_name << 'DNS:' + d } > + end > + subject_alt_name << 'DNS:' + Facter["fqdn"].value > + > + ef = OpenSSL::X509::ExtensionFactory.new > + > + names = subject_alt_name.collect{|e| > ef.create_extension("subjectAltName", e, "false") } > + names = OpenSSL::ASN1::Set([OpenSSL::ASN1::Sequence(names)]) > + > + attrs = [ > + OpenSSL::X509::Attribute.new("extReq", names), > + OpenSSL::X509::Attribute.new("msExtReq", names), > + ] > + > + attrs.each{|attr| csr.add_attribute(attr) } > + > + if Puppet[:allow_csr_attributes] > + @csrattributes = Puppet[:csr_attributes_file] > + unless FileTest.exists?(@csrattributes) > + fail "CSR attributes are enabled but #{@csrattributes} is missing" > + else > + extensions = YAML.load_file(@csrattributes).to_a > + end > + attributes = [] > + extensions.each { |e| > + oid = e[0] > + value = OpenSSL::ASN1::Set([OpenSSL::ASN1::Sequence(e[1])]) > + attributes << OpenSSL::X509::Attribute.new(oid, value) > + } > + attributes.each{ |attr| csr.add_attribute(attr) } > + end > + > csr.sign(key, OpenSSL::Digest::MD5.new) > > raise Puppet::Error, "CSR sign verification failed; you need to clean the > certificate request for #{name} on the server" unless > csr.verify(key.public_key) > diff --git a/spec/unit/ssl/certificate_request_spec.rb > b/spec/unit/ssl/certificate_request_spec.rb > index e45f013..e616c76 100755 > --- a/spec/unit/ssl/certificate_request_spec.rb > +++ b/spec/unit/ssl/certificate_request_spec.rb > @@ -126,6 +126,8 @@ describe Puppet::SSL::CertificateRequest do > it "should set the CN to the :ca_name setting when the CSR is for a CA" do > subject = mock 'subject' > Puppet.settings.expects(:value).with(:ca_name).returns "mycertname" > + Puppet.settings.expects(:value).with(:allow_csr_attributes).returns > false > + Puppet.settings.expects(:value).with(:certdnsnames).returns > "othercertname" > OpenSSL::X509::Name.expects(:new).with { |subject| subject[0][1] == > "mycertname" }.returns(subject) > @request.expects(:subject=).with(subject) > Puppet::SSL::CertificateRequest.new(Puppet::SSL::CA_NAME).generate(@key) > -- > 1.7.4.1 > > -- > You received this message because you are subscribed to the Google Groups > "Puppet Developers" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]. > For more options, visit this group at > http://groups.google.com/group/puppet-dev?hl=en. > - Eric Sorenson - N37 17.255 W121 55.738 - http://twitter.com/ahpook - -- You received this message because you are subscribed to the Google Groups "Puppet Developers" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/puppet-dev?hl=en.
