diff --git a/modules/wireguard/manifests/init.pp b/modules/wireguard/manifests/init.pp new file mode 100644 index 0000000..64c19c6 --- /dev/null +++ b/modules/wireguard/manifests/init.pp @@ -0,0 +1,27 @@ +# manage wireguard interfaces via wg-quick +class wireguard ( + Boolean $manage_package = true, + String $package_name = 'wireguard-tools', + Hash $interfaces = {}, +) { + + if $manage_package { + package { $package_name: + ensure => installed, + before => File['/etc/wireguard'], + } + } + + file { '/etc/wireguard': + ensure => directory, + owner => 'root', + group => 'root', + mode => '0700', + } + + $interfaces.each |String $iface, Hash $data| { + wireguard::interface { $iface: + * => $data, + } + } +} diff --git a/modules/wireguard/manifests/interface.pp b/modules/wireguard/manifests/interface.pp new file mode 100644 index 0000000..516d4be --- /dev/null +++ b/modules/wireguard/manifests/interface.pp @@ -0,0 +1,40 @@ +# manage one wg-quick interface; without private_key, the existing /etc/wireguard/.key is loaded via PostUp +define wireguard::interface ( + Array[Stdlib::IP::Address] $addresses, + Optional[Stdlib::Port] $listen_port = undef, + Optional[Integer[1280, 9000]] $mtu = undef, + Optional[Variant[String, Sensitive[String]]] $private_key = undef, + Array[Hash] $peers = [], +) { + + $conf = "/etc/wireguard/${name}.conf" + $key = $private_key ? { + Sensitive => $private_key.unwrap, + default => $private_key, + } + + file { $conf: + ensure => file, + owner => 'root', + group => 'root', + mode => '0600', + content => Sensitive(template('wireguard/wg.conf.erb')), + show_diff => false, + notify => Exec["wireguard_syncconf_${name}"], + } + + service { "wg-quick@${name}": + ensure => running, + enable => true, + require => File[$conf], + } + + # syncconf applies peer/key changes without bouncing the tunnel; address/mtu changes need a manual restart + exec { "wireguard_syncconf_${name}": + command => "/bin/bash -c 'wg syncconf ${name} <(wg-quick strip ${name})'", + onlyif => "/usr/sbin/ip link show ${name}", + path => ['/usr/bin', '/usr/sbin', '/bin', '/sbin'], + refreshonly => true, + require => Service["wg-quick@${name}"], + } +} diff --git a/modules/wireguard/templates/wg.conf.erb b/modules/wireguard/templates/wg.conf.erb new file mode 100644 index 0000000..b9e8066 --- /dev/null +++ b/modules/wireguard/templates/wg.conf.erb @@ -0,0 +1,31 @@ +# THIS FILE IS MANAGED BY PUPPET +[Interface] +<% @addresses.each do |addr| -%> +Address = <%= addr %> +<% end -%> +<% if @listen_port -%> +ListenPort = <%= @listen_port %> +<% end -%> +<% if @mtu -%> +MTU = <%= @mtu %> +<% end -%> +<% if @key -%> +PrivateKey = <%= @key %> +<% else -%> +PostUp = wg set %i private-key /etc/wireguard/%i.key +<% end -%> +<% @peers.each do |peer| -%> + +[Peer] +PublicKey = <%= peer['public_key'] %> +<% if peer['preshared_key'] -%> +PresharedKey = <%= peer['preshared_key'].respond_to?(:unwrap) ? peer['preshared_key'].unwrap : peer['preshared_key'] %> +<% end -%> +AllowedIPs = <%= Array(peer['allowed_ips']).join(', ') %> +<% if peer['endpoint'] -%> +Endpoint = <%= peer['endpoint'] %> +<% end -%> +<% if peer['persistent_keepalive'] -%> +PersistentKeepalive = <%= peer['persistent_keepalive'] %> +<% end -%> +<% end -%>