Good day, First off, I''m a complete puppet newbie, this openvpn recipe is pretty much the first puppet work I''ve done so be gentle :-) Secondly, the openvpn setup for Debian (and systems based on Debian) allows each openvpn network (tunnel) to be specified using a separate config file for each: /etc/openvpn/<vpn>.conf Each tunnel can be then stopped/started/restarted using : /etc/init.d/openvpn stop|start|restart <vpn> This allows one tunnel to be altered and restarted without affecting others, otherwise a restart would all tunnels to be restarted which can cause the keys of all clients to become out of sync for a minute, possibly longer. Unfortunately, I''ve found this complicates the puppet setup, although this may have more to do with my inexperience with puppet than anything else. I include my recipe below with additional comments/questions. I would be grateful for any corrections and suggestions for improvments. Note, I haven''t completely followed the StyleGuide but will probably tidy up if/when I receive comments. In addition if people consider this of reasonable value to others I could add it as a recipe to the wiki. Anyway here it is, my comments/questions are prepended with ** :- # /etc/puppet/manifests/classes/openvpn.pp ** Is it possible to have only one file { }, so the shared elements ** only need to be specified once, e.g. owner, group, perhaps using ** case within file { } ? define openvpn_file ($source = "", $content = "", $tunnel, $path, $mode = 0640) { if $source { file { "$name": source => "puppet:///files/$source", path => $path, ensure => present, mode => $mode, owner => root, group => root, before => SERVICE["openvpn_$tunnel"], require => PACKAGE["openvpn"], notify => SERVICE["openvpn_$tunnel"], } } if $content { file { "$name": content => $content, path => $path, ensure => present, mode => $mode, owner => root, group => root, before => SERVICE["openvpn_$tunnel"], require => PACKAGE["openvpn"], notify => SERVICE["openvpn_$tunnel"], } } } # openvpn_file ** Need separate service so start/stop can work on each tunnel; BUT ** note problems this causes; enable set to true tries to call ** update-rc.d with the service name (openvpn_tunnel) but there is ** only one init.d/openvpn script that can be enabled/disabled # For Debian systems start/stop can be called with tunnel name allowing # VPNs to be controlled separately define openvpn_service { service { "openvpn_$name": ensure => true, # Can''t use enable and init - how to use debian and enable, but with multiple services for # the same package # enable => true, hasrestart => false, provider => "init", start => "/etc/init.d/openvpn start $name", stop => "/etc/init.d/openvpn stop $name", pattern => "openvpn\s.*$name.conf" } } # openvpn_service class openvpn_base { package { "openvpn": ensure => latest } file { "/etc/openvpn/keys": ensure => directory, require => PACKAGE["openvpn"], } ** Note the comment about not being able to use the openvpn_file. How ** to have ca_crt defined once per openvpn installation BUT having it ** associated with each openvpn_service ? # Root CA certificate - can''t use openvpn_file as it uses the # tunnel''s service and I don''t know how to make this once per node # file use a service which is once per tunnel file { "ca_crt": path => "/etc/openvpn/keys/ca.crt", source => "puppet:///files/openvpn/ca.crt", ensure => present, mode => 0640, owner => root, group => root, require => [ File["/etc/openvpn/keys"], PACKAGE["openvpn"] ], } } # openvpn_base define openvpn_client($server, $server_host, $port, $network) { $what = "client" $remote = "remote $server_host\n" $localip = "$network.2" $remoteip = "$network.1" $tun = "$server" $tls = "tls-client\ntls-remote server" $keys = "cert keys/$server.crt\nkey keys/$server.key" # Service based upon name for Debian based systems openvpn_service { "$server": } openvpn_file { "$server.conf": tunnel => $server, path => "/etc/openvpn/$server.conf", content => template("openvpn/shared.conf"), } # Client1 Certificate openvpn_file { "$server-crt": tunnel => $server, path => "/etc/openvpn/keys/$server.crt", source => "openvpn/$server-$name.crt", require => File["/etc/openvpn/keys"], } # Client1 Key (secret) openvpn_file { "$server-key": tunnel => $server, path => "/etc/openvpn/keys/$server.key", source => "openvpn/$server-$name.key", mode => 400, require => File["/etc/openvpn/keys"], } } # openvpn_client # Only for servers - the parameters file, the server key and # certificate are only needed once no matter how many server configs # are on this host class openvpn_server_base { ** Similar problem with the server''s files as the ca_crt as far the ** service goes. # Diffie Hellman parameters - can''t use openvpn_file as it uses the # tunnel''s service and I don''t know how to make this once per node # file use a service which is once per tunnel file { "dh": path => "/etc/openvpn/keys/dh2048.pem", source => "puppet:///files/openvpn/dh2048.pem", ensure => present, mode => 0640, owner => root, group => root, require => [ File["/etc/openvpn/keys"], PACKAGE["openvpn"] ], } # Server Certificate - same here file { "$name-server-crt": path => "/etc/openvpn/keys/server.crt", source => "puppet:///files/openvpn/$name-server.crt", ensure => present, mode => 0640, owner => root, group => root, require => [ File["/etc/openvpn/keys"], PACKAGE["openvpn"] ], } # Server Key (secret) - same here file { "$name-server-key": path => "/etc/openvpn/keys/server.key", source => "puppet:///files/openvpn/$name-server.key", mode => 400, ensure => present, owner => root, group => root, require => [ File["/etc/openvpn/keys"], PACKAGE["openvpn"] ], } } # openvpn_server_base # One server config per client host define openvpn_server($client, $port, $network) { $what = "server" $remote = "" $localip = "$network.1" $remoteip = "$network.2" $tun = "$client" $tls = "tls-server" $keys = "cert keys/server.crt\nkey keys/server.key\ndh keys/dh2048.pem" # Service based upon name for Debian based systems openvpn_service { "$client": } openvpn_file { "$client.conf": tunnel => $client, path => "/etc/openvpn/$client.conf", content => template("openvpn/shared.conf"), require => [ File["$name-server-key"] ], } } # openvpn_server class openvpn { include openvpn_base $host1_host2_net = "192.168.30" $host1_host2_port = "44430" $host2_host3_net = "192.168.40" $host2_host3_port = "44440" case $name { host2: { openvpn_client { "host2": port => $host1_host2_port, server => "host1", server_host => "host1.somewhere.net", network => $host1_host2_net, } include openvpn_server_base openvpn_server { "host2": client => "host3", port => $host2_host3_port, network => $host2_host3_net, } } # host2 host1: { include openvpn_server_base openvpn_server { "host1": client => "host2", port => $host1_host2_port, network => $host1_host2_net, } } # host1 } } # openvpn Thank you for any assistance with this. Sincerely, Adrian Phillips -- Who really wrote the works of William Shakespeare ? http://www.pbs.org/wgbh/pages/frontline/shakespeare/
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Sunday 28 October 2007, Adrian Phillips wrote:> Good day, > > First off, I''m a complete puppet newbie, this openvpn recipe is pretty > much the first puppet work I''ve done so be gentle :-)Great! I have a openvpn module on my todo for way too long already :)> Secondly, the openvpn setup for Debian (and systems based on Debian) > allows each openvpn network (tunnel) to be specified using a separate > config file for each: /etc/openvpn/<vpn>.conf > > Each tunnel can be then stopped/started/restarted using : > /etc/init.d/openvpn stop|start|restart <vpn> > > This allows one tunnel to be altered and restarted without affecting > others, otherwise a restart would all tunnels to be restarted which > can cause the keys of all clients to become out of sync for a minute, > possibly longer. > > Unfortunately, I''ve found this complicates the puppet setup, although > this may have more to do with my inexperience with puppet than > anything else. I include my recipe below with additional > comments/questions. I would be grateful for any corrections and > suggestions for improvments.Debian also has an AUTOSTART variable in /etc/default/openvpn which denotes all tunnels to be started on boot. I would try to a) create a purged directory with flag files to enumerate the tunnels that should be started. e.g. /var/lib/puppet/modules/openvpn/{host1,host2} b) replace the assignment to AUTOSTART in /etc/default/openvpn by a little function like this: AUTOSTART="$(cd /var/lib/puppet/modules/openvpn/; ls)" c) use a service to manage the base rc.d links for openvpn (i.e. starting on boot, stopping on shutdown) and use custom execs to start/stop/restart a tunnel when its config file changes.> Note, I haven''t completely followed the StyleGuide but will probably > tidy up if/when I receive comments. In addition if people consider > this of reasonable value to others I could add it as a recipe to the > wiki. > > Anyway here it is, my comments/questions are prepended with ** :- > > # /etc/puppet/manifests/classes/openvpn.pp > > ** Is it possible to have only one file { }, so the shared elements > ** only need to be specified once, e.g. owner, group, perhaps using > ** case within file { } ? > > define openvpn_file ($source = "", $content = "", $tunnel, $path, $mode > = 0640) { if $source { > file { "$name": > source => "puppet:///files/$source", > path => $path, > ensure => present, > mode => $mode, > owner => root, > group => root, > before => SERVICE["openvpn_$tunnel"], > require => PACKAGE["openvpn"], > notify => SERVICE["openvpn_$tunnel"], > } > } > if $content { > file { "$name": > content => $content, > path => $path, > ensure => present, > mode => $mode, > owner => root, > group => root, > before => SERVICE["openvpn_$tunnel"], > require => PACKAGE["openvpn"], > notify => SERVICE["openvpn_$tunnel"], > } > } > } # openvpn_fileNo this (source vs. content) is one of the few cases where you have to duplicate all info. For other cases, there exists a $var ? { ''val1'' => ''result1'', ''val2'' => ''result2'' } syntax. Most of the other points should be resolved too by restructuring the service.> Thank you for any assistance with this. > > Sincerely, > > Adrian PhillipsRegards, David - -- The primary freedom of open source is not the freedom from cost, but the free- dom to shape software to do what you want. This freedom is /never/ exercised without cost, but is available /at all/ only by accepting the very different costs associated with open source, costs not in money, but in time and effort. - -- http://www.schierer.org/~luke/log/20070710-1129/on-forks-and-forking -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFHJLSg/Pp1N6Uzh0URApMuAJ4zUkKUSL9NmXRaPbMdKxl0Rfe/3gCgjdI8 3CoqSON7g5xa1GIRRNGmO9s=81vp -----END PGP SIGNATURE-----
>>>>> "David" == David Schmitt <david@schmitt.edv-bus.at> writes:David> On Sunday 28 October 2007, Adrian Phillips wrote: >> Good day, >> >> First off, I''m a complete puppet newbie, this openvpn recipe is >> pretty much the first puppet work I''ve done so be gentle :-) David> Most of the other points should be resolved too by David> restructuring the service. Thanks for the feedback - it''ll probably take me a week or two before I get to fix this, then I''ll repost the result. Sincerely, Adrian Phillips -- Who really wrote the works of William Shakespeare ? http://www.pbs.org/wgbh/pages/frontline/shakespeare/
>>>>> "David" == David Schmitt <david@schmitt.edv-bus.at> writes:David> On Sunday 28 October 2007, Adrian Phillips wrote: >> ** Is it possible to have only one file { }, so the shared >> elements ** only need to be specified once, e.g. owner, group, >> perhaps using ** case within file { } ? >> David> No this (source vs. content) is one of the few cases where David> you have to duplicate all info. For other cases, there David> exists a $var ? { ''val1'' => ''result1'', ''val2'' => ''result2'' David> } syntax. After Luke posted on the "Boolean Expressions" thread I changed this to :- define openvpn_file ($source = "", $content = "", $tunnel, $path, $mode = 0640) { file { "$name": path => $path, ensure => present, mode => $mode, owner => root, group => root, before => SERVICE["openvpn_$tunnel"], require => PACKAGE["openvpn"], notify => SERVICE["openvpn_$tunnel"], } if $source { File[$name] { source => "puppet:///files/$source" } } if $content { File[$name] { content => $content } } } # openvpn_file which means information doesn''t have to be duplicated, if I''ve understood how it works correctly at any rate. Regards, Adrian Phillips -- Who really wrote the works of William Shakespeare ? http://www.pbs.org/wgbh/pages/frontline/shakespeare/
On Oct 29, 2007, at 10:47 AM, Adrian Phillips wrote:> if $source { > File[$name] { source => "puppet:///files/$source" } > } > if $content { > File[$name] { content => $content } > }This only works if $source and $content are set to false, not "". That is, the empty string is not considered false by Puppet. -- A conservative is a man who believes that nothing should be done for the first time. --Alfred E. Wiggam --------------------------------------------------------------------- Luke Kanies | http://reductivelabs.com | http://madstop.com
>>>>> "Luke" == Luke Kanies <luke@madstop.com> writes:Luke> On Oct 29, 2007, at 10:47 AM, Adrian Phillips wrote: >> if $source { File[$name] { source => "puppet:///files/$source" >> } >> } >> if $content { File[$name] { content => $content } >> } Luke> This only works if $source and $content are set to false, Luke> not "". That is, the empty string is not considered false Luke> by Puppet. Ah, okay, thanks. Regards, Adrian -- Who really wrote the works of William Shakespeare ? http://www.pbs.org/wgbh/pages/frontline/shakespeare/
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Monday 29 October 2007, Adrian Phillips wrote:> >>>>> "David" == David Schmitt <david@schmitt.edv-bus.at> writes: > > David> On Sunday 28 October 2007, Adrian Phillips wrote: > >> ** Is it possible to have only one file { }, so the shared > >> elements ** only need to be specified once, e.g. owner, group, > >> perhaps using ** case within file { } ? > > David> No this (source vs. content) is one of the few cases where > David> you have to duplicate all info. For other cases, there > David> exists a $var ? { ''val1'' => ''result1'', ''val2'' => ''result2'' > David> } syntax. > > After Luke posted on the "Boolean Expressions" thread I changed this > to :- > > define openvpn_file ($source = "", $content = "", $tunnel, $path, $mode > = 0640) { file { "$name": > path => $path, > ensure => present, > mode => $mode, > owner => root, > group => root, > before => SERVICE["openvpn_$tunnel"], > require => PACKAGE["openvpn"], > notify => SERVICE["openvpn_$tunnel"], > } > > if $source { > File[$name] { source => "puppet:///files/$source" } > } > if $content { > File[$name] { content => $content } > } > } # openvpn_file > > which means information doesn''t have to be duplicated, if I''ve > understood how it works correctly at any rate.ooohh ... That is really a great imrpovement! I hadn''t realized, that you can annotate additional attributes in the same scope! Regards, David - -- The primary freedom of open source is not the freedom from cost, but the free- dom to shape software to do what you want. This freedom is /never/ exercised without cost, but is available /at all/ only by accepting the very different costs associated with open source, costs not in money, but in time and effort. - -- http://www.schierer.org/~luke/log/20070710-1129/on-forks-and-forking -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFHJuzW/Pp1N6Uzh0URAjAbAKCWtYaEvVwmtFfKqmweZOJzsIkfpQCbB64o jbPKiKJBhR9u8fYh+yqMZPs=j4ld -----END PGP SIGNATURE-----
>>>>> "David" == David Schmitt <david@schmitt.edv-bus.at> writes:David> On Monday 29 October 2007, Adrian Phillips wrote: >> define openvpn_file ($source = "", $content = "", $tunnel, >> $path, $mode = 0640) { file { "$name": path => $path, ensure => >> present, mode => $mode, owner => root, group => root, before => >> SERVICE["openvpn_$tunnel"], require => PACKAGE["openvpn"], >> notify => SERVICE["openvpn_$tunnel"], >> } >> >> if $source { File[$name] { source => "puppet:///files/$source" >> } >> } >> if $content { File[$name] { content => $content } >> } >> } # openvpn_file >> >> which means information doesn''t have to be duplicated, if I''ve >> understood how it works correctly at any rate. David> ooohh ... That is really a great imrpovement! I hadn''t David> realized, that you can annotate additional attributes in David> the same scope! Is there some place in the wiki an example could be placed (or an existing one modified) to highlight this ? Scanning the wiki doesn''t give me an obvious place, although once I sort out this openvpn recipe it could serve as en example. Regards, Adrian -- Who really wrote the works of William Shakespeare ? http://www.pbs.org/wgbh/pages/frontline/shakespeare/
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Tuesday 30 October 2007, Adrian Phillips wrote:> >>>>> "David" == David Schmitt <david@schmitt.edv-bus.at> writes: > > David> On Monday 29 October 2007, Adrian Phillips wrote: > >> define openvpn_file ($source = "", $content = "", $tunnel, > >> $path, $mode = 0640) { file { "$name": path => $path, ensure => > >> present, mode => $mode, owner => root, group => root, before => > >> SERVICE["openvpn_$tunnel"], require => PACKAGE["openvpn"], > >> notify => SERVICE["openvpn_$tunnel"], > >> } > >> > >> if $source { File[$name] { source => "puppet:///files/$source" > >> } > >> } > >> if $content { File[$name] { content => $content } > >> } > >> } # openvpn_file > >> > >> which means information doesn''t have to be duplicated, if I''ve > >> understood how it works correctly at any rate. > > David> ooohh ... That is really a great imrpovement! I hadn''t > David> realized, that you can annotate additional attributes in > David> the same scope! > > Is there some place in the wiki an example could be placed (or an > existing one modified) to highlight this ? Scanning the wiki doesn''t > give me an obvious place, although once I sort out this openvpn recipe > it could serve as en example.Perhaps in the LanguageTutorial#resource-defaults for a start? Regards, David - -- The primary freedom of open source is not the freedom from cost, but the free- dom to shape software to do what you want. This freedom is /never/ exercised without cost, but is available /at all/ only by accepting the very different costs associated with open source, costs not in money, but in time and effort. - -- http://www.schierer.org/~luke/log/20070710-1129/on-forks-and-forking -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) iD8DBQFHJvpI/Pp1N6Uzh0URAsEoAJ9cB8qThHIhTT9YYEtwf/1sN8lEhQCfUpAr qoiCY5nrKoBGK+nion4XmMA=ktrW -----END PGP SIGNATURE-----
On Oct 30, 2007, at 4:32 AM, David Schmitt wrote:>> >> Is there some place in the wiki an example could be placed (or an >> existing one modified) to highlight this ? Scanning the wiki doesn''t >> give me an obvious place, although once I sort out this openvpn >> recipe >> it could serve as en example. > > Perhaps in the LanguageTutorial#resource-defaults for a start?Sounds like a great place for someone else to put it. :) -- I love deadlines. I like the whooshing sound they make as they fly by. --Douglas Adams --------------------------------------------------------------------- Luke Kanies | http://reductivelabs.com | http://madstop.com