Matt Wise
2011-Apr-26 02:10 UTC
[Puppet Users] Custom data embedded in Puppet SSL Certs...
I''m working out some security issues here and wanted to throw something out there... I''ll be digging in tonight to see whether something like this is possible, so I''d appreciate feedback quickly if anyone happens to know if this is possible. Imagine a scenario where our individual hosts actually tell the puppet server which ''config'' they want. This is our environment, and its not changeable. (The short explanation — its done this way because we provision nodes in several clouds where hostnames are not known until after a host has booted). For now, our nodes actually check in and say "I want XYZ class". I''d like to have our nodes able to do this ONCE ... only when they generate their CSR. After that, I''d like their ''base_class'' to be embedded in the CSR (And subsequently the CERT), so that a client cannot later change its mind about what kind of host it is. Essentially I''m thinking the process would be something like this: Client: -) fill in ''base_class'' somewhere (puppet.conf?) -) run puppet... host generates private key, and csr, and submits it to the puppet ca master Server: -) process signs CSR and provides Cert back to host (this is automated in our case, but not with autosign.conf) Client: -) begin actual puppet run.. request real configuration Server: -) read ''base_class'' from certificate, and fill in $base_class with that data .. Thoughts? Any ideas on a good way to work this out? (my alternative method is going to involve a back-end Amazon SimpleDB script that dumps a nodes base_class into the database the first time ti runs, and then forever-after pulls from SimpleDB to fill in the base_class variable. I dont like this though, as its slow and it adds another service dependency.) -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
Jeff McCune
2011-Apr-26 09:54 UTC
Re: [Puppet Users] Custom data embedded in Puppet SSL Certs...
On Tue, Apr 26, 2011 at 4:10 AM, Matt Wise <wise@wiredgeek.net> wrote:> I''m working out some security issues here and wanted to throw something out there... I''ll be digging in tonight to see whether something like this is possible, so I''d appreciate feedback quickly if anyone happens to know if this is possible. Imagine a scenario where our individual hosts actually tell the puppet server which ''config'' they want. This is our environment, and its not changeable. (The short explanation — its done this way because we provision nodes in several clouds where hostnames are not known until after a host has booted). For now, our nodes actually check in and say "I want XYZ class". > > I''d like to have our nodes able to do this ONCE ... only when they generate their CSR. After that, I''d like their ''base_class'' to be embedded in the CSR (And subsequently the CERT), so that a client cannot later change its mind about what kind of host it is. Essentially I''m thinking the process would be something like this: > > Client: > -) fill in ''base_class'' somewhere (puppet.conf?) > -) run puppet... host generates private key, and csr, and submits it to the puppet ca master > > Server: > -) process signs CSR and provides Cert back to host (this is automated in our case, but not with autosign.conf) > > Client: > -) begin actual puppet run.. request real configuration > > Server: > -) read ''base_class'' from certificate, and fill in $base_class with that data .. > > > Thoughts? Any ideas on a good way to work this out?This feels like quite a hack, but I agree with you there''s no really good way for Puppet to do this today. The agent can set the environment (puppet environment) it wants, but that doesn''t really give you what you want. I would normally accomplish this using a custom fact, but you mentioned this is security related so I see the desire to get the base class embedded into the certificate data. Practically speaking, the certificate cannot be forged once signed. You can easily change the certificate name in the request using: puppet agent --certname=my_base_class But! You''re going to run into duplicate certificate names, which will be a pain to manage. Better instead, you could prefix each certificate name with the FQDN, or some other unique identifier and a character not valid for DNS hostnames: puppet agent --certname="$(facter fqdn)::my_base_class" You can then match against this in your puppet manifests or your External Node Classifier by splitting out the string to the right of the double colons. Hope this helps, -- Jeff McCune Professional Services, Puppet Labs @0xEFF -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
Matt Wise
2011-Apr-26 13:50 UTC
Re: [Puppet Users] Custom data embedded in Puppet SSL Certs...
:) This is most definitely a hack. The issue is that once you start using Puppet to push out secure-data that HostA might need, but HostB should never be able to get — you run into this problem. If HostB is broken into and its ''node type'' is changed (whether by hostname, or editing a custom puppet fact), it can suddenly get data for HostA. I am actually thinking that the ''Subject Alternative Name'' may be the best place for this kind of data — but I''m wondering whether theres any place in Puppet where I an implement a hack that allows puppet to parse through these fields and determine if they''re valid. IE, perhaps in auth.conf? Or maybe theres a way to use a ''prerun'' command in puppet.conf that I can feed the clients certificate to? Any thoughts there? —Matt On Apr 26, 2011, at 2:54 AM, Jeff McCune wrote:> On Tue, Apr 26, 2011 at 4:10 AM, Matt Wise <wise@wiredgeek.net> wrote: >> I''m working out some security issues here and wanted to throw something out there... I''ll be digging in tonight to see whether something like this is possible, so I''d appreciate feedback quickly if anyone happens to know if this is possible. Imagine a scenario where our individual hosts actually tell the puppet server which ''config'' they want. This is our environment, and its not changeable. (The short explanation — its done this way because we provision nodes in several clouds where hostnames are not known until after a host has booted). For now, our nodes actually check in and say "I want XYZ class". >> >> I''d like to have our nodes able to do this ONCE ... only when they generate their CSR. After that, I''d like their ''base_class'' to be embedded in the CSR (And subsequently the CERT), so that a client cannot later change its mind about what kind of host it is. Essentially I''m thinking the process would be something like this: >> >> Client: >> -) fill in ''base_class'' somewhere (puppet.conf?) >> -) run puppet... host generates private key, and csr, and submits it to the puppet ca master >> >> Server: >> -) process signs CSR and provides Cert back to host (this is automated in our case, but not with autosign.conf) >> >> Client: >> -) begin actual puppet run.. request real configuration >> >> Server: >> -) read ''base_class'' from certificate, and fill in $base_class with that data .. >> >> >> Thoughts? Any ideas on a good way to work this out? > > > This feels like quite a hack, but I agree with you there''s no really > good way for Puppet to do this today. The agent can set the > environment (puppet environment) it wants, but that doesn''t really > give you what you want. > > I would normally accomplish this using a custom fact, but you > mentioned this is security related so I see the desire to get the base > class embedded into the certificate data. Practically speaking, the > certificate cannot be forged once signed. > > You can easily change the certificate name in the request using: > > puppet agent --certname=my_base_class > > But! You''re going to run into duplicate certificate names, which will > be a pain to manage. Better instead, you could prefix each > certificate name with the FQDN, or some other unique identifier and a > character not valid for DNS hostnames: > > puppet agent --certname="$(facter fqdn)::my_base_class" > > You can then match against this in your puppet manifests or your > External Node Classifier by splitting out the string to the right of > the double colons. > > Hope this helps, > -- > Jeff McCune > Professional Services, Puppet Labs > @0xEFF > > -- > You received this message because you are subscribed to the Google Groups "Puppet Users" group. > To post to this group, send email to puppet-users@googlegroups.com. > To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. > For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en. >-- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
Matt Wise
2011-Apr-26 16:00 UTC
Re: [Puppet Users] Custom data embedded in Puppet SSL Certs...
Ok, spoke with Jeff a bit on IRC about this. Part of this problem is easy it turns out. You can add ''+ExportCertData'' to the SSLOptions in Apache which will pass the CERT in PEM format to Puppet for each client when they connect. You can then do a custom node classifier that reads this data and does something intelligent. Again, easy. The hard part it turns out is getting some custom data into the SSL cert to begin with. The CSR thats generated does not get generated with ''certdnsnames'' embedded in it, thats done purely on the Signing side (aka, your puppet ca). I had hoped I could set ''certdnsnames'' on the client and that would be passed to the server in some way, but its not. I''m pretty sure at this point that some puppet code will need to change for this to work. I''ll be submitting a puppet feature request for this in a few minutes.. —Matt On Apr 26, 2011, at 6:50 AM, Matt Wise wrote:> :) This is most definitely a hack. The issue is that once you start using Puppet to push out secure-data that HostA might need, but HostB should never be able to get — you run into this problem. If HostB is broken into and its ''node type'' is changed (whether by hostname, or editing a custom puppet fact), it can suddenly get data for HostA. > > I am actually thinking that the ''Subject Alternative Name'' may be the best place for this kind of data — but I''m wondering whether theres any place in Puppet where I an implement a hack that allows puppet to parse through these fields and determine if they''re valid. IE, perhaps in auth.conf? Or maybe theres a way to use a ''prerun'' command in puppet.conf that I can feed the clients certificate to? Any thoughts there? > > —Matt > > On Apr 26, 2011, at 2:54 AM, Jeff McCune wrote: > >> On Tue, Apr 26, 2011 at 4:10 AM, Matt Wise <wise@wiredgeek.net> wrote: >>> I''m working out some security issues here and wanted to throw something out there... I''ll be digging in tonight to see whether something like this is possible, so I''d appreciate feedback quickly if anyone happens to know if this is possible. Imagine a scenario where our individual hosts actually tell the puppet server which ''config'' they want. This is our environment, and its not changeable. (The short explanation — its done this way because we provision nodes in several clouds where hostnames are not known until after a host has booted). For now, our nodes actually check in and say "I want XYZ class". >>> >>> I''d like to have our nodes able to do this ONCE ... only when they generate their CSR. After that, I''d like their ''base_class'' to be embedded in the CSR (And subsequently the CERT), so that a client cannot later change its mind about what kind of host it is. Essentially I''m thinking the process would be something like this: >>> >>> Client: >>> -) fill in ''base_class'' somewhere (puppet.conf?) >>> -) run puppet... host generates private key, and csr, and submits it to the puppet ca master >>> >>> Server: >>> -) process signs CSR and provides Cert back to host (this is automated in our case, but not with autosign.conf) >>> >>> Client: >>> -) begin actual puppet run.. request real configuration >>> >>> Server: >>> -) read ''base_class'' from certificate, and fill in $base_class with that data .. >>> >>> >>> Thoughts? Any ideas on a good way to work this out? >> >> >> This feels like quite a hack, but I agree with you there''s no really >> good way for Puppet to do this today. The agent can set the >> environment (puppet environment) it wants, but that doesn''t really >> give you what you want. >> >> I would normally accomplish this using a custom fact, but you >> mentioned this is security related so I see the desire to get the base >> class embedded into the certificate data. Practically speaking, the >> certificate cannot be forged once signed. >> >> You can easily change the certificate name in the request using: >> >> puppet agent --certname=my_base_class >> >> But! You''re going to run into duplicate certificate names, which will >> be a pain to manage. Better instead, you could prefix each >> certificate name with the FQDN, or some other unique identifier and a >> character not valid for DNS hostnames: >> >> puppet agent --certname="$(facter fqdn)::my_base_class" >> >> You can then match against this in your puppet manifests or your >> External Node Classifier by splitting out the string to the right of >> the double colons. >> >> Hope this helps, >> -- >> Jeff McCune >> Professional Services, Puppet Labs >> @0xEFF >> >> -- >> You received this message because you are subscribed to the Google Groups "Puppet Users" group. >> To post to this group, send email to puppet-users@googlegroups.com. >> To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. >> For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en. >> >-- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
Nan Liu
2011-Apr-26 16:25 UTC
Re: [Puppet Users] Custom data embedded in Puppet SSL Certs...
Why embed this in the cert, rather than custom facts? Your second requirement is interesting, on one hand the client can set the class info as part of the certificate, on the other hand you doesn''t want the client to change it afterwards. I would suggest client submit the list of classes as a custom fact, and serverside override so once the setting is obtained the client can not override the value. So if the server doesn''t have the class info matching the CN, store the initial class info from client facts into a server location (db, file) that can be retrieved later via enc, extlookup. So something along the line of # server_class is obtained either from ENC or extlookup which is based on client certificate name. if $server_class { $base_class = $server_class } else { # client_class is a custom function, and can be as simply as FACTER_client_class environment variable. $base_class = $client_class # write a custom function to store the client_class to either the extlookup or ENC location. store($client_class, $certname) } If you need to allow the client to client set it later on, you can either manually update the server side settings or just write a wrapper for puppet cert --clean that will remove the ENC or extlookup data for this client. Thanks, Nan On Tue, Apr 26, 2011 at 9:00 AM, Matt Wise <wise@wiredgeek.net> wrote:> Ok, spoke with Jeff a bit on IRC about this. Part of this problem is easy it turns out. You can add ''+ExportCertData'' to the SSLOptions in Apache which will pass the CERT in PEM format to Puppet for each client when they connect. You can then do a custom node classifier that reads this data and does something intelligent. Again, easy. > > The hard part it turns out is getting some custom data into the SSL cert to begin with. The CSR thats generated does not get generated with ''certdnsnames'' embedded in it, thats done purely on the Signing side (aka, your puppet ca). I had hoped I could set ''certdnsnames'' on the client and that would be passed to the server in some way, but its not. > > I''m pretty sure at this point that some puppet code will need to change for this to work. I''ll be submitting a puppet feature request for this in a few minutes.. > > —Matt > > > On Apr 26, 2011, at 6:50 AM, Matt Wise wrote: > >> :) This is most definitely a hack. The issue is that once you start using Puppet to push out secure-data that HostA might need, but HostB should never be able to get — you run into this problem. If HostB is broken into and its ''node type'' is changed (whether by hostname, or editing a custom puppet fact), it can suddenly get data for HostA. >> >> I am actually thinking that the ''Subject Alternative Name'' may be the best place for this kind of data — but I''m wondering whether theres any place in Puppet where I an implement a hack that allows puppet to parse through these fields and determine if they''re valid. IE, perhaps in auth.conf? Or maybe theres a way to use a ''prerun'' command in puppet.conf that I can feed the clients certificate to? Any thoughts there? >> >> —Matt >> >> On Apr 26, 2011, at 2:54 AM, Jeff McCune wrote: >> >>> On Tue, Apr 26, 2011 at 4:10 AM, Matt Wise <wise@wiredgeek.net> wrote: >>>> I''m working out some security issues here and wanted to throw something out there... I''ll be digging in tonight to see whether something like this is possible, so I''d appreciate feedback quickly if anyone happens to know if this is possible. Imagine a scenario where our individual hosts actually tell the puppet server which ''config'' they want. This is our environment, and its not changeable. (The short explanation — its done this way because we provision nodes in several clouds where hostnames are not known until after a host has booted). For now, our nodes actually check in and say "I want XYZ class". >>>> >>>> I''d like to have our nodes able to do this ONCE ... only when they generate their CSR. After that, I''d like their ''base_class'' to be embedded in the CSR (And subsequently the CERT), so that a client cannot later change its mind about what kind of host it is. Essentially I''m thinking the process would be something like this: >>>> >>>> Client: >>>> -) fill in ''base_class'' somewhere (puppet.conf?) >>>> -) run puppet... host generates private key, and csr, and submits it to the puppet ca master >>>> >>>> Server: >>>> -) process signs CSR and provides Cert back to host (this is automated in our case, but not with autosign.conf) >>>> >>>> Client: >>>> -) begin actual puppet run.. request real configuration >>>> >>>> Server: >>>> -) read ''base_class'' from certificate, and fill in $base_class with that data .. >>>> >>>> >>>> Thoughts? Any ideas on a good way to work this out? >>> >>> >>> This feels like quite a hack, but I agree with you there''s no really >>> good way for Puppet to do this today. The agent can set the >>> environment (puppet environment) it wants, but that doesn''t really >>> give you what you want. >>> >>> I would normally accomplish this using a custom fact, but you >>> mentioned this is security related so I see the desire to get the base >>> class embedded into the certificate data. Practically speaking, the >>> certificate cannot be forged once signed. >>> >>> You can easily change the certificate name in the request using: >>> >>> puppet agent --certname=my_base_class >>> >>> But! You''re going to run into duplicate certificate names, which will >>> be a pain to manage. Better instead, you could prefix each >>> certificate name with the FQDN, or some other unique identifier and a >>> character not valid for DNS hostnames: >>> >>> puppet agent --certname="$(facter fqdn)::my_base_class" >>> >>> You can then match against this in your puppet manifests or your >>> External Node Classifier by splitting out the string to the right of >>> the double colons. >>> >>> Hope this helps, >>> -- >>> Jeff McCune >>> Professional Services, Puppet Labs >>> @0xEFF >>> >>> -- >>> You received this message because you are subscribed to the Google Groups "Puppet Users" group. >>> To post to this group, send email to puppet-users@googlegroups.com. >>> To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. >>> For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en. >>> >> > > -- > You received this message because you are subscribed to the Google Groups "Puppet Users" group. > To post to this group, send email to puppet-users@googlegroups.com. > To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. > For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en. > >-- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
Matt Wise
2011-Apr-26 16:39 UTC
Re: [Puppet Users] Custom data embedded in Puppet SSL Certs...
Nan, You''re going down the same line of thought I had as an alternative to embedding it in the Cert itself. The reason to embed it in the cert is that you avoid having all of the "if its not here, go check there" code. You don''t need to maintain a database with this data either. In our case we have many puppet masters behind a load balancer, so we ''d have to leverage a database to hold the data, or risk having each of our puppet servers have different data on them about our nodes. If it turns out that the cert-side of the fix will take too long to implement (bug #7243), then we may go down that path anyways.. but I like the idea of the data being locked into the CSR and subsequently the Cert itself, as its exceedingly hard to change after that. This also opens up the door for people to add custom authentication data into their certs for their environments... maybe checks against some custom Unique identifier of hardware, or something else along those lines to validate that the server is truly allowed to connect in to puppet. FWIW, its because we leverage puppet over the internet to manage cloud systems that we really care about this. Had we just been managing internal networked systems, this may not be such a big deal. The benefits here though are pretty obvious I think... PS, I''ve also submitted bug 7244 — requesting that the ''autosign'' code be extended to allow for external ''autosign classifiers''. This would allow autosigning to work and for the puppet implementors to determine what mechanism they want to use to allow or disallow an autosigned SSL cert. In our case we''ve written our own mechanism around this, but we''d love to move it into something more "supported". —Matt On Apr 26, 2011, at 9:25 AM, Nan Liu wrote:> Why embed this in the cert, rather than custom facts? Your second > requirement is interesting, on one hand the client can set the class > info as part of the certificate, on the other hand you doesn''t want > the client to change it afterwards. > > I would suggest client submit the list of classes as a custom fact, > and serverside override so once the setting is obtained the client can > not override the value. So if the server doesn''t have the class info > matching the CN, store the initial class info from client facts into a > server location (db, file) that can be retrieved later via enc, > extlookup. > > So something along the line of > > # server_class is obtained either from ENC or extlookup which is based > on client certificate name. > if $server_class { > $base_class = $server_class > } else { > # client_class is a custom function, and can be as simply as > FACTER_client_class environment variable. > $base_class = $client_class > # write a custom function to store the client_class to either the > extlookup or ENC location. > store($client_class, $certname) > } > > If you need to allow the client to client set it later on, you can > either manually update the server side settings or just write a > wrapper for puppet cert --clean that will remove the ENC or extlookup > data for this client. > > Thanks, > > Nan > > On Tue, Apr 26, 2011 at 9:00 AM, Matt Wise <wise@wiredgeek.net> wrote: >> Ok, spoke with Jeff a bit on IRC about this. Part of this problem is easy it turns out. You can add ''+ExportCertData'' to the SSLOptions in Apache which will pass the CERT in PEM format to Puppet for each client when they connect. You can then do a custom node classifier that reads this data and does something intelligent. Again, easy. >> >> The hard part it turns out is getting some custom data into the SSL cert to begin with. The CSR thats generated does not get generated with ''certdnsnames'' embedded in it, thats done purely on the Signing side (aka, your puppet ca). I had hoped I could set ''certdnsnames'' on the client and that would be passed to the server in some way, but its not. >> >> I''m pretty sure at this point that some puppet code will need to change for this to work. I''ll be submitting a puppet feature request for this in a few minutes.. >> >> —Matt >> >> >> On Apr 26, 2011, at 6:50 AM, Matt Wise wrote: >> >>> :) This is most definitely a hack. The issue is that once you start using Puppet to push out secure-data that HostA might need, but HostB should never be able to get — you run into this problem. If HostB is broken into and its ''node type'' is changed (whether by hostname, or editing a custom puppet fact), it can suddenly get data for HostA. >>> >>> I am actually thinking that the ''Subject Alternative Name'' may be the best place for this kind of data — but I''m wondering whether theres any place in Puppet where I an implement a hack that allows puppet to parse through these fields and determine if they''re valid. IE, perhaps in auth.conf? Or maybe theres a way to use a ''prerun'' command in puppet.conf that I can feed the clients certificate to? Any thoughts there? >>> >>> —Matt >>> >>> On Apr 26, 2011, at 2:54 AM, Jeff McCune wrote: >>> >>>> On Tue, Apr 26, 2011 at 4:10 AM, Matt Wise <wise@wiredgeek.net> wrote: >>>>> I''m working out some security issues here and wanted to throw something out there... I''ll be digging in tonight to see whether something like this is possible, so I''d appreciate feedback quickly if anyone happens to know if this is possible. Imagine a scenario where our individual hosts actually tell the puppet server which ''config'' they want. This is our environment, and its not changeable. (The short explanation — its done this way because we provision nodes in several clouds where hostnames are not known until after a host has booted). For now, our nodes actually check in and say "I want XYZ class". >>>>> >>>>> I''d like to have our nodes able to do this ONCE ... only when they generate their CSR. After that, I''d like their ''base_class'' to be embedded in the CSR (And subsequently the CERT), so that a client cannot later change its mind about what kind of host it is. Essentially I''m thinking the process would be something like this: >>>>> >>>>> Client: >>>>> -) fill in ''base_class'' somewhere (puppet.conf?) >>>>> -) run puppet... host generates private key, and csr, and submits it to the puppet ca master >>>>> >>>>> Server: >>>>> -) process signs CSR and provides Cert back to host (this is automated in our case, but not with autosign.conf) >>>>> >>>>> Client: >>>>> -) begin actual puppet run.. request real configuration >>>>> >>>>> Server: >>>>> -) read ''base_class'' from certificate, and fill in $base_class with that data .. >>>>> >>>>> >>>>> Thoughts? Any ideas on a good way to work this out? >>>> >>>> >>>> This feels like quite a hack, but I agree with you there''s no really >>>> good way for Puppet to do this today. The agent can set the >>>> environment (puppet environment) it wants, but that doesn''t really >>>> give you what you want. >>>> >>>> I would normally accomplish this using a custom fact, but you >>>> mentioned this is security related so I see the desire to get the base >>>> class embedded into the certificate data. Practically speaking, the >>>> certificate cannot be forged once signed. >>>> >>>> You can easily change the certificate name in the request using: >>>> >>>> puppet agent --certname=my_base_class >>>> >>>> But! You''re going to run into duplicate certificate names, which will >>>> be a pain to manage. Better instead, you could prefix each >>>> certificate name with the FQDN, or some other unique identifier and a >>>> character not valid for DNS hostnames: >>>> >>>> puppet agent --certname="$(facter fqdn)::my_base_class" >>>> >>>> You can then match against this in your puppet manifests or your >>>> External Node Classifier by splitting out the string to the right of >>>> the double colons. >>>> >>>> Hope this helps, >>>> -- >>>> Jeff McCune >>>> Professional Services, Puppet Labs >>>> @0xEFF >>>> >>>> -- >>>> You received this message because you are subscribed to the Google Groups "Puppet Users" group. >>>> To post to this group, send email to puppet-users@googlegroups.com. >>>> To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. >>>> For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en. >>>> >>> >> >> -- >> You received this message because you are subscribed to the Google Groups "Puppet Users" group. >> To post to this group, send email to puppet-users@googlegroups.com. >> To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. >> For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en. >> >> > > -- > You received this message because you are subscribed to the Google Groups "Puppet Users" group. > To post to this group, send email to puppet-users@googlegroups.com. > To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. > For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en. >-- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
Jacob Helwig
2011-Apr-26 16:53 UTC
Re: [Puppet Users] Custom data embedded in Puppet SSL Certs...
On Mon, 25 Apr 2011 19:10:35 -0700, Matt Wise wrote:> > I''m working out some security issues here and wanted to throw > something out there... I''ll be digging in tonight to see whether > something like this is possible, so I''d appreciate feedback quickly if > anyone happens to know if this is possible. Imagine a scenario where > our individual hosts actually tell the puppet server which ''config'' > they want. This is our environment, and its not changeable. (The short > explanation — its done this way because we provision nodes in several > clouds where hostnames are not known until after a host has booted). > For now, our nodes actually check in and say "I want XYZ class". > > I''d like to have our nodes able to do this ONCE ... only when they > generate their CSR. After that, I''d like their ''base_class'' to be > embedded in the CSR (And subsequently the CERT), so that a client > cannot later change its mind about what kind of host it is. > Essentially I''m thinking the process would be something like this: > > Client: > -) fill in ''base_class'' somewhere (puppet.conf?) > -) run puppet... host generates private key, and csr, and submits it to the puppet ca master > > Server: > -) process signs CSR and provides Cert back to host (this is automated in our case, but not with autosign.conf) > > Client: > -) begin actual puppet run.. request real configuration > > Server: > -) read ''base_class'' from certificate, and fill in $base_class with that data .. > > > Thoughts? Any ideas on a good way to work this out? > > (my alternative method is going to involve a back-end Amazon SimpleDB > script that dumps a nodes base_class into the database the first time > ti runs, and then forever-after pulls from SimpleDB to fill in the > base_class variable. I dont like this though, as its slow and it adds > another service dependency.) > >I know you''ve stated that this is your configuration, and it''s not changeable, but I''m still confused about what lead you to this setup. I assume that you can "trust" the puppet master(s). Given that you can generate certificates for arbitrary cert names, how does not knowing the host name of a node until after it boots matter? It seems like just generating cert names that weren''t the same as the host name would give you all the security you''re looking for, and would solve the classification problem since the ''node name'' would be known before-hand (manifests match on cert name not host name, they''re just usually the same). Is there something about the provisioning process that prevents pre-generating the certs, and placing the cert & an appropriate puppet.conf on the machine before first boot? (This would definitely explain why this approach would be un-workable.) -- Jacob Helwig
David Rocamora
2011-Apr-26 17:41 UTC
Re: [Puppet Users] Custom data embedded in Puppet SSL Certs...
On Tue, Apr 26, 2011 at 12:39 PM, Matt Wise <wise@wiredgeek.net> wrote:> > > FWIW, its because we leverage puppet over the internet to manage cloud > systems that we really care about this. Had we just been managing internal > networked systems, this may not be such a big deal. The benefits here though > are pretty obvious I think... > >Hey Matt, When we were looking to expand our Puppet installation to cover cloud based machines, we experimented with some things around this. When we sat down and discovered what it would take to get this to happen reliably and consistently we determined it would create too much complexity. To us, it just created a situation where there were too many things that could fail. We opted for a different kind of approach that distributes a copy of our Puppet repository to new instances and they configure themselves without using a centralized Puppetmaster. Our machines only get puppetized when they start up. Since we''re deploying in the cloud we find it easier to just create a new machine with an upgraded configuration and then destroy the old one. We do have to be careful about controlling state on individual instances, but we are already doing this because we assume that any instance can disappear at anytime. It sounds like security is a big part of the reason you are looking to do this. In a Puppetmasterless environment like ours, we handle security by removing as much sensitive information from our Puppet repository as possible and restricting sensitive information in instance specific data. On top of this we can tell our instances to destroy as much of their local repository and instance specific data as possible when they are done being configured. This limits what an attacker can gain from one of our computers. I don''t really have much to comment on adding custom data in the certs. It seems like it would add a lot of complexity that could bite you when you really need it to work. As someone that was in this same position before, I thought I would let you know how we solved the problem by changing the way we configured the machines. I put up a blog post<http://blog.controlgroup.com/2011/04/25/configuring-machines-in-the-cloud-our-approach/>about this the other day that may shed some more light on how we implemented this. If you do decide to go down the custom data in the certs path I would like to hear more about how you make that work. HTH, Dave * * *David Rocamora* | VP DevOps | *CONTROL GROUP* | 233 Broadway | 21st Floor | New York, NY 10279 | www.controlgroup.com -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
Nigel Kersten
2011-Apr-26 19:10 UTC
Re: [Puppet Users] Custom data embedded in Puppet SSL Certs...
On Tue, Apr 26, 2011 at 4:10 AM, Matt Wise <wise@wiredgeek.net> wrote:> > I''d like to have our nodes able to do this ONCE ... only when they generate > their CSR. After that, I''d like their ''base_class'' to be embedded in the CSR > (And subsequently the CERT), so that a client cannot later change its mind > about what kind of host it is.Are you primarily concerned with clients using the correct class by default or protecting information in classes so that only specific hosts can access it? -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
Kristof Willaert
2011-Apr-26 21:57 UTC
Re: [Puppet Users] Custom data embedded in Puppet SSL Certs...
[snip] The hard part it turns out is getting some custom data into the SSL cert to> begin with. The CSR thats generated does not get generated with > ''certdnsnames'' embedded in it, thats done purely on the Signing side (aka, > your puppet ca). I had hoped I could set ''certdnsnames'' on the client and > that would be passed to the server in some way, but its not. >I think I might have a solution for this problem: Instead of using the Puppet CA functionality in Puppet, I created a simple CA using just OpenSSL. So both a puppet client and a puppetmaster get a cert that is signed by this CA (the only thing you need to do in the puppet.conf of the puppetmaster is put ca=false in before you start it the first time). That way, I can distribute "pre-signed" certificates to my puppet clients and puppetmasters. This also means that you can simply embed a custom "subjectAltname" directive in the openssl.conf file used to sign the client cert. Below the relevant parts of my openssl.conf: x509_extensions = usr_cert [ usr_cert ] basicConstraints = critical, CA:FALSE keyUsage = digitalSignature, keyEncipherment extendedKeyUsage = serverAuth, clientAuth, emailProtection subjectKeyIdentifier = hash subjectAltname = <your custom class> The reason I work like this: I use a custom JeOS ISO to install my machines, which contains a host specific RPM/DEB containing the certs for that client. This way, I can easily reprovision the machine, let it automatically connect to the puppetmaster and get it configured, all fully automatic, and without the security concerns autosigning brings. Added bonus, using ISO''s instead of VM templates or something similar, is that ISO''s are perfectly agnostic of what virtual/physical infrastructure you have. kristof -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
Kristof Willaert
2011-Apr-26 22:01 UTC
Re: [Puppet Users] Custom data embedded in Puppet SSL Certs...
[snip] Below the relevant parts of my openssl.conf:> > x509_extensions = usr_cert > > [ usr_cert ] > basicConstraints = critical, CA:FALSE > keyUsage = digitalSignature, keyEncipherment > extendedKeyUsage = serverAuth, clientAuth, emailProtection > subjectKeyIdentifier = hash > subjectAltname = <your custom class> >Err, directive is called subjectAltNames ofcourse (getting late here ...) kristof -- You received this message because you are subscribed to the Google Groups "Puppet Users" group. To post to this group, send email to puppet-users@googlegroups.com. To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.