logo       

openvpn recipe: comments, suggestions, help: msg#00292

sysutils.puppet.user

Subject: openvpn recipe: comments, suggestions, help


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/


<Prev in Thread] Current Thread [Next in Thread>
Google Custom Search

News | FAQ | advertise