Hello I''m new to large scale puppet deployment and was hoping the list could offer some pointers on "module layout" My initial "layout" was motivated by a need to "harden" our Linux systems. I grouped the various hardening configs into: Kernel OS Network Shell Files Application I''m hoping I can create the same module structure within puppet. Using "sudo" as the first example, I want puppet to ensure "/usr/bin/ sudo" has "4111" file perms and "root:root" ownership. Directory layout: I used this handy script from "ProfFalken" http://www.threedrunkensysadsonthe.net/2010/04/quick-creation-of-puppet-modules/ BUT...this is where things are getting a little grey. I currently have: [root@laptop manifests]# pwd /etc/puppet/manifests [root@laptop manifests]# [root@laptop manifests]# tree os os |-- files |-- lib | |-- facter | `-- puppet | |-- parser | |-- provider | `-- type |-- manifests | |-- init.pp | `-- sudo.pp `-- templates 9 directories, 2 files [root@laptop manifests]# [root@laptop manifests]# cat os/manifests/sudo.pp # /etc/puppet/manifests/classes/sudo.pp class sudo { file { "/etc/sudoers": owner => "root", group => "root", mode => 4111, } } [root@laptop manifests]# Am I on the correct track? I''m guessing I should break the classes down into: sudo::perms sudo::ownership sudo::file (have puppet serve the sudo template) then in "os/manifests/site.pp" ..... would I import sudo? and the second question: How would I create hosts groups? I would like to group my hosts in "dev", "uat", "staging" and "prod" etc? Thanks Bruce -- 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.
One last question: Would the list suggest implementing "augeas" where possible? and would "augeas" fit into the "module layout" Thanks Bruce On Jun 18, 9:29 am, Bruce Bushby <bruce.bus...@gmail.com> wrote:> Hello > > I''m new to large scale puppet deployment and was hoping the list could > offer some pointers on "module layout" > > My initial "layout" was motivated by a need to "harden" our Linux > systems. I grouped the various hardening configs into: > > Kernel > OS > Network > Shell > Files > Application > > I''m hoping I can create the same module structure within puppet. > > Using "sudo" as the first example, I want puppet to ensure "/usr/bin/ > sudo" has "4111" file perms and "root:root" ownership. > > Directory layout: > I used this handy script from "ProfFalken"http://www.threedrunkensysadsonthe.net/2010/04/quick-creation-of-pupp... > > BUT...this is where things are getting a little grey. I currently > have: > > [root@laptop manifests]# pwd > /etc/puppet/manifests > [root@laptop manifests]# > [root@laptop manifests]# tree os > os > |-- files > |-- lib > | |-- facter > | `-- puppet > | |-- parser > | |-- provider > | `-- type > |-- manifests > | |-- init.pp > | `-- sudo.pp > `-- templates > > 9 directories, 2 files > [root@laptop manifests]# > [root@laptop manifests]# cat os/manifests/sudo.pp > # /etc/puppet/manifests/classes/sudo.pp > > class sudo { > file { "/etc/sudoers": > owner => "root", > group => "root", > mode => 4111, > }} > > [root@laptop manifests]# > > Am I on the correct track? > > I''m guessing I should break the classes down into: > sudo::perms > sudo::ownership > sudo::file (have puppet serve the sudo template) > > then in "os/manifests/site.pp" ..... would I import sudo? > > and the second question: How would I create hosts groups? I would like > to group my hosts in "dev", "uat", "staging" and "prod" etc? > > ThanksBruce-- 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.
> My initial "layout" was motivated by a need to "harden" our Linux > systems. I grouped the various hardening configs into: > > Kernel > OS > Network > Shell > Files > Application > > I''m hoping I can create the same module structure within puppet.Start here: http://docs.puppetlabs.com/guides/modules.html> Using "sudo" as the first example, I want puppet to ensure "/usr/bin/ > sudo" has "4111" file perms and "root:root" ownership. > > Directory layout: > I used this handy script from "ProfFalken" > http://www.threedrunkensysadsonthe.net/2010/04/quick-creation-of-puppet-modules/ > > BUT...this is where things are getting a little grey. I currently > have: > > [root@laptop manifests]# pwd > /etc/puppet/manifests > [root@laptop manifests]# > [root@laptop manifests]# tree os > os > |-- files > |-- lib > | |-- facter > | `-- puppet > | |-- parser > | |-- provider > | `-- type > |-- manifests > | |-- init.pp > | `-- sudo.pp > `-- templates > > 9 directories, 2 files > [root@laptop manifests]#You have your modules in /etc/puppet/manifests directory - which is probably not what you want. Modules should be located in something like /etc/puppet/modules as per instructions above.> [root@laptop manifests]# cat os/manifests/sudo.pp > # /etc/puppet/manifests/classes/sudo.pp > > class sudo { > file { "/etc/sudoers": > owner => "root", > group => "root", > mode => 4111, > } > } > [root@laptop manifests]# > > Am I on the correct track?Close. The class with the same name as the module should live in init.pp. So class sudo {} should be in: $MODULE_PATH/sudo/manifests/init.pp> I''m guessing I should break the classes down into: > sudo::perms > sudo::ownership > sudo::file (have puppet serve the sudo template)Far too fine grained probably :-). 1 class is enough to do all this ... depends on what you are trying to do. Don''t go crazy with organisation before you understand the language caveats. Start developing _something_ and see how your organisation works for you.> > then in "os/manifests/site.pp" ..... would I import sudo? >You ''include sudo'' or use the parameterized class syntax: class { "sudo": }> and the second question: How would I create hosts groups? I would like > to group my hosts in "dev", "uat", "staging" and "prod" etc?How do you identify these hosts now? I presume you have some DNS naming convention - this is generally what most people do ... they have a dns name such as: foo1.uat.mydomain.com And they identify the class of machine this way by using regsubst or inline_template to extract the ''uat'' or ''dev'' part out and use that as a variable. Otherwise ... you need to use node classification if your machines are not meaningfully named and identify them with your own knowledge of what the machines do: node roadwarrior.mydomain.com { $hostgroup = "uat" include somestuff } node donaldduck.mydomain.com { $hostgroup = "dev" include somestuff } class somestuff { case $hostgroup { "uat" : { # ... uat related stuff } "dev" : { # ... dev related stuff } } } ken. -- 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.
Augeas is a resource - I don''t see how it fits in as a module. You may _use_ it in your modules if you like. On Mon, Jun 20, 2011 at 12:09 PM, Bruce Bushby <bruce.bushby@gmail.com> wrote:> One last question: > > Would the list suggest implementing "augeas" where possible? and would > "augeas" fit into the "module layout" > > Thanks > Bruce > > > > > On Jun 18, 9:29 am, Bruce Bushby <bruce.bus...@gmail.com> wrote: >> Hello >> >> I''m new to large scale puppet deployment and was hoping the list could >> offer some pointers on "module layout" >> >> My initial "layout" was motivated by a need to "harden" our Linux >> systems. I grouped the various hardening configs into: >> >> Kernel >> OS >> Network >> Shell >> Files >> Application >> >> I''m hoping I can create the same module structure within puppet. >> >> Using "sudo" as the first example, I want puppet to ensure "/usr/bin/ >> sudo" has "4111" file perms and "root:root" ownership. >> >> Directory layout: >> I used this handy script from "ProfFalken"http://www.threedrunkensysadsonthe.net/2010/04/quick-creation-of-pupp... >> >> BUT...this is where things are getting a little grey. I currently >> have: >> >> [root@laptop manifests]# pwd >> /etc/puppet/manifests >> [root@laptop manifests]# >> [root@laptop manifests]# tree os >> os >> |-- files >> |-- lib >> | |-- facter >> | `-- puppet >> | |-- parser >> | |-- provider >> | `-- type >> |-- manifests >> | |-- init.pp >> | `-- sudo.pp >> `-- templates >> >> 9 directories, 2 files >> [root@laptop manifests]# >> [root@laptop manifests]# cat os/manifests/sudo.pp >> # /etc/puppet/manifests/classes/sudo.pp >> >> class sudo { >> file { "/etc/sudoers": >> owner => "root", >> group => "root", >> mode => 4111, >> }} >> >> [root@laptop manifests]# >> >> Am I on the correct track? >> >> I''m guessing I should break the classes down into: >> sudo::perms >> sudo::ownership >> sudo::file (have puppet serve the sudo template) >> >> then in "os/manifests/site.pp" ..... would I import sudo? >> >> and the second question: How would I create hosts groups? I would like >> to group my hosts in "dev", "uat", "staging" and "prod" etc? >> >> ThanksBruce > > -- > 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.
Thanks Ken.....I think I''m getting it....slowly :)> "...Start developing _something_ and see how your organisation works for you.."Right....I''ve started with the most basic setup to test CA keys by simply implementing file perms for /etc/sudoers I think my initial confusion was that I didn''t realize that when deploying "modules" ... you still need a "/etc/puppet/manifest/ site.pp" etc> "How do you identify these hosts now?"Some of the prod systems have "prod" in their hostname....but there are a lot that don''t confirm, thanks for the examples for "grouping" will give them a go. Getting back to my ultra simple setup, I''m finding that I can''t run "puppetd --test": [root@msukpuppet02 puppet]# puppetd --test err: Could not retrieve catalog from remote server: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed warning: Not using cache on failed catalog err: Could not retrieve catalog; skipping run [root@msukpuppet02 puppet]# HOWEVER...this works perfectly: [root@msukpuppet02 puppet]# puppetd --test -- server=msukpuppet01.mserv.local info: Caching catalog for msukpuppet02.mserv.local info: Applying configuration version ''1308583986'' notice: Finished catalog run in 0.02 seconds [root@msukpuppet02 puppet]# My puppet config file sits in "/etc/sysconfig/puppet" [root@msukpuppet02 puppet]# cat /etc/sysconfig/puppet # The puppetmaster server PUPPET_SERVER=msukpuppet01.mserv.local # If you wish to specify the port to connect to do so here PUPPET_PORT=8140 # Where to log to. Specify syslog to send log messages to the system log. PUPPET_LOG=/var/log/puppet/puppet.log # You may specify other parameters to the puppet client here PUPPET_EXTRA_OPTS=--waitforcert=500 [root@msukpuppet02 puppet]# I have checked both systems time is correct perfect and both system resolve in the dns correctly for both A and PTR records. I''m using RHEL 6.1 (puppet-0.25.5-1.el6.noarch) Thanks again for the help!!!! Bruce On Jun 20, 1:12 pm, Ken Barber <k...@puppetlabs.com> wrote:> Augeas is a resource - I don''t see how it fits in as a module. You may > _use_ it in your modules if you like. > > > > > > > > On Mon, Jun 20, 2011 at 12:09 PM, Bruce Bushby <bruce.bus...@gmail.com> wrote: > > One last question: > > > Would the list suggest implementing "augeas" where possible? and would > > "augeas" fit into the "module layout" > > > Thanks > > Bruce > > > On Jun 18, 9:29 am, Bruce Bushby <bruce.bus...@gmail.com> wrote: > >> Hello > > >> I''m new to large scale puppet deployment and was hoping the list could > >> offer some pointers on "module layout" > > >> My initial "layout" was motivated by a need to "harden" our Linux > >> systems. I grouped the various hardening configs into: > > >> Kernel > >> OS > >> Network > >> Shell > >> Files > >> Application > > >> I''m hoping I can create the same module structure within puppet. > > >> Using "sudo" as the first example, I want puppet to ensure "/usr/bin/ > >> sudo" has "4111" file perms and "root:root" ownership. > > >> Directory layout: > >> I used this handy script from "ProfFalken"http://www.threedrunkensysadsonthe.net/2010/04/quick-creation-of-pupp... > > >> BUT...this is where things are getting a little grey. I currently > >> have: > > >> [root@laptop manifests]# pwd > >> /etc/puppet/manifests > >> [root@laptop manifests]# > >> [root@laptop manifests]# tree os > >> os > >> |-- files > >> |-- lib > >> | |-- facter > >> | `-- puppet > >> | |-- parser > >> | |-- provider > >> | `-- type > >> |-- manifests > >> | |-- init.pp > >> | `-- sudo.pp > >> `-- templates > > >> 9 directories, 2 files > >> [root@laptop manifests]# > >> [root@laptop manifests]# cat os/manifests/sudo.pp > >> # /etc/puppet/manifests/classes/sudo.pp > > >> class sudo { > >> file { "/etc/sudoers": > >> owner => "root", > >> group => "root", > >> mode => 4111, > >> }} > > >> [root@laptop manifests]# > > >> Am I on the correct track? > > >> I''m guessing I should break the classes down into: > >> sudo::perms > >> sudo::ownership > >> sudo::file (have puppet serve the sudo template) > > >> then in "os/manifests/site.pp" ..... would I import sudo? > > >> and the second question: How would I create hosts groups? I would like > >> to group my hosts in "dev", "uat", "staging" and "prod" etc? > > >> ThanksBruce > > > -- > > 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 athttp://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.
On Sat, Jun 18, 2011 at 1:29 AM, Bruce Bushby <bruce.bushby@gmail.com>wrote:> Hello > > I''m new to large scale puppet deployment and was hoping the list could > offer some pointers on "module layout" > > My initial "layout" was motivated by a need to "harden" our Linux > systems. I grouped the various hardening configs into: > > Kernel > OS > Network > Shell > Files > Application > > I''m hoping I can create the same module structure within puppet.In my experience, these module categories are too broad and it will make maintenance difficult. You don''t want to get too fine-grained with your modules, but if you keep things this broad, you''ll end up having lots of complicated relationships like Class[os::foo] -> Class[files::foo] I made this mistake on a large deployment and regretted 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.
> Getting back to my ultra simple setup, I''m finding that I can''t run > "puppetd --test": > [root@msukpuppet02 puppet]# puppetd --test > err: Could not retrieve catalog from remote server: SSL_connect > returned=1 errno=0 state=SSLv3 read server certificate B: certificate > verify failed > warning: Not using cache on failed catalog > err: Could not retrieve catalog; skipping run > [root@msukpuppet02 puppet]# > > > HOWEVER...this works perfectly: > > [root@msukpuppet02 puppet]# puppetd --test -- > server=msukpuppet01.mserv.local > info: Caching catalog for msukpuppet02.mserv.local > info: Applying configuration version ''1308583986'' > notice: Finished catalog run in 0.02 seconds > [root@msukpuppet02 puppet]# > > > > My puppet config file sits in "/etc/sysconfig/puppet"Well - thats the RedHat specific environment file. Your configuration file for puppet (at least the one we usually refer to) is usually /etc/puppet/puppet.conf ;-). Anyway - the error you are getting is an SSL certificate security issue. When you run: puppet agent --test Its looking for the hostname ''puppet'' and trying to connect to it. Now if the server side certificate doesn''t have the alias ''puppet'' in the CN field its going to get rejected by the client. Think web server certificates in your browser ... except instead of giving you a warning you can push through ... we reject the connection. This is why using the alternate hostname works: puppet agent --test --server=msukpuppet01.mserv.local The hostname matches the CN field in the certificate this time :-). So you have a few choices here. You can update the /etc/puppet/puppet.conf on your clients with the setting: [agent] server=msukpuppet01.mserv.local That way it will just use that each time you do a ''puppet agent -t''. Or, you can regenerate your server certificate to have a number of aliases: puppet, msukpuppet01.mserv.local, puppet.mserv.local etc. I can explain this but ... what version of Puppet are you running btw? I get the impression its an old one. I would recommend upgrading to 2.6 before you proceed too far :-). If you already run 2.6 let me know :-). ken. -- 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.
Thanks again Ken!! I found it, /etc/puppet/puppet.conf requires: server = <server_name> and then: puppetd --test works without having to specify the server name......doh!!!! I should have checked that this morning! At last I can start testing a module layout and augeas :)) I''ll be sure to post the results in case others have a similar question. Bruce On Jun 20, 7:30 pm, Ken Barber <k...@puppetlabs.com> wrote:> > Getting back to my ultra simple setup, I''m finding that I can''t run > > "puppetd --test": > > [root@msukpuppet02 puppet]# puppetd --test > > err: Could not retrieve catalog from remote server: SSL_connect > > returned=1 errno=0 state=SSLv3 read server certificate B: certificate > > verify failed > > warning: Not using cache on failed catalog > > err: Could not retrieve catalog; skipping run > > [root@msukpuppet02 puppet]# > > > HOWEVER...this works perfectly: > > > [root@msukpuppet02 puppet]# puppetd --test -- > > server=msukpuppet01.mserv.local > > info: Caching catalog for msukpuppet02.mserv.local > > info: Applying configuration version ''1308583986'' > > notice: Finished catalog run in 0.02 seconds > > [root@msukpuppet02 puppet]# > > > My puppet config file sits in "/etc/sysconfig/puppet" > > Well - thats the RedHat specific environment file. Your configuration > file for puppet (at least the one we usually refer to) is usually > /etc/puppet/puppet.conf ;-). > > Anyway - the error you are getting is an SSL certificate security > issue. When you run: > > puppet agent --test > > Its looking for the hostname ''puppet'' and trying to connect to it. Now > if the server side certificate doesn''t have the alias ''puppet'' in the > CN field its going to get rejected by the client. Think web server > certificates in your browser ... except instead of giving you a > warning you can push through ... we reject the connection. > > This is why using the alternate hostname works: > > puppet agent --test --server=msukpuppet01.mserv.local > > The hostname matches the CN field in the certificate this time :-). > > So you have a few choices here. You can update the > /etc/puppet/puppet.conf on your clients with the setting: > > [agent] > server=msukpuppet01.mserv.local > > That way it will just use that each time you do a ''puppet agent -t''. > > Or, you can regenerate your server certificate to have a number of > aliases: puppet, msukpuppet01.mserv.local, puppet.mserv.local etc. I > can explain this but ... what version of Puppet are you running btw? I > get the impression its an old one. I would recommend upgrading to 2.6 > before you proceed too far :-). If you already run 2.6 let me know > :-). > > ken.-- 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.
Thanks Nigel, appreciate the heads up! I''m finding that puppet module are great when you want a module for "ssh" or a module for "sudoers" ...but I can''t find an example where there is a module called "os" which contains "ssh.pp" , "prod_sudoers.pp" , "dev_sudoers.pp" , "userauth.pp", "iptables.pp" ....etc Then /etc/puppet/manifest/site.pp would include the module "os" and then /etc/puppet/modules/os/manifest/init.pp would include the various "pp" components for various hosts lists. Is this even possible? On Jun 20, 5:50 pm, Nigel Kersten <ni...@puppetlabs.com> wrote:> On Sat, Jun 18, 2011 at 1:29 AM, Bruce Bushby <bruce.bus...@gmail.com>wrote: > > > > > > > > > > > Hello > > > I''m new to large scale puppet deployment and was hoping the list could > > offer some pointers on "module layout" > > > My initial "layout" was motivated by a need to "harden" our Linux > > systems. I grouped the various hardening configs into: > > > Kernel > > OS > > Network > > Shell > > Files > > Application > > > I''m hoping I can create the same module structure within puppet. > > In my experience, these module categories are too broad and it will make > maintenance difficult. > > You don''t want to get too fine-grained with your modules, but if you keep > things this broad, you''ll end up having lots of complicated relationships > like Class[os::foo] -> Class[files::foo] > > I made this mistake on a large deployment and regretted 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.
On Thu, Jun 23, 2011 at 3:09 AM, Bruce Bushby <bruce.bushby@gmail.com> wrote:> Thanks Nigel, appreciate the heads up! > > I''m finding that puppet module are great when you want a module for > "ssh" or a module for "sudoers" ...but I can''t find an example where > there is a module called "os" which contains "ssh.pp" , > "prod_sudoers.pp" , "dev_sudoers.pp" , "userauth.pp", > "iptables.pp" ....etcHere are the file mappings to class names so that the autoloader finds them. $modulepath/foo/manifests/init.pp -> class foo { ... } $modulepath/foo/manifests/bar.pp -> class foo::bar { ... } $modulepath/foo/manifests/bar/baz.pp -> class foo::bar::baz { ... } Is that what you meant Bruce?> > Then /etc/puppet/manifest/site.pp would include the module "os" > > and then /etc/puppet/modules/os/manifest/init.pp would include the > various "pp" components for various hosts lists. > > Is this even possible? > > > > > On Jun 20, 5:50 pm, Nigel Kersten <ni...@puppetlabs.com> wrote: >> On Sat, Jun 18, 2011 at 1:29 AM, Bruce Bushby <bruce.bus...@gmail.com>wrote: >> >> >> >> >> >> >> >> >> >> > Hello >> >> > I''m new to large scale puppet deployment and was hoping the list could >> > offer some pointers on "module layout" >> >> > My initial "layout" was motivated by a need to "harden" our Linux >> > systems. I grouped the various hardening configs into: >> >> > Kernel >> > OS >> > Network >> > Shell >> > Files >> > Application >> >> > I''m hoping I can create the same module structure within puppet. >> >> In my experience, these module categories are too broad and it will make >> maintenance difficult. >> >> You don''t want to get too fine-grained with your modules, but if you keep >> things this broad, you''ll end up having lots of complicated relationships >> like Class[os::foo] -> Class[files::foo] >> >> I made this mistake on a large deployment and regretted 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. > >-- Nigel Kersten Product, Puppet Labs @nigelkersten -- 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.