--- /dev/null
+# an ipsec peer, another node to connect to
+define ipsec::peer(
+ $ipsec_conf_file,
+ $ipsec_secrets_file,
+
+ $local_name,
+ $local_ipaddress,
+ $peer_name,
+ $peer_ipaddress,
+
+ $local_networks = [],
+ $peer_networks = [],
+
+ $network_name = 'ipsec',
+) {
+ $leftsubnet = $local_networks ? {
+ [] => '',
+ default => "leftsubnet = ${$local_networks.join(', ')}"
+ }
+ $rightsubnet = $peer_networks ? {
+ [] => '',
+ default => "rightsubnet = ${$peer_networks.join(', ')}"
+ }
+ concat::fragment { "${network_name}::${ipsec_conf_file}::${name}":
+ target => $ipsec_conf_file,
+ content => @("EOF"),
+ # peer ${name}
+ conn ${network_name}::${peer_name}
+ # left is us (local, ${local_name})
+ left = ${local_ipaddress}
+ ${leftsubnet}
+
+ # right is our peer (remote, ${peer_name})
+ right = ${peer_ipaddress}
+ ${rightsubnet}
+
+ auto=route
+ | EOF
+ }
+
+ # create the data portion for the key derivation function
+ #
+ # It needs to be the same data on both ends of a connection, so the
+ # corresponding secrets entry at the peer gets the same PSK. We do
+ # this by putting the peer's info and our info in some arbitrary,
+ # yet canonical order by sorting.
+ $ipsec_psk_data = ("${local_name}(${local_ipaddress})" < "${peer_name}(${peer_ipaddress})") ? {
+ true => "ipsec-peer-psk-${network_name}-${local_name}(${local_ipaddress})-${peer_name}(${peer_ipaddress})",
+ false => "ipsec-peer-psk-${network_name}-${peer_name}(${peer_ipaddress})-${local_name}(${local_ipaddress})"
+ }
+ $ipsec_psk = hkdf('/etc/puppet/secret', $ipsec_psk_data)
+ concat::fragment { "${network_name}::${ipsec_secrets_file}::${name}":
+ target => $ipsec_secrets_file,
+ content => @("EOF"),
+ # peer ${peer_name}
+ ${peer_ipaddress} : PSK "${ipsec_psk}"
+ | EOF
+ }
+
+ ferm::rule { "${network_name}-${name}":
+ description => "allow ipsec protocols for peer ${peer_name}",
+ domain => '(ip ip6)',
+ chain => 'ipsec-peers',
+ rule => "saddr ${peer_ipaddress} ACCEPT",
+ }
+}