summaryrefslogtreecommitdiff
path: root/puppet/modules/openvpn/manifests
diff options
context:
space:
mode:
Diffstat (limited to 'puppet/modules/openvpn/manifests')
-rw-r--r--puppet/modules/openvpn/manifests/client.pp187
-rw-r--r--puppet/modules/openvpn/manifests/client_specific_config.pp79
-rw-r--r--puppet/modules/openvpn/manifests/config.pp52
-rw-r--r--puppet/modules/openvpn/manifests/init.pp43
-rw-r--r--puppet/modules/openvpn/manifests/install.pp46
-rw-r--r--puppet/modules/openvpn/manifests/params.pp37
-rw-r--r--puppet/modules/openvpn/manifests/server.pp233
-rw-r--r--puppet/modules/openvpn/manifests/service.pp36
8 files changed, 713 insertions, 0 deletions
diff --git a/puppet/modules/openvpn/manifests/client.pp b/puppet/modules/openvpn/manifests/client.pp
new file mode 100644
index 00000000..92c6aa4e
--- /dev/null
+++ b/puppet/modules/openvpn/manifests/client.pp
@@ -0,0 +1,187 @@
+# == Define: openvpn::client
+#
+# This define creates the client certs for a specified openvpn server as well
+# as creating a tarball that can be directly imported into openvpn clients
+#
+#
+# === Parameters
+#
+# [*server*]
+# String. Name of the corresponding openvpn endpoint
+# Required
+#
+# [*compression*]
+# String. Which compression algorithim to use
+# Default: comp-lzo
+# Options: comp-lzo or '' (disable compression)
+#
+# [*dev*]
+# String. Device method
+# Default: tun
+# Options: tun (routed connections), tap (bridged connections)
+#
+# [*mute*]
+# Integer. Set log mute level
+# Default: 20
+#
+# [*mute_replay_warnings*]
+# Boolean. Silence duplicate packet warnings (common on wireless networks)
+# Default: true
+#
+# [*nobind*]
+# Boolean. Whether or not to bind to a specific port number
+# Default: true
+#
+# [*persist_key*]
+# Boolean. Try to retain access to resources that may be unavailable
+# because of privilege downgrades
+# Default: true
+#
+# [*persist_tun*]
+# Boolean. Try to retain access to resources that may be unavailable
+# because of privilege downgrades
+# Default: true
+#
+# [*port*]
+# Integer. The port the openvpn server service is running on
+# Default: 1194
+#
+# [*proto*]
+# String. What IP protocol is being used.
+# Default: tcp
+# Options: tcp or udp
+#
+# [*remote_host*]
+# String. The IP or hostname of the openvpn server service
+# Default: FQDN
+#
+# [*resolv_retry*]
+# Integer/String. How many seconds should the openvpn client try to resolve
+# the server's hostname
+# Default: infinite
+# Options: Integer or infinite
+#
+# [*verb*]
+# Integer. Level of logging verbosity
+# Default: 3
+#
+#
+# === Examples
+#
+# openvpn::client {
+# 'my_user':
+# server => 'contractors',
+# remote_host => 'vpn.mycompany.com'
+# }
+#
+# * Removal:
+# Manual process right now, todo for the future
+#
+#
+# === Authors
+#
+# * Raffael Schmid <mailto:raffael@yux.ch>
+# * John Kinsella <mailto:jlkinsel@gmail.com>
+# * Justin Lambert <mailto:jlambert@letsevenup.com>
+#
+# === License
+#
+# Copyright 2013 Raffael Schmid, <raffael@yux.ch>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+define openvpn::client(
+ $server,
+ $compression = 'comp-lzo',
+ $dev = 'tun',
+ $mute = '20',
+ $mute_replay_warnings = true,
+ $nobind = true,
+ $persist_key = true,
+ $persist_tun = true,
+ $port = '1194',
+ $proto = 'tcp',
+ $remote_host = $::fqdn,
+ $resolv_retry = 'infinite',
+ $verb = '3',
+) {
+
+ Openvpn::Server[$server] ->
+ Openvpn::Client[$name]
+
+ exec {
+ "generate certificate for ${name} in context of ${server}":
+ command => ". ./vars && ./pkitool ${name}",
+ cwd => "/etc/openvpn/${server}/easy-rsa",
+ creates => "/etc/openvpn/${server}/easy-rsa/keys/${name}.crt",
+ provider => 'shell';
+ }
+
+ file {
+ [ "/etc/openvpn/${server}/download-configs/${name}",
+ "/etc/openvpn/${server}/download-configs/${name}/keys"]:
+ ensure => directory;
+
+ "/etc/openvpn/${server}/download-configs/${name}/keys/${name}.crt":
+ ensure => link,
+ target => "/etc/openvpn/${server}/easy-rsa/keys/${name}.crt",
+ require => Exec["generate certificate for ${name} in context of ${server}"];
+
+ "/etc/openvpn/${server}/download-configs/${name}/keys/${name}.key":
+ ensure => link,
+ target => "/etc/openvpn/${server}/easy-rsa/keys/${name}.key",
+ require => Exec["generate certificate for ${name} in context of ${server}"];
+
+ "/etc/openvpn/${server}/download-configs/${name}/keys/ca.crt":
+ ensure => link,
+ target => "/etc/openvpn/${server}/easy-rsa/keys/ca.crt",
+ require => Exec["generate certificate for ${name} in context of ${server}"];
+
+ "/etc/openvpn/${server}/download-configs/${name}/${name}.conf":
+ owner => root,
+ group => root,
+ mode => '0444',
+ content => template('openvpn/client.erb'),
+ notify => Exec["tar the thing ${server} with ${name}"];
+ }
+
+ exec {
+ "tar the thing ${server} with ${name}":
+ cwd => "/etc/openvpn/${server}/download-configs/",
+ command => "/bin/rm ${name}.tar.gz; tar --exclude=\\*.conf.d -chzvf ${name}.tar.gz ${name}",
+ refreshonly => true,
+ require => [ File["/etc/openvpn/${server}/download-configs/${name}/${name}.conf"],
+ File["/etc/openvpn/${server}/download-configs/${name}/keys/ca.crt"],
+ File["/etc/openvpn/${server}/download-configs/${name}/keys/${name}.key"],
+ File["/etc/openvpn/${server}/download-configs/${name}/keys/${name}.crt"]
+ ],
+ notify => Exec["generate ${name}.ovpn in ${server}"];
+ }
+
+ exec {
+ "generate ${name}.ovpn in ${server}":
+ cwd => "/etc/openvpn/${server}/download-configs/",
+ command => "/bin/rm ${name}.ovpn; cat ${name}/${name}.conf|perl -lne 'if(m|^ca keys/ca.crt|){ chomp(\$ca=`cat ${name}/keys/ca.crt`); print \"<ca>\n\$ca\n</ca>\"} elsif(m|^cert keys/${name}.crt|) { chomp(\$crt=`cat ${name}/keys/${name}.crt`); print \"<cert>\n\$crt\n</cert>\"} elsif(m|^key keys/${name}.key|){ chomp(\$key=`cat ${name}/keys/${name}.key`); print \"<key>\n\$key\n</key>\"} else { print} ' > ${name}.ovpn",
+ refreshonly => true,
+ require => [ File["/etc/openvpn/${server}/download-configs/${name}/${name}.conf"],
+ File["/etc/openvpn/${server}/download-configs/${name}/keys/ca.crt"],
+ File["/etc/openvpn/${server}/download-configs/${name}/keys/${name}.key"],
+ File["/etc/openvpn/${server}/download-configs/${name}/keys/${name}.crt"],
+ ],
+ }
+
+ file { "/etc/openvpn/${server}/download-configs/${name}.ovpn":
+ mode => '0400',
+ require => Exec["generate ${name}.ovpn in ${server}"],
+ }
+}
diff --git a/puppet/modules/openvpn/manifests/client_specific_config.pp b/puppet/modules/openvpn/manifests/client_specific_config.pp
new file mode 100644
index 00000000..4287421a
--- /dev/null
+++ b/puppet/modules/openvpn/manifests/client_specific_config.pp
@@ -0,0 +1,79 @@
+# == Define: openvpn::client_specific_config
+#
+# This define configures options which will be pushed by the server to a
+# specific client only. This feature is explained here:
+# http://openvpn.net/index.php/open-source/documentation/howto.html#policy
+#
+# === Parameters
+#
+# All the parameters are explained in the openvpn documentation:
+# http://openvpn.net/index.php/open-source/documentation/howto.html#policy
+#
+# [*server*]
+# String. Name of the corresponding openvpn endpoint
+# Required
+#
+# [*iroute*]
+# Array. Array of iroute combinations.
+# Default: []
+#
+# [*ifconfig*]
+# String. IP configuration to push to the client.
+# Default: false
+#
+# [*dhcp_options]
+# Array. DHCP options to push to the client.
+# Default: []
+#
+#
+# === Examples
+#
+# openvpn::client_specific_config {
+# 'vpn_client':
+# server => 'contractors',
+# iroute => ['10.0.1.0 255.255.255.0'],
+# ifconfig => '10.10.10.1 10.10.10.2',
+# dhcp_options => ['DNS 8.8.8.8']
+# }
+#
+# * Removal:
+# Manual process right now, todo for the future
+#
+#
+# === Authors
+#
+# * Raffael Schmid <mailto:raffael@yux.ch>
+#
+# === License
+#
+# Copyright 2013 Raffael Schmid, <raffael@yux.ch>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+define openvpn::client_specific_config(
+ $server,
+ $iroute = [],
+ $ifconfig = false,
+ $dhcp_options = []
+) {
+
+ Openvpn::Server[$server] ->
+ Openvpn::Client[$name] ->
+ Openvpn::Client_specific_config[$name]
+
+ file { "/etc/openvpn/${server}/client-configs/${name}":
+ ensure => present,
+ content => template('openvpn/client_specific_config.erb')
+ }
+
+}
diff --git a/puppet/modules/openvpn/manifests/config.pp b/puppet/modules/openvpn/manifests/config.pp
new file mode 100644
index 00000000..32b32094
--- /dev/null
+++ b/puppet/modules/openvpn/manifests/config.pp
@@ -0,0 +1,52 @@
+# == Class: openvpn::config
+#
+# This class sets up the openvpn enviornment as well as the default config file
+#
+#
+# === Examples
+#
+# This class should not be directly invoked
+#
+# === Authors
+#
+# * Raffael Schmid <mailto:raffael@yux.ch>
+# * John Kinsella <mailto:jlkinsel@gmail.com>
+# * Justin Lambert <mailto:jlambert@letsevenup.com>
+#
+# === License
+#
+# Copyright 2013 Raffael Schmid, <raffael@yux.ch>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+class openvpn::config {
+
+ if $::osfamily == 'Debian' {
+ include concat::setup
+
+ concat {
+ '/etc/default/openvpn':
+ owner => root,
+ group => root,
+ mode => 644,
+ warn => true;
+ }
+
+ concat::fragment {
+ 'openvpn.default.header':
+ content => template('openvpn/etc-default-openvpn.erb'),
+ target => '/etc/default/openvpn',
+ order => 01;
+ }
+ }
+}
diff --git a/puppet/modules/openvpn/manifests/init.pp b/puppet/modules/openvpn/manifests/init.pp
new file mode 100644
index 00000000..7e07f025
--- /dev/null
+++ b/puppet/modules/openvpn/manifests/init.pp
@@ -0,0 +1,43 @@
+# == Class: openvpn
+#
+# This module installs the openvpn service, configures vpn endpoints, generates
+# client certificates, and generates client config files
+#
+#
+# === Examples
+#
+# * Installation:
+# class { 'openvpn': }
+#
+#
+# === Authors
+#
+# * Raffael Schmid <mailto:raffael@yux.ch>
+# * John Kinsella <mailto:jlkinsel@gmail.com>
+# * Justin Lambert <mailto:jlambert@letsevenup.com>
+#
+# === License
+#
+# Copyright 2013 Raffael Schmid, <raffael@yux.ch>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+class openvpn {
+
+ class {'openvpn::params': } ->
+ class {'openvpn::install': } ->
+ class {'openvpn::config': } ~>
+ class {'openvpn::service': } ->
+ Class['openvpn']
+
+}
diff --git a/puppet/modules/openvpn/manifests/install.pp b/puppet/modules/openvpn/manifests/install.pp
new file mode 100644
index 00000000..a230373a
--- /dev/null
+++ b/puppet/modules/openvpn/manifests/install.pp
@@ -0,0 +1,46 @@
+# == Class: openvpn
+#
+# This module installs the openvpn service, configures vpn endpoints, generates
+# client certificates, and generates client config files
+#
+#
+# === Examples
+#
+# This class should not be directly invoked
+#
+#
+# === Authors
+#
+# * Raffael Schmid <mailto:raffael@yux.ch>
+# * John Kinsella <mailto:jlkinsel@gmail.com>
+# * Justin Lambert <mailto:jlambert@letsevenup.com>
+#
+# === License
+#
+# Copyright 2013 Raffael Schmid, <raffael@yux.ch>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+class openvpn::install {
+
+ package {
+ 'openvpn':
+ ensure => installed;
+ }
+
+ file {
+ [ '/etc/openvpn', '/etc/openvpn/keys' ]:
+ ensure => directory,
+ require => Package['openvpn'];
+ }
+}
diff --git a/puppet/modules/openvpn/manifests/params.pp b/puppet/modules/openvpn/manifests/params.pp
new file mode 100644
index 00000000..33495270
--- /dev/null
+++ b/puppet/modules/openvpn/manifests/params.pp
@@ -0,0 +1,37 @@
+# === License
+#
+# Copyright 2013 Raffael Schmid, <raffael@yux.ch>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+class openvpn::params {
+
+ $group = $::osfamily ? {
+ 'RedHat' => 'nobody',
+ default => 'nogroup'
+ }
+
+ $easyrsa_source = $::osfamily ? {
+ 'RedHat' => $::operatingsystemmajrelease ? {
+ 6 => '/usr/share/openvpn/easy-rsa/2.0',
+ default => '/usr/share/doc/openvpn-2.2.2/easy-rsa/2.0'
+ },
+ default => '/usr/share/doc/openvpn/examples/easy-rsa/2.0'
+ }
+
+ $link_openssl_cnf = $::osfamily ? {
+ /(Debian|RedHat)/ => true,
+ default => false
+ }
+
+}
diff --git a/puppet/modules/openvpn/manifests/server.pp b/puppet/modules/openvpn/manifests/server.pp
new file mode 100644
index 00000000..649048c4
--- /dev/null
+++ b/puppet/modules/openvpn/manifests/server.pp
@@ -0,0 +1,233 @@
+# == Define: openvpn::server
+#
+# This define creates the openvpn server instance and ssl certificates
+#
+#
+# === Parameters
+#
+# [*country*]
+# String. Country to be used for the SSL certificate
+#
+# [*province*]
+# String. Province to be used for the SSL certificate
+#
+# [*city*]
+# String. City to be used for the SSL certificate
+#
+# [*organization*]
+# String. Organization to be used for the SSL certificate
+#
+# [*email*]
+# String. Email address to be used for the SSL certificate
+#
+# [*compression*]
+# String. Which compression algorithim to use
+# Default: comp-lzo
+# Options: comp-lzo or '' (disable compression)
+#
+# [*dev*]
+# String. Device method
+# Default: tun
+# Options: tun (routed connections), tap (bridged connections)
+#
+# [*user*]
+# String. Group to drop privileges to after startup
+# Default: nobody
+#
+# [*group*]
+# String. User to drop privileges to after startup
+# Default: depends on your $::osfamily
+#
+# [*ipp*]
+# Boolean. Persist ifconfig information to a file to retain client IP
+# addresses between sessions
+# Default: false
+#
+# [*local*]
+# String. Interface for openvpn to bind to.
+# Default: $::ipaddress_eth0
+# Options: An IP address or '' to bind to all ip addresses
+#
+# [*logfile*]
+# String. Logfile for this openvpn server
+# Default: false
+# Options: false (syslog) or log file name
+#
+# [*port*]
+# Integer. The port the openvpn server service is running on
+# Default: 1194
+#
+# [*proto*]
+# String. What IP protocol is being used.
+# Default: tcp
+# Options: tcp or udp
+#
+# [*status_log*]
+# String. Logfile for periodic dumps of the vpn service status
+# Default: "${name}/openvpn-status.log"
+#
+# [*server*]
+# String. Network to assign client addresses out of
+# Default: None. Required in tun mode, not in tap mode
+#
+# [*push*]
+# Array. Options to push out to the client. This can include routes, DNS
+# servers, DNS search domains, and many other options.
+# Default: []
+#
+#
+# === Examples
+#
+# openvpn::client {
+# 'my_user':
+# server => 'contractors',
+# remote_host => 'vpn.mycompany.com'
+# }
+#
+# * Removal:
+# Manual process right now, todo for the future
+#
+#
+# === Authors
+#
+# * Raffael Schmid <mailto:raffael@yux.ch>
+# * John Kinsella <mailto:jlkinsel@gmail.com>
+# * Justin Lambert <mailto:jlambert@letsevenup.com>
+#
+# === License
+#
+# Copyright 2013 Raffael Schmid, <raffael@yux.ch>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+define openvpn::server(
+ $country,
+ $province,
+ $city,
+ $organization,
+ $email,
+ $compression = 'comp-lzo',
+ $dev = 'tun0',
+ $user = 'nobody',
+ $group = false,
+ $ipp = false,
+ $ip_pool = [],
+ $local = $::ipaddress_eth0,
+ $logfile = false,
+ $port = '1194',
+ $proto = 'tcp',
+ $status_log = "${name}/openvpn-status.log",
+ $server = '',
+ $push = []
+) {
+
+ include openvpn
+ Class['openvpn::install'] ->
+ Openvpn::Server[$name] ~>
+ Class['openvpn::service']
+
+ $tls_server = $proto ? {
+ /tcp/ => true,
+ default => false
+ }
+
+ $group_to_set = $group ? {
+ false => $openvpn::params::group,
+ default => $group
+ }
+
+ file {
+ ["/etc/openvpn/${name}", "/etc/openvpn/${name}/client-configs", "/etc/openvpn/${name}/download-configs" ]:
+ ensure => directory;
+ }
+
+ exec {
+ "copy easy-rsa to openvpn config folder ${name}":
+ command => "/bin/cp -r ${openvpn::params::easyrsa_source} /etc/openvpn/${name}/easy-rsa",
+ creates => "/etc/openvpn/${name}/easy-rsa",
+ notify => Exec["fix_easyrsa_file_permissions_${name}"],
+ require => File["/etc/openvpn/${name}"];
+ }
+
+ exec {
+ "fix_easyrsa_file_permissions_${name}":
+ refreshonly => true,
+ command => "/bin/chmod 755 /etc/openvpn/${name}/easy-rsa/*";
+ }
+
+ file {
+ "/etc/openvpn/${name}/easy-rsa/vars":
+ ensure => present,
+ content => template('openvpn/vars.erb'),
+ require => Exec["copy easy-rsa to openvpn config folder ${name}"];
+ }
+
+ file {
+ "/etc/openvpn/${name}/easy-rsa/openssl.cnf":
+ require => Exec["copy easy-rsa to openvpn config folder ${name}"];
+ }
+
+ if $openvpn::params::link_openssl_cnf == true {
+ File["/etc/openvpn/${name}/easy-rsa/openssl.cnf"] {
+ ensure => link,
+ target => "/etc/openvpn/${name}/easy-rsa/openssl-1.0.0.cnf"
+ }
+ }
+
+ exec {
+ "generate dh param ${name}":
+ command => '. ./vars && ./clean-all && ./build-dh',
+ cwd => "/etc/openvpn/${name}/easy-rsa",
+ creates => "/etc/openvpn/${name}/easy-rsa/keys/dh1024.pem",
+ provider => 'shell',
+ require => File["/etc/openvpn/${name}/easy-rsa/vars"];
+
+ "initca ${name}":
+ command => '. ./vars && ./pkitool --initca',
+ cwd => "/etc/openvpn/${name}/easy-rsa",
+ creates => "/etc/openvpn/${name}/easy-rsa/keys/ca.key",
+ provider => 'shell',
+ require => [ Exec["generate dh param ${name}"], File["/etc/openvpn/${name}/easy-rsa/openssl.cnf"] ];
+
+ "generate server cert ${name}":
+ command => '. ./vars && ./pkitool --server server',
+ cwd => "/etc/openvpn/${name}/easy-rsa",
+ creates => "/etc/openvpn/${name}/easy-rsa/keys/server.key",
+ provider => 'shell',
+ require => Exec["initca ${name}"];
+ }
+
+ file {
+ "/etc/openvpn/${name}/keys":
+ ensure => link,
+ target => "/etc/openvpn/${name}/easy-rsa/keys",
+ require => Exec["copy easy-rsa to openvpn config folder ${name}"];
+ }
+
+ if $::osfamily == 'Debian' {
+ concat::fragment {
+ "openvpn.default.autostart.${name}":
+ content => "AUTOSTART=\"\$AUTOSTART ${name}\"\n",
+ target => '/etc/default/openvpn',
+ order => 10;
+ }
+ }
+
+ file {
+ "/etc/openvpn/${name}.conf":
+ owner => root,
+ group => root,
+ mode => '0444',
+ content => template('openvpn/server.erb');
+ }
+}
diff --git a/puppet/modules/openvpn/manifests/service.pp b/puppet/modules/openvpn/manifests/service.pp
new file mode 100644
index 00000000..54e8db7d
--- /dev/null
+++ b/puppet/modules/openvpn/manifests/service.pp
@@ -0,0 +1,36 @@
+# == Class: openvpn::config
+#
+# This class maintains the openvpn service
+#
+#
+# === Examples
+#
+# This class should not be directly invoked
+#
+# === Authors
+#
+# * Raffael Schmid <mailto:raffael@yux.ch>
+# * John Kinsella <mailto:jlkinsel@gmail.com>
+# * Justin Lambert <mailto:jlambert@letsevenup.com>
+#
+# === License
+#
+# Copyright 2013 Raffael Schmid, <raffael@yux.ch>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# lied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+class openvpn::service {
+ service {
+ 'openvpn':
+ ensure => running,
+ enable => true,
+ hasrestart => true,
+ hasstatus => true;
+ }
+}