Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add wg quick as another provider for interfaces #54

Merged
merged 12 commits into from
Aug 11, 2022
56 changes: 29 additions & 27 deletions manifests/interface.pp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# @summary manages a wireguard setup
#
# @param interface the title of the defined resource, will be used for the wg interface
# @param ensure will ensure that the files for the provider will be present or absent
# @param input_interface ethernet interface where the wireguard packages will enter the system, used for firewall rules
# @param manage_firewall if true, a ferm rule will be created
# @param dport destination for firewall rules / where our wg instance will listen on. defaults to the last digits from the title
Expand All @@ -17,6 +18,7 @@
# @param routes different routes for the systemd-networkd configuration
# @param private_key Define private key which should be used for this interface, if not provided a private key will be generated
# @param preshared_key Define preshared key for the remote peer
# @param provider The specific backend to use for this `wireguard::interface` resource
#
# @author Tim Meusel <[email protected]>
# @author Sebastian Rakel <[email protected]>
Expand Down Expand Up @@ -78,6 +80,7 @@
# }
#
define wireguard::interface (
Enum['present', 'absent'] $ensure = 'present',
Wireguard::Peers $peers = [],
Optional[String[1]] $endpoint = undef,
Integer[0, 65535] $persistent_keepalive = 0,
Expand All @@ -94,6 +97,7 @@
Array[Hash[String[1], Variant[String[1], Boolean]]] $routes = [],
Optional[String[1]] $private_key = undef,
Optional[String[1]] $preshared_key = undef,
Enum['systemd', 'wgquick'] $provider = 'systemd',
) {
require wireguard

Expand Down Expand Up @@ -172,32 +176,30 @@
$peer = []
}

systemd::network { "${interface}.netdev":
content => epp("${module_name}/netdev.epp", {
'interface' => $interface,
'dport' => $dport,
'description' => $description,
'mtu' => $mtu,
'peers' => $peers + $peer,
}),
restart_service => true,
owner => 'root',
group => 'systemd-network',
mode => '0440',
require => File["/etc/wireguard/${interface}"],
}

$network_epp_params = {
'interface' => $interface,
'addresses' => $addresses,
'routes' => $routes,
}

systemd::network { "${interface}.network":
content => epp("${module_name}/network.epp", $network_epp_params),
restart_service => true,
owner => 'root',
group => 'systemd-network',
mode => '0440',
case $provider {
'systemd': {
wireguard::provider::systemd { $interface :
ensure => $ensure,
interface => $interface,
peers => $peers + $peer,
dport => $dport,
addresses => $addresses,
description => $description,
mtu => $mtu,
routes => $routes,
}
}
'wgquick': {
wireguard::provider::wgquick { $interface :
ensure => $ensure,
interface => $interface,
peers => $peers + $peer,
dport => $dport,
addresses => $addresses,
}
}
default: {
fail("provider ${provider} not supported")
}
}
}
51 changes: 51 additions & 0 deletions manifests/provider/systemd.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# @summary Manage the systemd components of a wireguard setup
# @api private
#
define wireguard::provider::systemd (
String[1] $interface = $title,
Enum['present', 'absent'] $ensure = 'present',
Wireguard::Peers $peers = [],
Integer[1024, 65000] $dport = Integer(regsubst($title, '^\D+(\d+)$', '\1')),
Array[Hash[String,Variant[Stdlib::IP::Address::V4::CIDR,Stdlib::IP::Address::V6::CIDR]]] $addresses = [],
Optional[String[1]] $description = undef,
Optional[Integer[1280, 9000]] $mtu = undef,
Array[Hash[String[1], Variant[String[1], Boolean]]] $routes = [],
) {
assert_private()

$systemd_ensure = $ensure ? {
'present' => 'file',
default => $ensure,
}

systemd::network { "${interface}.netdev":
ensure => $systemd_ensure,
content => epp("${module_name}/netdev.epp", {
'interface' => $interface,
'dport' => $dport,
'description' => $description,
'mtu' => $mtu,
'peers' => $peers,
}),
restart_service => true,
owner => 'root',
group => 'systemd-network',
mode => '0440',
require => File["/etc/wireguard/${interface}"],
}

$network_epp_params = {
'interface' => $interface,
'addresses' => $addresses,
'routes' => $routes,
}

systemd::network { "${interface}.network":
ensure => $systemd_ensure,
content => epp("${module_name}/network.epp", $network_epp_params),
restart_service => true,
owner => 'root',
group => 'systemd-network',
mode => '0440',
}
}
25 changes: 25 additions & 0 deletions manifests/provider/wgquick.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# @summary Manage the wg quick components of a wireguard setup
# @api private
#
define wireguard::provider::wgquick (
String[1] $interface = $title,
Enum['present', 'absent'] $ensure = 'present',
Wireguard::Peers $peers = [],
Integer[1024, 65000] $dport = Integer(regsubst($title, '^\D+(\d+)$', '\1')),
Array[Hash[String,Variant[Stdlib::IP::Address::V4::CIDR,Stdlib::IP::Address::V6::CIDR]]] $addresses = [],
) {
assert_private()
$params = {
'interface' => $interface,
'dport' => $dport,
'peers' => $peers,
'addresses' => $addresses,
}

file { "/etc/wireguard/${interface}.conf":
ensure => $ensure,
content => epp("${module_name}/wireguard_conf.epp", $params),
owner => 'root',
mode => '0600',
}
}
41 changes: 41 additions & 0 deletions spec/acceptance/init_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,45 @@
end
end
end

context 'with wg-quick' do
let :facts do
facts
end

it 'work with no errors' do
pp = <<-EOS
wireguard::interface { 'tun0':
sebastianrakel marked this conversation as resolved.
Show resolved Hide resolved
manage_firewall => false,
dport => 51820,
destination_addresses => [$facts['networking']['ip']],
addresses => [{'Address' => '192.0.2.1/24'}],
provider => 'wgquick',
peers => [
{
public_key => 'hZC2VwCilfF9k9nQC6a86xOBFKaqdAgy123dkA6Z008=',
allowed_ips => ['192.0.2.3'],
}
],
}

wireguard::interface { 'tun1':
manage_firewall => false,
dport => 51821,
destination_addresses => [$facts['networking']['ip']],
addresses => [{'Address' => '192.0.3.1/24'}],
provider => 'wgquick',
peers => [
{
public_key => 'hZC2VwCilfF9k9nQC6a86xOBFKaqdAgy123dkA6Z008=',
allowed_ips => ['192.0.3.3'],
}
],
}
EOS

apply_manifest(pp, catch_failures: true)
apply_manifest(pp, catch_changes: true)
end
end
end
23 changes: 23 additions & 0 deletions spec/defines/interface_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,29 @@ class {"systemd":
it { is_expected.to contain_file("/etc/systemd/network/#{title}.network").with_content(%r{Address=fe80::ade1/64}) }
it { is_expected.not_to contain_ferm__rule("allow_wg_#{title}") }
end

context 'wgquick with required params (public_key) and without firewall rules' do
let :params do
{
public_key: 'blabla==',
endpoint: 'wireguard.example.com:1234',
manage_firewall: false,
# we need to set destination_addresses to overwrite the default
# that would configure IPv4+IPv6, but GHA doesn't provide IPv6 for us
destination_addresses: [facts[:networking]['ip'],],
provider: 'wgquick',
}
end

it { is_expected.to compile.with_all_deps }
it { is_expected.to contain_class('wireguard') }
it { is_expected.to contain_exec("generate private key #{title}") }
it { is_expected.to contain_exec("generate public key #{title}") }
it { is_expected.to contain_file("/etc/wireguard/#{title}.pub") }
it { is_expected.to contain_file("/etc/wireguard/#{title}") }
it { is_expected.to contain_file("/etc/wireguard/#{title}.conf") }
it { is_expected.not_to contain_ferm__rule("allow_wg_#{title}") }
end
end
end
end
31 changes: 31 additions & 0 deletions templates/wireguard_conf.epp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<%- |
String[1] $interface,
Stdlib::Port $dport,
Wireguard::Peers $peers,
Array[Hash] $addresses,
| -%>
sebastianrakel marked this conversation as resolved.
Show resolved Hide resolved
# THIS FILE IS MANAGED BY PUPPET
[Interface]
<% $addresses.each |$address| { -%>
Address = <%= $address['Address'] %>
<% } -%>
ListenPort = <%= $dport %>
PostUp = wg set %i private-key /etc/wireguard/<%= $interface %>
<% $peers.each |$peer| { -%>

<% if $peer['description'] { -%>
# <%= $peer['description'] %>
<% } -%>
[Peer]
PublicKey=<%= $peer['public_key'] %>
<% if $peer['endpoint'] { -%>
Endpoint=<%= $peer['endpoint'] %>
<% } -%>
<% if $peer['preshared_key'] { -%>
PresharedKey=<%= $peer['preshared_key'] %>
<% } -%>
PersistentKeepalive=<%= pick($peer['persistent_keepalive'], 0) %>
<% pick($peer['allowed_ips'], ['fe80::/64', 'fd00::/8', '0.0.0.0/0']).each |$allowed_ip| { -%>
AllowedIPs=<%= $allowed_ip %>
<% } -%>
<% } -%>