diff --git a/Cargo.lock b/Cargo.lock index 683795b94..5db884627 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -137,6 +137,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "bitflags" version = "1.3.2" @@ -761,6 +767,7 @@ name = "netavark" version = "1.3.1-dev" dependencies = [ "anyhow", + "base64", "chrono", "clap", "env_logger", @@ -771,7 +778,9 @@ dependencies = [ "libc", "log", "netlink-packet-core", + "netlink-packet-generic", "netlink-packet-route", + "netlink-packet-wireguard", "netlink-sys", "nix 0.25.0", "rand", @@ -797,6 +806,19 @@ dependencies = [ "netlink-packet-utils", ] +[[package]] +name = "netlink-packet-generic" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94a5d5ed7a2e8303cde48c4c75b9cbe004d1df98bdd0183aea8f4db7f010cb00" +dependencies = [ + "anyhow", + "byteorder", + "libc", + "netlink-packet-core", + "netlink-packet-utils", +] + [[package]] name = "netlink-packet-route" version = "0.13.0" @@ -823,6 +845,20 @@ dependencies = [ "thiserror", ] +[[package]] +name = "netlink-packet-wireguard" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ffa5ccfab369b38b5aed9dabe51b62b39bc9c80de7bd1213c5a8cdae03c4" +dependencies = [ + "anyhow", + "byteorder", + "libc", + "log", + "netlink-packet-generic", + "netlink-packet-utils", +] + [[package]] name = "netlink-sys" version = "0.8.3" diff --git a/Cargo.toml b/Cargo.toml index 5a13b541d..15c2c4b42 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,8 +38,12 @@ zvariant = "3.4.1" sha2 = "0.10.6" netlink-packet-route = "0.13" netlink-packet-core = "0.4.2" +netlink-packet-wireguard = "0.2.1" +netlink-packet-generic = "0.3.1" fs2 = "0.4.3" netlink-sys = "0.8.3" +base64 = "0.13.1" + [build-dependencies] chrono = { version = "0.4.22", default-features = false, features = ["clock"] } diff --git a/src/commands/setup.rs b/src/commands/setup.rs index 48fb2e8c0..ea21413ae 100644 --- a/src/commands/setup.rs +++ b/src/commands/setup.rs @@ -66,9 +66,11 @@ impl Setup { let (mut hostns, mut netns) = core_utils::open_netlink_sockets(&self.network_namespace_path)?; + let (mut generic_hostns, mut generic_netns) = + core_utils::open_generic_netlink_sockets(&self.network_namespace_path)?; // setup loopback, it should be safe to assume that 1 is the loopback index - netns.netlink.set_up(LinkID::ID(1))?; + netns.netlink.as_mut().unwrap().set_up(LinkID::ID(1))?; let mut drivers = Vec::with_capacity(network_options.network_info.len()); @@ -105,25 +107,36 @@ impl Setup { // Only now after we validated all drivers we setup each. // If there is an error we have to tear down all previous drivers. for (i, driver) in drivers.iter().enumerate() { - let (status, aardvark_entry) = - match driver.setup((&mut hostns.netlink, &mut netns.netlink)) { - Ok((s, a)) => (s, a), - Err(e) => { - // now teardown the already setup drivers - for dri in drivers.iter().take(i) { - match dri.teardown((&mut hostns.netlink, &mut netns.netlink)) { - Ok(_) => {} - Err(e) => { - error!( + let (status, aardvark_entry) = match driver.setup( + ( + &mut hostns.netlink.as_mut().unwrap(), + &mut netns.netlink.as_mut().unwrap(), + ), + ( + &mut generic_hostns.netlink_generic.as_mut().unwrap(), + &mut generic_netns.netlink_generic.as_mut().unwrap(), + ), + ) { + Ok((s, a)) => (s, a), + Err(e) => { + // now teardown the already setup drivers + for dri in drivers.iter().take(i) { + match dri.teardown(( + &mut hostns.netlink.as_mut().unwrap(), + &mut netns.netlink.as_mut().unwrap(), + )) { + Ok(_) => {} + Err(e) => { + error!( "failed to cleanup previous networks after setup failed: {}", e ) - } - }; - } - return Err(e); + } + }; } - }; + return Err(e); + } + }; let _ = response.insert(driver.network_name(), status); if let Some(a) = aardvark_entry { diff --git a/src/commands/teardown.rs b/src/commands/teardown.rs index 42a472275..c5467960a 100644 --- a/src/commands/teardown.rs +++ b/src/commands/teardown.rs @@ -108,7 +108,10 @@ impl Teardown { } }; - match driver.teardown((&mut hostns.netlink, &mut netns.netlink)) { + match driver.teardown(( + &mut hostns.netlink.as_mut().unwrap(), + &mut netns.netlink.as_mut().unwrap(), + )) { Ok(_) => {} Err(err) => { error_list.push(err); diff --git a/src/network/NOTES.md b/src/network/NOTES.md new file mode 100644 index 000000000..36a033266 --- /dev/null +++ b/src/network/NOTES.md @@ -0,0 +1,20 @@ +- https://docs.rs/ipnet/2.5.0/ipnet/enum.IpSubnets.html + - can be used to get smallest subset + +- properly parse config +- set up interface + +## To change +create network interface name from podman + +## To test +- interface config without + - address + - private key +- peer configs without + - allowedIPs + - publickey +- config must be readable +- Interface is up +- routes match the allowedIPs settings + diff --git a/src/network/bridge.rs b/src/network/bridge.rs index 55501c086..3762c3d8d 100644 --- a/src/network/bridge.rs +++ b/src/network/bridge.rs @@ -22,7 +22,7 @@ use super::{ internal_types::{ IPAMAddresses, PortForwardConfig, SetupNetwork, TearDownNetwork, TeardownPortForward, }, - netlink, + netlink, netlink_generic, types::StatusBlock, }; @@ -93,6 +93,7 @@ impl driver::NetworkDriver for Bridge<'_> { fn setup( &self, netlink_sockets: (&mut netlink::Socket, &mut netlink::Socket), + _netlink_generic_sockets: (&mut netlink_generic::Socket, &mut netlink_generic::Socket), ) -> NetavarkResult<(StatusBlock, Option)> { let data = match &self.data { Some(d) => d, diff --git a/src/network/constants.rs b/src/network/constants.rs index 67eb235c2..264d464ab 100644 --- a/src/network/constants.rs +++ b/src/network/constants.rs @@ -10,6 +10,7 @@ pub const IPAM_NONE: &str = "none"; pub const DRIVER_BRIDGE: &str = "bridge"; pub const DRIVER_MACVLAN: &str = "macvlan"; +pub const DRIVER_WIREGUARD: &str = "wireguard"; pub const OPTION_ISOLATE: &str = "isolate"; pub const OPTION_MTU: &str = "mtu"; diff --git a/src/network/core_utils.rs b/src/network/core_utils.rs index 2f0c45d6e..afc6fe015 100644 --- a/src/network/core_utils.rs +++ b/src/network/core_utils.rs @@ -20,6 +20,7 @@ use std::str::FromStr; use sysctl::{Sysctl, SysctlError}; use super::netlink; +use super::netlink_generic; pub struct CoreUtils { pub networkns: String, @@ -273,7 +274,8 @@ pub struct NamespaceOptions { /// as long as the File object is valid pub file: File, pub fd: RawFd, - pub netlink: netlink::Socket, + pub netlink: Option, + pub netlink_generic: Option, } pub fn open_netlink_sockets( @@ -296,12 +298,46 @@ pub fn open_netlink_sockets( NamespaceOptions { file: hostns.0, fd: hostns.1, - netlink: host_socket, + netlink: Some(host_socket), + netlink_generic: None, }, NamespaceOptions { file: netns.0, fd: netns.1, - netlink: netns_sock, + netlink: Some(netns_sock), + netlink_generic: None, + }, + )) +} + +pub fn open_generic_netlink_sockets( + netns_path: &str, +) -> NetavarkResult<(NamespaceOptions, NamespaceOptions)> { + let netns = open_netlink_socket(netns_path).wrap("open container netns")?; + let hostns = open_netlink_socket("/proc/self/ns/net").wrap("open host netns")?; + + let host_socket = netlink_generic::Socket::new().wrap("host netlink socket")?; + + exec_netns!( + hostns.1, + netns.1, + res, + netlink_generic::Socket::new().wrap("netns netlink socket") + ); + + let netns_sock = res?; + Ok(( + NamespaceOptions { + file: hostns.0, + fd: hostns.1, + netlink: None, + netlink_generic: Some(host_socket), + }, + NamespaceOptions { + file: netns.0, + fd: netns.1, + netlink: None, + netlink_generic: Some(netns_sock), }, )) } diff --git a/src/network/driver.rs b/src/network/driver.rs index 81bf2ed81..58b971976 100644 --- a/src/network/driver.rs +++ b/src/network/driver.rs @@ -10,8 +10,9 @@ use super::{ bridge::Bridge, constants, macvlan::MacVlan, - netlink, + netlink, netlink_generic, types::{Network, PerNetworkOptions, PortMapping, StatusBlock}, + wireguard::WireGuard, }; use std::os::unix::io::RawFd; @@ -35,6 +36,7 @@ pub trait NetworkDriver { fn setup( &self, netlink_sockets: (&mut netlink::Socket, &mut netlink::Socket), + netlink_generic_sockets: (&mut netlink_generic::Socket, &mut netlink_generic::Socket), ) -> NetavarkResult<(StatusBlock, Option)>; /// teardown the network interfaces/firewall rules for this driver fn teardown( @@ -50,6 +52,7 @@ pub fn get_network_driver(info: DriverInfo) -> NetavarkResult Ok(Box::new(Bridge::new(info))), constants::DRIVER_MACVLAN => Ok(Box::new(MacVlan::new(info))), + constants::DRIVER_WIREGUARD => Ok(Box::new(WireGuard::new(info))), _ => Err(NetavarkError::Message(format!( "unknown network driver {}", diff --git a/src/network/macvlan.rs b/src/network/macvlan.rs index a0ec302da..cabd69f17 100644 --- a/src/network/macvlan.rs +++ b/src/network/macvlan.rs @@ -17,6 +17,7 @@ use super::{ driver::{self, DriverInfo}, internal_types::IPAMAddresses, netlink::{self, CreateLinkOptions}, + netlink_generic, types::{NetInterface, StatusBlock}, }; @@ -94,6 +95,7 @@ impl driver::NetworkDriver for MacVlan<'_> { fn setup( &self, netlink_sockets: (&mut netlink::Socket, &mut netlink::Socket), + _netlink_generic_sockets: (&mut netlink_generic::Socket, &mut netlink_generic::Socket), ) -> Result<(StatusBlock, Option), NetavarkError> { let data = match &self.data { Some(d) => d, diff --git a/src/network/mod.rs b/src/network/mod.rs index 52c4b89e9..0b7f1aa3d 100644 --- a/src/network/mod.rs +++ b/src/network/mod.rs @@ -16,6 +16,8 @@ pub mod driver; pub mod internal_types; pub mod macvlan; pub mod netlink; +pub mod netlink_generic; +pub mod wireguard; impl types::NetworkOptions { pub fn load(path: Option) -> NetavarkResult { diff --git a/src/network/netlink.rs b/src/network/netlink.rs index 742a12c58..9d3aac77c 100644 --- a/src/network/netlink.rs +++ b/src/network/netlink.rs @@ -171,6 +171,16 @@ impl Socket { Ok(()) } + pub fn set_link_ns(&mut self, link_id: u32, netns_fd: i32) -> NetavarkResult<()> { + let mut msg = LinkMessage::default(); + msg.header.index = link_id; + msg.nlas.push(Nla::NetNsFd(netns_fd)); + + let result = self.make_netlink_request(RtnlMessage::SetLink(msg), NLM_F_ACK)?; + expect_netlink_result!(result, 0); + Ok(()) + } + fn create_addr_msg(link_id: u32, addr: &ipnet::IpNet) -> AddressMessage { let mut msg = AddressMessage::default(); msg.header.index = link_id; diff --git a/src/network/netlink_generic.rs b/src/network/netlink_generic.rs new file mode 100644 index 000000000..58f2c39c6 --- /dev/null +++ b/src/network/netlink_generic.rs @@ -0,0 +1,292 @@ +use crate::{ + error::{ErrorWrap, NetavarkError, NetavarkResult}, + wrap, +}; +use log::trace; +use netlink_packet_core::{NetlinkMessage, NetlinkPayload, NLM_F_ACK, NLM_F_DUMP, NLM_F_REQUEST}; +use netlink_packet_generic::{ + ctrl::{nlas::GenlCtrlAttrs, GenlCtrl, GenlCtrlCmd}, + GenlMessage, +}; +use netlink_packet_wireguard::{nlas::WgDeviceAttrs, Wireguard, WireguardCmd}; + +use netlink_sys::{protocols::NETLINK_GENERIC, SocketAddr}; + +pub struct Socket { + socket: netlink_sys::Socket, + sequence_number: u32, + /// buffer size for reading netlink messages, see NLMSG_GOODSIZE in the kernel + buffer: [u8; 8192], + wireguard_family: Option, +} + +macro_rules! expect_netlink_result { + ($result:expr, $count:expr) => { + if $result.len() != $count { + return Err(NetavarkError::msg(format!( + "{}: unexpected netlink result (got {} result(s), want {})", + function!(), + $result.len(), + $count + ))); + } + }; +} + +/// get the function name of the currently executed function +/// taken from https://stackoverflow.com/a/63904992 +macro_rules! function { + () => {{ + fn f() {} + fn type_name_of(_: T) -> &'static str { + std::any::type_name::() + } + let name = type_name_of(f); + + // Find and cut the rest of the path + match &name[..name.len() - 3].rfind(':') { + Some(pos) => &name[pos + 1..name.len() - 3], + None => &name[..name.len() - 3], + } + }}; +} + +impl Socket { + pub fn new() -> NetavarkResult { + let mut socket = wrap!(netlink_sys::Socket::new(NETLINK_GENERIC), "open")?; + let kernel_addr = &SocketAddr::new(0, 0); + wrap!(socket.bind_auto(), "bind")?; + wrap!(socket.connect(kernel_addr), "connect")?; + + Ok(Socket { + socket, + sequence_number: 0, + buffer: [0; 8192], + wireguard_family: None, + }) + } + + pub fn set_wireguard_device(&mut self, nlas: Vec) -> NetavarkResult<()> { + let msg: GenlMessage = GenlMessage::from_payload(Wireguard { + cmd: WireguardCmd::SetDevice, + nlas, + }); + let result = self.make_wireguard_request(msg, NLM_F_ACK)?; + expect_netlink_result!(result, 0); + Ok(()) + } + + fn query_family_id(&mut self, family_name: &'static str) -> NetavarkResult { + let genlmsg: GenlMessage = GenlMessage::from_payload(GenlCtrl { + cmd: GenlCtrlCmd::GetFamily, + nlas: vec![GenlCtrlAttrs::FamilyName(family_name.to_owned())], + }); + let mut result = self.make_ctrl_request(genlmsg, true, NLM_F_ACK)?; + expect_netlink_result!(result, 1); + let result: GenlMessage = result.remove(0); + let mut family: Option = None; + for nla in result.payload.nlas { + match nla { + GenlCtrlAttrs::FamilyId(m) => family = Some(m), + _ => (), + }; + } + match family { + Some(fam) => Ok(fam), + None => Err(NetavarkError::msg( + "Unable to resolve netlink family id for WireGuard API packets", + )), + } + } + + fn make_ctrl_request( + &mut self, + msg: GenlMessage, + multi: bool, + flags: u16, + ) -> NetavarkResult>> { + self.send_ctrl(msg, flags).wrap("send to netlink")?; + self.recv_ctrl(multi) + } + + fn make_wireguard_request( + &mut self, + msg: GenlMessage, + flags: u16, + ) -> NetavarkResult>> { + self.send_wireguard(msg, flags).wrap("send to netlink")?; + self.recv_wireguard(flags & NLM_F_DUMP == NLM_F_DUMP) + } + + fn send_wireguard(&mut self, msg: GenlMessage, flags: u16) -> NetavarkResult<()> { + if self.wireguard_family == None { + let family = self + .query_family_id("wireguard") + .expect("Could not resolve family_id for WireGuard netlink API"); + trace!("WireGuard family ID is: {:?}", family); + self.wireguard_family = Some(family); + } + let family = self + .wireguard_family + .expect("WireGuard family was exptected to be queried, but was None"); + let mut nlmsg = NetlinkMessage::from(msg); + + nlmsg.header.flags = NLM_F_REQUEST | flags; + nlmsg.header.sequence_number = { + self.sequence_number += 1; + self.sequence_number + }; + nlmsg.finalize(); + nlmsg.header.message_type = family; + + nlmsg.serialize(&mut self.buffer[..]); + + trace!("send WireGuard netlink packet: {:?}", nlmsg); + self.socket.send(&self.buffer[..nlmsg.buffer_len()], 0)?; + Ok(()) + } + + fn recv_wireguard(&mut self, multi: bool) -> NetavarkResult>> { + let mut offset = 0; + let mut result = Vec::new(); + + // if multi is set we expect a multi part message + loop { + let size = wrap!( + self.socket.recv(&mut &mut self.buffer[..], 0), + "recv from netlink" + )?; + + loop { + let bytes = &self.buffer[offset..]; + let rx_packet: NetlinkMessage> = + NetlinkMessage::deserialize(bytes).map_err(|e| { + NetavarkError::Message(format!( + "failed to deserialize netlink message: {}", + e, + )) + })?; + trace!("read netlink packet: {:?}", rx_packet); + if rx_packet.header.sequence_number != self.sequence_number { + return Err(NetavarkError::msg(format!( + "netlink: sequence_number out of sync (got {}, want {})", + rx_packet.header.sequence_number, self.sequence_number, + ))); + } + + match rx_packet.payload { + NetlinkPayload::Done => return Ok(result), + NetlinkPayload::Error(e) | NetlinkPayload::Ack(e) => { + if e.code != 0 { + return Err(e.into()); + } + return Ok(result); + } + NetlinkPayload::Noop => { + return Err(NetavarkError::msg( + "unimplemented netlink message type NOOP", + )) + } + NetlinkPayload::Overrun(_) => { + return Err(NetavarkError::msg( + "unimplemented netlink message type OVERRUN", + )) + } + NetlinkPayload::InnerMessage(msg) => { + result.push(msg); + if !multi { + return Ok(result); + } + } + }; + + offset += rx_packet.header.length as usize; + if offset == size || rx_packet.header.length == 0 { + offset = 0; + break; + } + } + } + } + + fn send_ctrl(&mut self, msg: GenlMessage, flags: u16) -> NetavarkResult<()> { + let mut nlmsg = netlink_packet_core::NetlinkMessage::from(msg); + + nlmsg.header.flags = NLM_F_REQUEST | flags; + nlmsg.header.sequence_number = { + self.sequence_number += 1; + self.sequence_number + }; + + nlmsg.finalize(); + nlmsg.serialize(&mut self.buffer[..]); + + trace!("sending GenlCtrl netlink msg: {:?}", nlmsg); + self.socket.send(&self.buffer[..nlmsg.buffer_len()], 0)?; + Ok(()) + } + + fn recv_ctrl(&mut self, multi: bool) -> NetavarkResult>> { + let mut offset = 0; + let mut result = Vec::new(); + + // if multi is set we expect a multi part message + loop { + let size = wrap!( + self.socket.recv(&mut &mut self.buffer[..], 0), + "recv from netlink" + )?; + + loop { + let bytes = &self.buffer[offset..]; + let rx_packet: NetlinkMessage> = + NetlinkMessage::deserialize(bytes).map_err(|e| { + NetavarkError::Message(format!( + "failed to deserialize netlink message: {}", + e, + )) + })?; + trace!("read netlink packet: {:?}", rx_packet); + + if rx_packet.header.sequence_number != self.sequence_number { + return Err(NetavarkError::msg(format!( + "netlink: sequence_number out of sync (got {}, want {})", + rx_packet.header.sequence_number, self.sequence_number, + ))); + } + + match rx_packet.payload { + NetlinkPayload::Done => return Ok(result), + NetlinkPayload::Error(e) | NetlinkPayload::Ack(e) => { + if e.code != 0 { + return Err(e.into()); + } + return Ok(result); + } + NetlinkPayload::Noop => { + return Err(NetavarkError::msg( + "unimplemented netlink message type NOOP", + )) + } + NetlinkPayload::Overrun(_) => { + return Err(NetavarkError::msg( + "unimplemented netlink message type OVERRUN", + )) + } + NetlinkPayload::InnerMessage(msg) => { + result.push(msg); + if !multi { + return Ok(result); + } + } + }; + + offset += rx_packet.header.length as usize; + if offset == size || rx_packet.header.length == 0 { + offset = 0; + break; + } + } + } + } +} diff --git a/src/network/types.rs b/src/network/types.rs index e97a9f497..387b02f26 100644 --- a/src/network/types.rs +++ b/src/network/types.rs @@ -107,6 +107,10 @@ pub struct PerNetworkOptions { /// MAC address for the container interface. #[serde(rename = "static_mac")] pub static_mac: Option, + + /// Additional options for a network + #[serde(rename = "options")] + pub options: Option>, } // PortMapping is one or more ports that will be mapped into the container. diff --git a/src/network/wireguard.rs b/src/network/wireguard.rs new file mode 100644 index 000000000..08f0222b2 --- /dev/null +++ b/src/network/wireguard.rs @@ -0,0 +1,674 @@ +use std::net::ToSocketAddrs; +use std::{collections::HashMap, convert::TryInto, net::IpAddr, os::unix::prelude::RawFd}; +use std::{net, vec}; + +use base64::decode; +use ipnet::IpNet; +use log::debug; +use netlink_packet_route::nlas::link::InfoKind; +use netlink_packet_wireguard::constants::{AF_INET, AF_INET6}; +use netlink_packet_wireguard::nlas::{ + WgAllowedIp, WgAllowedIpAttrs, WgDeviceAttrs, WgPeer, WgPeerAttrs, +}; + +use crate::network::netlink::Route; +use crate::network::types::NetInterface; +use crate::{ + dns::aardvark::AardvarkEntry, + error::{ErrorWrap, NetavarkError, NetavarkResult}, +}; + +use super::{ + constants::NO_CONTAINER_INTERFACE_ERROR, + driver::{self, DriverInfo}, + netlink::{self, CreateLinkOptions}, + netlink_generic, + types::StatusBlock, +}; + +// TODO_WG: Document the option +const CONFIG_OPTION: &str = "config"; + +#[derive(Debug)] +struct Peer { + /// IPs that will be forwarded to the Peer + /// and from which traffic is accepted + allowed_ips: Vec, + /// Seconds between Handshakes sent to peer + /// in order to keep the connection alive + /// Optional + persistent_keepalive: Option, + /// Peers public key to verify traffic during crypto routing + public_key: [u8; 32], + preshared_key: Option<[u8; 32]>, + endpoint: Option, +} + +#[derive(Debug)] +struct InternalData { + /// WireGuard interface name + interface_name: String, + /// addresses of the WireGuard interface + addresses: Vec, + /// + private_key: [u8; 32], + /// mtu for the network interface (0 if default) + mtu: u16, + /// WireGuard peers + peers: Vec, + /// Listening Port + /// Optional + port: Option, +} + +pub struct WireGuard<'a> { + info: DriverInfo<'a>, + data: Option, +} + +impl<'a> WireGuard<'a> { + pub fn new(info: DriverInfo<'a>) -> Self { + WireGuard { info, data: None } + } +} + +impl driver::NetworkDriver for WireGuard<'_> { + fn network_name(&self) -> String { + self.info.network.name.clone() + } + + fn validate(&mut self) -> NetavarkResult<()> { + if self.info.per_network_opts.interface_name.is_empty() { + return Err(NetavarkError::msg(NO_CONTAINER_INTERFACE_ERROR)); + } + + let options = match &self.info.per_network_opts.options { + Some(options) => options, + None => { + return Err(NetavarkError::msg( + "no options specified for WireGuard driver", + )) + } + }; + + let config_path = match options.get(CONFIG_OPTION) { + Some(path) => path, + None => { + return Err(NetavarkError::msg( + "no path to WireGuard config file specified", + )) + } + }; + + let data = match parse_config( + config_path, + self.info.per_network_opts.interface_name.clone(), + ) { + Ok(data) => data, + Err(e) => { + return Err(NetavarkError::msg(format!( + "when parsing WireGuard config: {:?}", + e + ))) + } + }; + + // Peer Validation + for (index, peer) in data.peers.iter().enumerate() { + if peer.public_key == [0; 32] { + return Err(NetavarkError::msg(format!( + "invalid WireGuard configuration: Peer #{:?} is missing a PublicKey", + index + ))); + } + if peer.allowed_ips.len() == 0 { + return Err(NetavarkError::msg(format!( + "invalid WireGuard configuration: Peer #{:?} is missing AllowedIPs", + index + ))); + } + } + + // Interface Validation + // will succeed if the interface has an Address and a PrivateKey + if data.private_key == [0; 32] { + return Err(NetavarkError::msg(format!( + "invalid WireGuard configuration: Interface is missing a PrivateKey", + ))); + } + if data.addresses.len() == 0 { + return Err(NetavarkError::msg(format!( + "invalid WireGuard configuration: Interface is missing an Address", + ))); + } + self.data = Some(data); + + Ok(()) + } + + fn setup( + &self, + netlink_sockets: (&mut netlink::Socket, &mut netlink::Socket), + netlink_generic_sockets: (&mut netlink_generic::Socket, &mut netlink_generic::Socket), + ) -> Result<(StatusBlock, Option), NetavarkError> { + let data = match &self.data { + Some(d) => d, + None => return Err(NetavarkError::msg("must call validate() before setup()")), + }; + + debug!("Setup network {}", self.info.network.name); + debug!( + "Container interface name: {} with IP addresses {:?}", + self.info.per_network_opts.interface_name, data.addresses + ); + + let (host_sock, netns_sock) = netlink_sockets; + let (generic_host_sock, generic_netns_sock) = netlink_generic_sockets; + + let interface = create_wireguard_interface( + (host_sock, generic_host_sock), + (netns_sock, generic_netns_sock), + data, + self.info.netns_host, + self.info.netns_container, + )?; + let mut interfaces: HashMap = HashMap::new(); + interfaces.insert( + interface, + NetInterface { + mac_address: "".to_string(), + subnets: None, + }, + ); + + let response = StatusBlock { + dns_server_ips: None, + dns_search_domains: None, + interfaces: Some(interfaces), + }; + Ok((response, None)) + } + + fn teardown( + &self, + netlink_sockets: (&mut netlink::Socket, &mut netlink::Socket), + ) -> NetavarkResult<()> { + netlink_sockets.1.del_link(netlink::LinkID::Name( + self.info.per_network_opts.interface_name.to_string(), + ))?; + Ok(()) + } +} + +fn create_wireguard_interface( + host: (&mut netlink::Socket, &mut netlink_generic::Socket), + netns: (&mut netlink::Socket, &mut netlink_generic::Socket), + data: &InternalData, + hostns_fd: RawFd, + netns_fd: RawFd, +) -> NetavarkResult { + let (host_link_socket, _host_generic_socket) = host; + let (netns_link_socket, netns_generic_socket) = netns; + + let mut create_link_opts = + CreateLinkOptions::new(data.interface_name.to_string(), InfoKind::Wireguard); + create_link_opts.mtu = data.mtu as u32; + + debug!( + "Creating WireGuard interface {}", + data.interface_name.to_string() + ); + + host_link_socket + .create_link(create_link_opts.clone()) + .wrap("create WireGuard interface: {}")?; + + let link = host_link_socket + .get_link(netlink::LinkID::Name(data.interface_name.to_string())) + .wrap("get WireGuard interface")?; + + debug!( + "Moving WireGuard interface {} from namespace {} to container namespace {}", + data.interface_name.to_string(), + hostns_fd, + netns_fd + ); + host_link_socket + .set_link_ns(link.header.index, netns_fd) + .wrap("moving WireGuard interface to container network namespace")?; + + debug!( + "Adding Addresses to WireGuard interface {}", + data.interface_name.to_string() + ); + + for addr in &data.addresses { + netns_link_socket + .add_addr(link.header.index, addr) + .wrap("add ip addr to WireGuard interface")?; + } + + let nlas = generate_wireguard_device_nlas(data); + + debug!( + "Setting up WireGuard interface {}", + data.interface_name.to_string() + ); + netns_generic_socket + .set_wireguard_device(nlas) + .wrap("add WireGuard interface settings")?; + + if data.peers.len() > 0 { + debug!( + "Adding Peers to WireGuard interface {}", + data.interface_name.to_string() + ); + + for peer in data.peers[..].iter() { + let nlas = generate_peer_nlas_for_wireguard_device(&peer, data.interface_name.clone()); + netns_generic_socket + .set_wireguard_device(nlas) + .wrap("add Peer {:?} to WireGuard interface")?; + } + } + + debug!( + "Activating WireGuard interface {}", + data.interface_name.to_string(), + ); + + netns_link_socket + .set_up(netlink::LinkID::Name(data.interface_name.to_string())) + .wrap("set WireGuard interface up")?; + + for peer in data.peers[..].iter() { + let routes = generate_routes_for_peer(&data.addresses, &peer.allowed_ips); + for route in routes { + netns_link_socket.add_route(&route)?; + } + } + + Ok(data.interface_name.clone()) +} + +fn parse_config(path: &String, interface_name: String) -> Result { + // Get configuration data from file + let config_data = match std::fs::read_to_string(path) { + Ok(data) => data, + Err(e) => return Err(format!("problem reading WireGuard config: {:?}", e)), + }; + + // Setup line based parsing + // with empty data structures to store into + // + // Only Peer and Interface sections exists + // [Interface] can only be specified once and subsequent definitions + // will overwrite previously stored data + // + // If a [Peer] section is encountered a new Peer is added + let lines = config_data.lines(); + let mut peers: Vec = vec![]; + let mut interface = InternalData { + interface_name: "".to_string(), + addresses: vec![], + private_key: [0x00; 32], + mtu: 1420, + peers: vec![], + port: None, + }; + let mut interface_section = false; + let mut peer_section = false; + + for (index, line) in lines.into_iter().enumerate() { + if line.trim_start() == "" || line.trim_start().chars().next().unwrap().to_string() == "#" { + continue; + } + if line == "[Interface]" { + interface_section = true; + peer_section = false; + continue; + } + if line == "[Peer]" { + interface_section = false; + peer_section = true; + // Add a new peer to the peers array + // which will be used to store information + // from lines that will be parsed next + peers.push(Peer { + allowed_ips: vec![], + persistent_keepalive: None, + public_key: [0; 32], + preshared_key: None, + endpoint: None, + }); + continue; + } + // splitting once gives key and value. + // Using any other split can conflict with the base64 encoded keys + let (key, value) = match line.split_once("=") { + Some(tuple) => { + let key: String = tuple.0.split_whitespace().collect(); + let value: String = tuple.1.split_whitespace().collect(); + (key, value) + } + None => { + return Err(format!( + "when parsing WireGuard configuration {} on line: {}.", + line, index + )) + } + }; + if key != "" && value == "" { + if value == "" { + return Err(format!( + "when parsing WireGuard configuration {} on line {}. No value provided.", + key, index + )); + } + } + if interface_section { + match key.as_str() { + "Address" => { + let ip_with_cidr = add_cidr_to_ip_addr_if_missing(value.clone()); + let ip: IpNet = match ip_with_cidr.parse() { + Ok(ip) => ip, + Err(e) => { + return Err(format!( + "{:?} when parsing WireGuard interface address: {:?}", + e, value + )) + } + }; + interface.addresses.push(ip) + } + "ListenPort" => { + let port = match value.parse::() { + Ok(port) => port, + Err(e) => { + return Err(format!( + "{:?} when parsing WireGuard interface port: {:?}", + e, value + )); + } + }; + interface.port = Some(port); + } + "PrivateKey" => { + interface.private_key = match decode(value.clone()) { + Ok(key) => match key.try_into() { + Ok(key) => key, + Err(e) => { + return Err(format!( + "{:?} when decoding base64 PrivateKey: {:?}. Is it 32 bytes?", + e, value + )) + } + }, + Err(e) => { + return Err(format!( + "{:?} when decoding base64 PrivateKey: {:?}", + e, value + )) + } + } + } + _ => { + debug!( + "Ignoring key `{}` in WireGuard interface configuration", + key + ); + } + } + } + if peer_section { + let current_peer_index = peers.len() - 1; + let current_peer = &mut peers[current_peer_index]; + match key.as_str() { + "AllowedIPs" => { + let ips = value.split(","); + for ip in ips { + let ip_with_cidr = add_cidr_to_ip_addr_if_missing(ip.to_string()); + let ip: IpNet = match ip_with_cidr.parse() { + Ok(ip) => ip, + Err(e) => { + return Err(format!( + "{:?} when parsing WireGuard peers AllowedIPs: {:?}. Occurs in {:?}", + e, value, ip + )) + } + }; + current_peer.allowed_ips.push(ip); + } + } + "Endpoint" => { + current_peer.endpoint = match parse_endpoint(value.clone()) { + Ok(endpoint) => endpoint, + Err(e) => { + return Err(format!( + "when trying to parse Endpoint {} for peer {}: {:?}", + value, current_peer_index, e + )) + } + } + } + "PublicKey" => { + current_peer.public_key = match decode(value.clone()) { + Ok(key) => match key.try_into() { + Ok(key) => key, + Err(e) => { + return Err(format!( + "{:?} when decoding base64 PublicKey: {:?} for peer {:?}. Is it 32 bytes?", + e, value, current_peer_index + )) + } + }, + Err(e) => { + return Err(format!( + "{:?} when decoding base64 PublicKey: {:?} for peer {:?}", + e, value, current_peer_index + )) + } + } + } + "PresharedKey" => { + current_peer.preshared_key = match decode(value.clone()) { + Ok(key) => match key.try_into() { + Ok(key) => Some(key), + Err(e) => { + return Err(format!( + "{:?} when decoding base64 PresharedKey: {:?} for peer {:?}. Is it 32 bytes?", + e, value, current_peer_index + )) + } + }, + Err(e) => { + return Err(format!( + "{:?} when decoding base64 PresharedKey: {:?} for peer {:?}", + e, value, current_peer_index + )) + } + } + } + "PersistentKeepalive" => { + let keepalive = match value.parse::() { + Ok(keepalive) => keepalive, + Err(e) => { + return Err(format!( + "{:?} when parsing WireGuard peers PersistentKeepalive value: {:?}", + e, value + )); + } + }; + current_peer.persistent_keepalive = Some(keepalive); + } + _ => { + debug!("Ignoring key `{}` in WireGuard peer configuration", key); + } + } + } + } + + interface.interface_name = interface_name; + interface.peers = peers; + + return Ok(interface); +} + +fn add_cidr_to_ip_addr_if_missing(addr: String) -> String { + let mut ip4_cidr = "/32".to_string(); + let mut ip6_cidr = "/128".to_string(); + match addr.split_once('/') { + Some(_) => addr, // CIDR was defined, nothing to do + None => { + // default to a host CIDR + if addr.contains(":") { + ip6_cidr.insert_str(0, &addr); + let ip = ip6_cidr; + return ip; + } else { + ip4_cidr.insert_str(0, &addr); + let ip = ip4_cidr; + return ip; + } + } + } +} + +fn parse_endpoint(addr: String) -> Result, String> { + let (endpoint_addr, endpoint_port) = match addr.split_once(":") { + Some(tuple) => tuple, + None => return Err("incomplete Endpoint address".to_string()), + }; + let port: u16 = match endpoint_port.parse() { + Ok(ip) => ip, + Err(e) => return Err(format!("incorrect port: {}", e)), + }; + + let ip: IpAddr = match endpoint_addr.parse() { + Ok(ip) => ip, + Err(_) => { + // we might have gotten a hostname in the config + // try this next + match addr.to_socket_addrs() { + Ok(mut addr) => match addr.next() { + Some(addr) => addr.ip(), + None => { + return Err(format!("could not parse {:?}", addr)); + } + }, + Err(_) => { + return Err(format!("could not parse {:?}", addr)); + } + } + } + }; + + return Ok(Some(net::SocketAddr::new(ip, port))); +} + +fn generate_wireguard_device_nlas(data: &InternalData) -> Vec { + let mut nlas = vec![ + WgDeviceAttrs::IfName(data.interface_name.to_string()), + WgDeviceAttrs::PrivateKey(data.private_key), + ]; + + match data.port { + Some(port) => nlas.push(WgDeviceAttrs::ListenPort(port)), + None => (), + } + return nlas; +} +fn generate_peer_nlas_for_wireguard_device( + peer: &Peer, + interface_name: String, +) -> Vec { + let mut allowed_ip_nla = vec![]; + for ip in peer.allowed_ips[..].iter() { + let mut family: u16 = AF_INET; + + match ip { + IpNet::V4(_) => (), + IpNet::V6(_) => family = AF_INET6, + } + allowed_ip_nla.push(WgAllowedIp { + 0: vec![ + WgAllowedIpAttrs::IpAddr(ip.network()), + WgAllowedIpAttrs::Cidr(ip.prefix_len()), + WgAllowedIpAttrs::Family(family), + ], + }); + } + let mut wg_peer = WgPeer { + 0: vec![ + WgPeerAttrs::PublicKey(peer.public_key), + WgPeerAttrs::AllowedIps(allowed_ip_nla), + ], + }; + match peer.preshared_key { + Some(key) => wg_peer.0.push(WgPeerAttrs::PresharedKey(key)), + None => (), + } + match peer.persistent_keepalive { + Some(keepalive) => wg_peer.0.push(WgPeerAttrs::PersistentKeepalive(keepalive)), + None => (), + } + match peer.endpoint { + Some(endpoint) => wg_peer.0.push(WgPeerAttrs::Endpoint(endpoint)), + None => (), + } + let nlas = vec![ + WgDeviceAttrs::IfName(interface_name), + WgDeviceAttrs::Peers(vec![wg_peer]), + ]; + return nlas; +} + +fn generate_routes_for_peer( + interface_addresses: &Vec, + allowed_ips: &Vec, +) -> Vec { + let mut routes = vec![]; + for gateway in &interface_addresses[..] { + match gateway { + IpNet::V4(gateway) => { + for dest in &allowed_ips[..] { + match dest { + IpNet::V4(dest) => { + if dest.contains(gateway) || gateway.supernet() == dest.supernet() { + let route: Route = Route::Ipv4 { + dest: dest.clone(), + gw: gateway.addr(), + metric: None, + }; + routes.push(route); + } + } + IpNet::V6(_) => { + continue; + } + } + } + } + IpNet::V6(gateway) => { + for dest in &allowed_ips[..] { + match dest { + IpNet::V4(_) => { + continue; + } + IpNet::V6(dest) => { + if dest.contains(gateway) || gateway.supernet() == dest.supernet() { + let route: Route = Route::Ipv6 { + dest: dest.clone(), + gw: gateway.addr(), + metric: None, + }; + routes.push(route); + } + } + } + } + } + } + } + return routes; +} diff --git a/test/400-wireguard.bats b/test/400-wireguard.bats new file mode 100644 index 000000000..60a61eadf --- /dev/null +++ b/test/400-wireguard.bats @@ -0,0 +1,206 @@ +#!/usr/bin/env bats -*- bats -*- +# +# wireguard driver test +# + +load helpers + +function setup() { + basic_setup +} + +@test "simple WireGuard setup" { + run_netavark --file ${TESTSDIR}/testfiles/wireguard/wireguard.json setup $(get_container_netns_path) + result="$output" + + # check that interface exists + run_in_container_netns ip -j --details link show wg-test + link_info="$output" + assert_json "$link_info" '.[].flags[] | select(.=="UP")' "==" "UP" "Container interface is up" + assert_json "$link_info" ".[].linkinfo.info_kind" "==" "wireguard" "Container interface is a macvlan device" + + # check ip addresses + ipaddr="10.10.0.1/16" + ipaddr2="2001::1/64" + ipaddr3="10.11.1.1/32" + ipaddr4="dd01:129d:3:a992:11da:aa22:93df:1/128" + run_in_container_netns ip addr show wg-test + assert "$output" "=~" "$ipaddr" "WireGuard IPv4 address matches container address" + assert "$output" "=~" "$ipaddr2" "WireGuard IPv6 address matches container address" + assert "$output" "=~" "$ipaddr3" "IPv4 without CIDR was added to container WireGuard interface" + assert "$output" "=~" "$ipaddr4" "IPv6 without CIDR was added to container WireGuard interface" + + # check gateway assignment + run_in_container_netns ip r + assert "$output" "=~" "10.10.0.0/16 dev wg-test proto kernel scope link src 10.10.0.1" "wireguard ipv4 gateways are correctly set up" + assert "$output" "=~" "10.11.1.0/24 via 10.11.1.1 dev wg-test proto static metric 100" "wireguard ipv4 gateways are correctly set up" + run_in_container_netns ip -6 r + assert "$output" "=~" "2001::/64 dev wg-test proto kernel metric 256 pref medium" "wireguard ipv6 gateways are correctly set up" + assert "$output" "=~" "dd01:129d:3:a992:11da:aa22:93df:1 dev wg-test proto kernel metric 256 pref medium" "wireguard ipv6 gateways are correctly set up" + + # check Interface key + # To get the key that is compared here run echo $PRIVATE_KEY | wg pubkey on the PrivateKey from testfiles/wireguard.conf + run_in_container_netns wg + assert "$output" "=~" "private key: \(hidden\)" "WireGuard interface key was correctly set" + assert "$output" "=~" "public key: HIgo9xNzJMWLKASShiTqIybxZ0U3wGLiUeJ1PKf8ykw=" "WireGuard interface key was correctly set" + + # check WireGuard Port + assert "$output" "=~" "listening port: 51820" "WireGuard port was correctly set" + + # check IPv4 peer + assert "$output" "=~" "peer: xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=" "WireGuard peer was added" + assert "$output" "=~" "preshared key: \(hidden\)" "WireGuard peer preshared key was correctly set" + assert "$output" "=~" "allowed ips: 10.10.0.2/32, 10.11.1.0/24" "WireGuard peer allowed IPs were correctly set" + assert "$output" "=~" "endpoint: 123.45.67.89:12345" "WireGuard peer endpoint was correctly set" + + # check IPv6 peer + assert "$output" "=~" "peer: gN65BkIKy1eCE9pP1wdc8ROUtkHLF2PfAqYdyYBz6EA=" "WireGuard peer was added" + assert "$output" "=~" "allowed ips: ffff:ffff::/32" "WireGuard peer allowed IPs were correctly set" + + # check mixed IPv6, IPv4 peer + assert "$output" "=~" "peer: fMyt1P5L9yGCY41Zk8NviMqqj0S8NS5Ta9GtqwHa1Sw=" "WireGuard peer was added" + assert "$output" "=~" "allowed ips: ffff::abcd/128, 192.168.0.0/16" "WireGuard peer allowed IPs were correctly set" + + run_netavark --file ${TESTSDIR}/testfiles/wireguard/wireguard.json teardown $(get_container_netns_path) +} +@test "WireGuard Address parsing fail" { + expected_rc=1 + run_netavark --file ${TESTSDIR}/testfiles/wireguard/wireguard-fail-address-empty.json setup $(get_container_netns_path) + result="$output" + + assert "$output" "=" '{"error":"when parsing WireGuard config: \"when parsing WireGuard configuration Address on line 1. No value provided.\""}' "Correct error on empty address" + + expected_rc=1 + run_netavark --file ${TESTSDIR}/testfiles/wireguard/wireguard-fail-address-missing.json setup $(get_container_netns_path) + result="$output" + + assert "$output" "=" '{"error":"invalid WireGuard configuration: Interface is missing an Address"}' "Correct error on missing address" +} + +@test "WireGuard AllowedIPs parsing fail" { + expected_rc=1 + run_netavark --file ${TESTSDIR}/testfiles/wireguard/wireguard-fail-ipv6.json setup $(get_container_netns_path) + result="$output" + + assert "$output" "=" '{"error":"when parsing WireGuard config: \"AddrParseError(()) when parsing WireGuard peers AllowedIPs: \\\"ffff::agcd/128,192.168.0.0/16\\\". Occurs in \\\"ffff::agcd/128\\\"\""}' "Correct error on wrong IPv6" + + expected_rc=1 + run_netavark --file ${TESTSDIR}/testfiles/wireguard/wireguard-fail-ipv4.json setup $(get_container_netns_path) + result="$output" + + assert "$output" "=" '{"error":"when parsing WireGuard config: \"AddrParseError(()) when parsing WireGuard peers AllowedIPs: \\\"10.292.122.3/32,10.192.124.0/24\\\". Occurs in \\\"10.292.122.3/32\\\"\""}' "Correct error on wrong IPv4" + + expected_rc=1 + run_netavark --file ${TESTSDIR}/testfiles/wireguard/wireguard-fail-allowedips-empty.json setup $(get_container_netns_path) + result="$output" + + assert "$output" "=" '{"error":"when parsing WireGuard config: \"when parsing WireGuard configuration AllowedIPs on line 8. No value provided.\""}' "Correct error on empty AllowedIPs" + + expected_rc=1 + run_netavark --file ${TESTSDIR}/testfiles/wireguard/wireguard-fail-allowedips-missing.json setup $(get_container_netns_path) + result="$output" + + assert "$output" "=" '{"error":"invalid WireGuard configuration: Peer #0 is missing AllowedIPs"}' "Correct error on missing AllowedIPs" +} + +@test "WireGuard endpoint parsing fail" { + expected_rc=1 + run_netavark --file ${TESTSDIR}/testfiles/wireguard/wireguard-fail-endpoint-empty.json setup $(get_container_netns_path) + result="$output" + + assert "$output" "=" '{"error":"when parsing WireGuard config: \"when parsing WireGuard configuration Endpoint on line 9. No value provided.\""}' "Correct error on empty endpoint" + + expected_rc=1 + run_netavark --file ${TESTSDIR}/testfiles/wireguard/wireguard-fail-endpoint-ip.json setup $(get_container_netns_path) + result="$output" + + assert "$output" "=" '{"error":"when parsing WireGuard config: \"when trying to parse Endpoint 123.45.67.389:12345 for peer 0: \\\"could not parse \\\\\\\"123.45.67.389:12345\\\\\\\"\\\"\""}' "Correct error on wrong Endpoint IP" + + expected_rc=1 + run_netavark --file ${TESTSDIR}/testfiles/wireguard/wireguard-fail-endpoint-port.json setup $(get_container_netns_path) + result="$output" + + assert "$output" "=" '{"error":"when parsing WireGuard config: \"when trying to parse Endpoint 123.45.67.89:123456 for peer 0: \\\"incorrect port: number too large to fit in target type\\\"\""}' "Correct error on wrong Endpoint Port" + + expected_rc=1 + run_netavark --file ${TESTSDIR}/testfiles/wireguard/wireguard-fail-endpoint-hostname.json setup $(get_container_netns_path) + result="$output" + + assert "$output" "=" '{"error":"when parsing WireGuard config: \"when trying to parse Endpoint test.thisdomainshouldnotexist:12345 for peer 0: \\\"could not parse \\\\\\\"test.thisdomainshouldnotexist:12345\\\\\\\"\\\"\""}' "Correct error on wrong Endpoint hostname" +} + +@test "WireGuard port parsing fail" { + expected_rc=1 + run_netavark --file ${TESTSDIR}/testfiles/wireguard/wireguard-fail-port-empty.json setup $(get_container_netns_path) + result="$output" + + assert "$output" "=" '{"error":"when parsing WireGuard config: \"when parsing WireGuard configuration ListenPort on line 3. No value provided.\""}' "Correct error on empty port" + + expected_rc=1 + run_netavark --file ${TESTSDIR}/testfiles/wireguard/wireguard-fail-port.json setup $(get_container_netns_path) + result="$output" + + assert "$output" "=" '{"error":"when parsing WireGuard config: \"ParseIntError { kind: PosOverflow } when parsing WireGuard interface port: \\\"222222\\\"\""}' "Correct error on incorrect port" +} + +@test "WireGuard private key parsing fail" { + expected_rc=1 + run_netavark --file ${TESTSDIR}/testfiles/wireguard/wireguard-fail-privatekey-empty.json setup $(get_container_netns_path) + result="$output" + + assert "$output" "=" '{"error":"when parsing WireGuard config: \"when parsing WireGuard configuration PrivateKey on line 4. No value provided.\""}' "Correct error on empty privatekey" + + expected_rc=1 + run_netavark --file ${TESTSDIR}/testfiles/wireguard/wireguard-fail-privatekey-missing.json setup $(get_container_netns_path) + result="$output" + + assert "$output" "=" '{"error":"invalid WireGuard configuration: Interface is missing a PrivateKey"}' "Correct error on missing privatekey" + + expected_rc=1 + run_netavark --file ${TESTSDIR}/testfiles/wireguard/wireguard-fail-privatekey.json setup $(get_container_netns_path) + result="$output" + + assert "$output" "=" '{"error":"when parsing WireGuard config: \"[200, 9, 243, 229, 49, 73, 181, 237, 120, 182, 56, 183, 206, 83, 13, 171, 232, 93, 218, 182, 20, 34, 2, 65, 128, 29, 223, 6, 105] when decoding base64 PrivateKey: \\\"yAnz5TFJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=\\\". Is it 32 bytes?\""}' "Correct error on incorrect privatekey" +} + +@test "WireGuard public key parsing fail" { + expected_rc=1 + run_netavark --file ${TESTSDIR}/testfiles/wireguard/wireguard-fail-publickey-empty.json setup $(get_container_netns_path) + result="$output" + + assert "$output" "=" '{"error":"when parsing WireGuard config: \"when parsing WireGuard configuration PublicKey on line 7. No value provided.\""}' "Correct error on empty publickey" + + expected_rc=1 + run_netavark --file ${TESTSDIR}/testfiles/wireguard/wireguard-fail-publickey-missing.json setup $(get_container_netns_path) + result="$output" + + assert "$output" "=" '{"error":"invalid WireGuard configuration: Peer #0 is missing a PublicKey"}' "Correct error on missing publickey" + + expected_rc=1 + run_netavark --file ${TESTSDIR}/testfiles/wireguard/wireguard-fail-publickey.json setup $(get_container_netns_path) + result="$output" + + assert "$output" "=" '{"error":"when parsing WireGuard config: \"[197, 50, 1, 2, 27, 104, 118, 54, 250, 123, 175, 123, 66, 50, 196, 70, 221, 77, 0, 30, 38, 102, 170, 124, 14] when decoding base64 PublicKey: \\\"xTIBAhtodjb6e697QjLERt1NAB4mZqp8Dg=\\\" for peer 0. Is it 32 bytes?\""}' "Correct error on incorrect publickey" +} + +@test "WireGuard preshared key parsing fail" { + expected_rc=1 + run_netavark --file ${TESTSDIR}/testfiles/wireguard/wireguard-fail-presharedkey-empty.json setup $(get_container_netns_path) + result="$output" + + assert "$output" "=" '{"error":"when parsing WireGuard config: \"when parsing WireGuard configuration PresharedKey on line 8. No value provided.\""}' "Correct error on empty presharedkey" + + expected_rc=1 + run_netavark --file ${TESTSDIR}/testfiles/wireguard/wireguard-fail-presharedkey.json setup $(get_container_netns_path) + result="$output" + + assert "$output" "=" '{"error":"when parsing WireGuard config: \"[210, 68, 125, 27, 3, 40, 183, 170, 86, 71, 208, 240, 79, 188, 143, 200, 65, 149, 13, 160, 181, 11, 108, 119, 205, 121, 92, 129, 207] when decoding base64 PresharedKey: \\\"0kR9GwMot6pWR9DwT7yPyEGVDaC1C2x3zXlcgc8=\\\" for peer 0. Is it 32 bytes?\""}' "Correct error on incorrect presharedkey" +} + +@test "WireGuard incorrect line parsing fail" { + expected_rc=1 + run_netavark --file ${TESTSDIR}/testfiles/wireguard/wireguard-fail-broken-line.json setup $(get_container_netns_path) + result="$output" + + assert "$output" "=" '{"error":"when parsing WireGuard config: \"when parsing WireGuard configuration Address on line: 1.\""}' "Errors on malformed line" +} diff --git a/test/testfiles/wireguard/wireguard-fail-address-empty.conf b/test/testfiles/wireguard/wireguard-fail-address-empty.conf new file mode 100644 index 000000000..08bc4e102 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-address-empty.conf @@ -0,0 +1,4 @@ +[Interface] +Address = +ListenPort = 51820 +PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= diff --git a/test/testfiles/wireguard/wireguard-fail-address-empty.json b/test/testfiles/wireguard/wireguard-fail-address-empty.json new file mode 100644 index 000000000..d692a52a4 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-address-empty.json @@ -0,0 +1,22 @@ +{ + "container_id": "someID", + "container_name": "wireguard_test_container", + "networks": { + "wg": { + "options": { + "config": "test/testfiles/wireguard/wireguard-fail-address-empty.conf" + }, + "interface_name": "wg-test" + } + }, + "network_info": { + "wg": { + "dns_enabled": false, + "driver": "wireguard", + "id": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e", + "internal": false, + "ipv6_enabled": false, + "name": "wg" + } + } +} diff --git a/test/testfiles/wireguard/wireguard-fail-address-missing.conf b/test/testfiles/wireguard/wireguard-fail-address-missing.conf new file mode 100644 index 000000000..a2ba71512 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-address-missing.conf @@ -0,0 +1,3 @@ +[Interface] +ListenPort = 51820 +PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= diff --git a/test/testfiles/wireguard/wireguard-fail-address-missing.json b/test/testfiles/wireguard/wireguard-fail-address-missing.json new file mode 100644 index 000000000..cd9ee9635 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-address-missing.json @@ -0,0 +1,22 @@ +{ + "container_id": "someID", + "container_name": "wireguard_test_container", + "networks": { + "wg": { + "options": { + "config": "test/testfiles/wireguard/wireguard-fail-address-missing.conf" + }, + "interface_name": "wg-test" + } + }, + "network_info": { + "wg": { + "dns_enabled": false, + "driver": "wireguard", + "id": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e", + "internal": false, + "ipv6_enabled": false, + "name": "wg" + } + } +} diff --git a/test/testfiles/wireguard/wireguard-fail-allowedips-empty.conf b/test/testfiles/wireguard/wireguard-fail-allowedips-empty.conf new file mode 100644 index 000000000..fcfef6678 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-allowedips-empty.conf @@ -0,0 +1,9 @@ +[Interface] +Address = 2001::1/64 +Address = 10.10.0.1/16 +ListenPort = 51820 +PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= + +[Peer] +PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg= +AllowedIPs = diff --git a/test/testfiles/wireguard/wireguard-fail-allowedips-empty.json b/test/testfiles/wireguard/wireguard-fail-allowedips-empty.json new file mode 100644 index 000000000..4e0bdb9af --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-allowedips-empty.json @@ -0,0 +1,22 @@ +{ + "container_id": "someID", + "container_name": "wireguard_test_container", + "networks": { + "wg": { + "options": { + "config": "test/testfiles/wireguard/wireguard-fail-allowedips-empty.conf" + }, + "interface_name": "wg-test" + } + }, + "network_info": { + "wg": { + "dns_enabled": false, + "driver": "wireguard", + "id": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e", + "internal": false, + "ipv6_enabled": false, + "name": "wg" + } + } +} diff --git a/test/testfiles/wireguard/wireguard-fail-allowedips-missing.conf b/test/testfiles/wireguard/wireguard-fail-allowedips-missing.conf new file mode 100644 index 000000000..a149e9257 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-allowedips-missing.conf @@ -0,0 +1,8 @@ +[Interface] +Address = 2001::1/64 +Address = 10.10.0.1/16 +ListenPort = 51820 +PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= + +[Peer] +PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg= diff --git a/test/testfiles/wireguard/wireguard-fail-allowedips-missing.json b/test/testfiles/wireguard/wireguard-fail-allowedips-missing.json new file mode 100644 index 000000000..ca5906601 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-allowedips-missing.json @@ -0,0 +1,22 @@ +{ + "container_id": "someID", + "container_name": "wireguard_test_container", + "networks": { + "wg": { + "options": { + "config": "test/testfiles/wireguard/wireguard-fail-allowedips-missing.conf" + }, + "interface_name": "wg-test" + } + }, + "network_info": { + "wg": { + "dns_enabled": false, + "driver": "wireguard", + "id": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e", + "internal": false, + "ipv6_enabled": false, + "name": "wg" + } + } +} diff --git a/test/testfiles/wireguard/wireguard-fail-broken-line.conf b/test/testfiles/wireguard/wireguard-fail-broken-line.conf new file mode 100644 index 000000000..6630744e9 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-broken-line.conf @@ -0,0 +1,2 @@ +[Interface] +Address diff --git a/test/testfiles/wireguard/wireguard-fail-broken-line.json b/test/testfiles/wireguard/wireguard-fail-broken-line.json new file mode 100644 index 000000000..2b41fe0d9 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-broken-line.json @@ -0,0 +1,22 @@ +{ + "container_id": "someID", + "container_name": "wireguard_test_container", + "networks": { + "wg": { + "options": { + "config": "test/testfiles/wireguard/wireguard-fail-broken-line.conf" + }, + "interface_name": "wg-test" + } + }, + "network_info": { + "wg": { + "dns_enabled": false, + "driver": "wireguard", + "id": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e", + "internal": false, + "ipv6_enabled": false, + "name": "wg" + } + } +} diff --git a/test/testfiles/wireguard/wireguard-fail-endpoint-empty.conf b/test/testfiles/wireguard/wireguard-fail-endpoint-empty.conf new file mode 100644 index 000000000..45dc4cf45 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-endpoint-empty.conf @@ -0,0 +1,10 @@ +[Interface] +Address = 2001::1/64 +Address = 10.10.0.1/16 +ListenPort = 51820 +PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= + +[Peer] +PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg= +AllowedIPs = 10.192.122.3/32, 10.192.124.0/24 +Endpoint = diff --git a/test/testfiles/wireguard/wireguard-fail-endpoint-empty.json b/test/testfiles/wireguard/wireguard-fail-endpoint-empty.json new file mode 100644 index 000000000..e7ed5ffec --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-endpoint-empty.json @@ -0,0 +1,22 @@ +{ + "container_id": "someID", + "container_name": "wireguard_test_container", + "networks": { + "wg": { + "options": { + "config": "test/testfiles/wireguard/wireguard-fail-endpoint-empty.conf" + }, + "interface_name": "wg-test" + } + }, + "network_info": { + "wg": { + "dns_enabled": false, + "driver": "wireguard", + "id": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e", + "internal": false, + "ipv6_enabled": false, + "name": "wg" + } + } +} diff --git a/test/testfiles/wireguard/wireguard-fail-endpoint-hostname.conf b/test/testfiles/wireguard/wireguard-fail-endpoint-hostname.conf new file mode 100644 index 000000000..27bbf9f81 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-endpoint-hostname.conf @@ -0,0 +1,10 @@ +[Interface] +Address = 2001::1/64 +Address = 10.10.0.1/16 +ListenPort = 51820 +PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= + +[Peer] +PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg= +AllowedIPs = 10.192.122.3/32, 10.192.124.0/24 +Endpoint = test.thisdomainshouldnotexist:12345 diff --git a/test/testfiles/wireguard/wireguard-fail-endpoint-hostname.json b/test/testfiles/wireguard/wireguard-fail-endpoint-hostname.json new file mode 100644 index 000000000..90d806429 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-endpoint-hostname.json @@ -0,0 +1,22 @@ +{ + "container_id": "someID", + "container_name": "wireguard_test_container", + "networks": { + "wg": { + "options": { + "config": "test/testfiles/wireguard/wireguard-fail-endpoint-hostname.conf" + }, + "interface_name": "wg-test" + } + }, + "network_info": { + "wg": { + "dns_enabled": false, + "driver": "wireguard", + "id": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e", + "internal": false, + "ipv6_enabled": false, + "name": "wg" + } + } +} diff --git a/test/testfiles/wireguard/wireguard-fail-endpoint-ip.conf b/test/testfiles/wireguard/wireguard-fail-endpoint-ip.conf new file mode 100644 index 000000000..dd3347ffc --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-endpoint-ip.conf @@ -0,0 +1,10 @@ +[Interface] +Address = 2001::1/64 +Address = 10.10.0.1/16 +ListenPort = 51820 +PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= + +[Peer] +PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg= +AllowedIPs = 10.192.122.3/32, 10.192.124.0/24 +Endpoint = 123.45.67.389:12345 diff --git a/test/testfiles/wireguard/wireguard-fail-endpoint-ip.json b/test/testfiles/wireguard/wireguard-fail-endpoint-ip.json new file mode 100644 index 000000000..f44b467b4 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-endpoint-ip.json @@ -0,0 +1,22 @@ +{ + "container_id": "someID", + "container_name": "wireguard_test_container", + "networks": { + "wg": { + "options": { + "config": "test/testfiles/wireguard/wireguard-fail-endpoint-ip.conf" + }, + "interface_name": "wg-test" + } + }, + "network_info": { + "wg": { + "dns_enabled": false, + "driver": "wireguard", + "id": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e", + "internal": false, + "ipv6_enabled": false, + "name": "wg" + } + } +} diff --git a/test/testfiles/wireguard/wireguard-fail-endpoint-port.conf b/test/testfiles/wireguard/wireguard-fail-endpoint-port.conf new file mode 100644 index 000000000..eadd7b3dc --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-endpoint-port.conf @@ -0,0 +1,10 @@ +[Interface] +Address = 2001::1/64 +Address = 10.10.0.1/16 +ListenPort = 51820 +PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= + +[Peer] +PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg= +AllowedIPs = 10.192.122.3/32, 10.192.124.0/24 +Endpoint = 123.45.67.89:123456 diff --git a/test/testfiles/wireguard/wireguard-fail-endpoint-port.json b/test/testfiles/wireguard/wireguard-fail-endpoint-port.json new file mode 100644 index 000000000..e5cf26997 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-endpoint-port.json @@ -0,0 +1,22 @@ +{ + "container_id": "someID", + "container_name": "wireguard_test_container", + "networks": { + "wg": { + "options": { + "config": "test/testfiles/wireguard/wireguard-fail-endpoint-port.conf" + }, + "interface_name": "wg-test" + } + }, + "network_info": { + "wg": { + "dns_enabled": false, + "driver": "wireguard", + "id": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e", + "internal": false, + "ipv6_enabled": false, + "name": "wg" + } + } +} diff --git a/test/testfiles/wireguard/wireguard-fail-ipv4.conf b/test/testfiles/wireguard/wireguard-fail-ipv4.conf new file mode 100644 index 000000000..8572f8651 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-ipv4.conf @@ -0,0 +1,9 @@ +[Interface] +Address = 2001::1/64 +Address = 10.10.0.1/16 +ListenPort = 51820 +PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= + +[Peer] +PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg= +AllowedIPs = 10.292.122.3/32, 10.192.124.0/24 diff --git a/test/testfiles/wireguard/wireguard-fail-ipv4.json b/test/testfiles/wireguard/wireguard-fail-ipv4.json new file mode 100644 index 000000000..aa107e1f2 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-ipv4.json @@ -0,0 +1,22 @@ +{ + "container_id": "someID", + "container_name": "wireguard_test_container", + "networks": { + "wg": { + "options": { + "config": "test/testfiles/wireguard/wireguard-fail-ipv4.conf" + }, + "interface_name": "wg-test" + } + }, + "network_info": { + "wg": { + "dns_enabled": false, + "driver": "wireguard", + "id": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e", + "internal": false, + "ipv6_enabled": false, + "name": "wg" + } + } +} diff --git a/test/testfiles/wireguard/wireguard-fail-ipv6.conf b/test/testfiles/wireguard/wireguard-fail-ipv6.conf new file mode 100644 index 000000000..c1a03d185 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-ipv6.conf @@ -0,0 +1,9 @@ +[Interface] +Address = 2001::1/64 +Address = 10.10.0.1/16 +ListenPort = 51820 +PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= + +[Peer] +PublicKey = fMyt1P5L9yGCY41Zk8NviMqqj0S8NS5Ta9GtqwHa1Sw= +AllowedIPs = ffff::agcd/128, 192.168.0.0/16 diff --git a/test/testfiles/wireguard/wireguard-fail-ipv6.json b/test/testfiles/wireguard/wireguard-fail-ipv6.json new file mode 100644 index 000000000..ac0403b82 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-ipv6.json @@ -0,0 +1,22 @@ +{ + "container_id": "someID", + "container_name": "wireguard_test_container", + "networks": { + "wg": { + "options": { + "config": "test/testfiles/wireguard/wireguard-fail-ipv6.conf" + }, + "interface_name": "wg-test" + } + }, + "network_info": { + "wg": { + "dns_enabled": false, + "driver": "wireguard", + "id": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e", + "internal": false, + "ipv6_enabled": false, + "name": "wg" + } + } +} diff --git a/test/testfiles/wireguard/wireguard-fail-port-empty.conf b/test/testfiles/wireguard/wireguard-fail-port-empty.conf new file mode 100644 index 000000000..fb4dcf0a1 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-port-empty.conf @@ -0,0 +1,5 @@ +[Interface] +Address = 2001::1/64 +Address = 10.10.0.1/16 +ListenPort = +PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= diff --git a/test/testfiles/wireguard/wireguard-fail-port-empty.json b/test/testfiles/wireguard/wireguard-fail-port-empty.json new file mode 100644 index 000000000..a855d68c1 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-port-empty.json @@ -0,0 +1,22 @@ +{ + "container_id": "someID", + "container_name": "wireguard_test_container", + "networks": { + "wg": { + "options": { + "config": "test/testfiles/wireguard/wireguard-fail-port-empty.conf" + }, + "interface_name": "wg-test" + } + }, + "network_info": { + "wg": { + "dns_enabled": false, + "driver": "wireguard", + "id": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e", + "internal": false, + "ipv6_enabled": false, + "name": "wg" + } + } +} diff --git a/test/testfiles/wireguard/wireguard-fail-port.conf b/test/testfiles/wireguard/wireguard-fail-port.conf new file mode 100644 index 000000000..11fdf7d85 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-port.conf @@ -0,0 +1,5 @@ +[Interface] +Address = 2001::1/64 +Address = 10.10.0.1/16 +ListenPort = 222222 +PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= diff --git a/test/testfiles/wireguard/wireguard-fail-port.json b/test/testfiles/wireguard/wireguard-fail-port.json new file mode 100644 index 000000000..58d59a9be --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-port.json @@ -0,0 +1,22 @@ +{ + "container_id": "someID", + "container_name": "wireguard_test_container", + "networks": { + "wg": { + "options": { + "config": "test/testfiles/wireguard/wireguard-fail-port.conf" + }, + "interface_name": "wg-test" + } + }, + "network_info": { + "wg": { + "dns_enabled": false, + "driver": "wireguard", + "id": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e", + "internal": false, + "ipv6_enabled": false, + "name": "wg" + } + } +} diff --git a/test/testfiles/wireguard/wireguard-fail-presharedkey-empty.conf b/test/testfiles/wireguard/wireguard-fail-presharedkey-empty.conf new file mode 100644 index 000000000..e2e4f449d --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-presharedkey-empty.conf @@ -0,0 +1,10 @@ +[Interface] +Address = 2001::1/64 +Address = 10.10.0.1/16 +ListenPort = 51820 +PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= + +[Peer] +PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg= +PresharedKey = +AllowedIPs = 10.192.122.3/32, 10.192.124.0/24 diff --git a/test/testfiles/wireguard/wireguard-fail-presharedkey-empty.json b/test/testfiles/wireguard/wireguard-fail-presharedkey-empty.json new file mode 100644 index 000000000..61bc7b588 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-presharedkey-empty.json @@ -0,0 +1,22 @@ +{ + "container_id": "someID", + "container_name": "wireguard_test_container", + "networks": { + "wg": { + "options": { + "config": "test/testfiles/wireguard/wireguard-fail-presharedkey-empty.conf" + }, + "interface_name": "wg-test" + } + }, + "network_info": { + "wg": { + "dns_enabled": false, + "driver": "wireguard", + "id": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e", + "internal": false, + "ipv6_enabled": false, + "name": "wg" + } + } +} diff --git a/test/testfiles/wireguard/wireguard-fail-presharedkey.conf b/test/testfiles/wireguard/wireguard-fail-presharedkey.conf new file mode 100644 index 000000000..b28bd6ad0 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-presharedkey.conf @@ -0,0 +1,10 @@ +[Interface] +Address = 2001::1/64 +Address = 10.10.0.1/16 +ListenPort = 51820 +PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= + +[Peer] +PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg= +PresharedKey = 0kR9GwMot6pWR9DwT7yPyEGVDaC1C2x3zXlcgc8= +AllowedIPs = 10.192.122.3/32, 10.192.124.0/24 diff --git a/test/testfiles/wireguard/wireguard-fail-presharedkey.json b/test/testfiles/wireguard/wireguard-fail-presharedkey.json new file mode 100644 index 000000000..04c460c49 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-presharedkey.json @@ -0,0 +1,22 @@ +{ + "container_id": "someID", + "container_name": "wireguard_test_container", + "networks": { + "wg": { + "options": { + "config": "test/testfiles/wireguard/wireguard-fail-presharedkey.conf" + }, + "interface_name": "wg-test" + } + }, + "network_info": { + "wg": { + "dns_enabled": false, + "driver": "wireguard", + "id": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e", + "internal": false, + "ipv6_enabled": false, + "name": "wg" + } + } +} diff --git a/test/testfiles/wireguard/wireguard-fail-privatekey-empty.conf b/test/testfiles/wireguard/wireguard-fail-privatekey-empty.conf new file mode 100644 index 000000000..d890dde31 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-privatekey-empty.conf @@ -0,0 +1,5 @@ +[Interface] +Address = 2001::1/64 +Address = 10.10.0.1/16 +ListenPort = 51820 +PrivateKey = diff --git a/test/testfiles/wireguard/wireguard-fail-privatekey-empty.json b/test/testfiles/wireguard/wireguard-fail-privatekey-empty.json new file mode 100644 index 000000000..5eb1aab77 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-privatekey-empty.json @@ -0,0 +1,22 @@ +{ + "container_id": "someID", + "container_name": "wireguard_test_container", + "networks": { + "wg": { + "options": { + "config": "test/testfiles/wireguard/wireguard-fail-privatekey-empty.conf" + }, + "interface_name": "wg-test" + } + }, + "network_info": { + "wg": { + "dns_enabled": false, + "driver": "wireguard", + "id": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e", + "internal": false, + "ipv6_enabled": false, + "name": "wg" + } + } +} diff --git a/test/testfiles/wireguard/wireguard-fail-privatekey-missing.conf b/test/testfiles/wireguard/wireguard-fail-privatekey-missing.conf new file mode 100644 index 000000000..6a9c7b885 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-privatekey-missing.conf @@ -0,0 +1,4 @@ +[Interface] +Address = 2001::1/64 +Address = 10.10.0.1/16 +ListenPort = 51820 diff --git a/test/testfiles/wireguard/wireguard-fail-privatekey-missing.json b/test/testfiles/wireguard/wireguard-fail-privatekey-missing.json new file mode 100644 index 000000000..1500ec75f --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-privatekey-missing.json @@ -0,0 +1,22 @@ +{ + "container_id": "someID", + "container_name": "wireguard_test_container", + "networks": { + "wg": { + "options": { + "config": "test/testfiles/wireguard/wireguard-fail-privatekey-missing.conf" + }, + "interface_name": "wg-test" + } + }, + "network_info": { + "wg": { + "dns_enabled": false, + "driver": "wireguard", + "id": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e", + "internal": false, + "ipv6_enabled": false, + "name": "wg" + } + } +} diff --git a/test/testfiles/wireguard/wireguard-fail-privatekey.conf b/test/testfiles/wireguard/wireguard-fail-privatekey.conf new file mode 100644 index 000000000..ac0f2e97e --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-privatekey.conf @@ -0,0 +1,5 @@ +[Interface] +Address = 2001::1/64 +Address = 10.10.0.1/16 +ListenPort = 51820 +PrivateKey = yAnz5TFJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= diff --git a/test/testfiles/wireguard/wireguard-fail-privatekey.json b/test/testfiles/wireguard/wireguard-fail-privatekey.json new file mode 100644 index 000000000..81aa7fdf3 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-privatekey.json @@ -0,0 +1,22 @@ +{ + "container_id": "someID", + "container_name": "wireguard_test_container", + "networks": { + "wg": { + "options": { + "config": "test/testfiles/wireguard/wireguard-fail-privatekey.conf" + }, + "interface_name": "wg-test" + } + }, + "network_info": { + "wg": { + "dns_enabled": false, + "driver": "wireguard", + "id": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e", + "internal": false, + "ipv6_enabled": false, + "name": "wg" + } + } +} diff --git a/test/testfiles/wireguard/wireguard-fail-publickey-empty.conf b/test/testfiles/wireguard/wireguard-fail-publickey-empty.conf new file mode 100644 index 000000000..9710d3e1f --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-publickey-empty.conf @@ -0,0 +1,9 @@ +[Interface] +Address = 2001::1/64 +Address = 10.10.0.1/16 +ListenPort = 51820 +PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= + +[Peer] +PublicKey = +AllowedIPs = 10.192.122.3/32, 10.192.124.0/24 diff --git a/test/testfiles/wireguard/wireguard-fail-publickey-empty.json b/test/testfiles/wireguard/wireguard-fail-publickey-empty.json new file mode 100644 index 000000000..b3c6e0149 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-publickey-empty.json @@ -0,0 +1,22 @@ +{ + "container_id": "someID", + "container_name": "wireguard_test_container", + "networks": { + "wg": { + "options": { + "config": "test/testfiles/wireguard/wireguard-fail-publickey-empty.conf" + }, + "interface_name": "wg-test" + } + }, + "network_info": { + "wg": { + "dns_enabled": false, + "driver": "wireguard", + "id": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e", + "internal": false, + "ipv6_enabled": false, + "name": "wg" + } + } +} diff --git a/test/testfiles/wireguard/wireguard-fail-publickey-missing.conf b/test/testfiles/wireguard/wireguard-fail-publickey-missing.conf new file mode 100644 index 000000000..1aa5d2054 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-publickey-missing.conf @@ -0,0 +1,8 @@ +[Interface] +Address = 2001::1/64 +Address = 10.10.0.1/16 +ListenPort = 51820 +PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= + +[Peer] +AllowedIPs = 10.192.122.3/32, 10.192.124.0/24 diff --git a/test/testfiles/wireguard/wireguard-fail-publickey-missing.json b/test/testfiles/wireguard/wireguard-fail-publickey-missing.json new file mode 100644 index 000000000..afbe4d196 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-publickey-missing.json @@ -0,0 +1,22 @@ +{ + "container_id": "someID", + "container_name": "wireguard_test_container", + "networks": { + "wg": { + "options": { + "config": "test/testfiles/wireguard/wireguard-fail-publickey-missing.conf" + }, + "interface_name": "wg-test" + } + }, + "network_info": { + "wg": { + "dns_enabled": false, + "driver": "wireguard", + "id": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e", + "internal": false, + "ipv6_enabled": false, + "name": "wg" + } + } +} diff --git a/test/testfiles/wireguard/wireguard-fail-publickey.conf b/test/testfiles/wireguard/wireguard-fail-publickey.conf new file mode 100644 index 000000000..22e9b22ed --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-publickey.conf @@ -0,0 +1,9 @@ +[Interface] +Address = 2001::1/64 +Address = 10.10.0.1/16 +ListenPort = 51820 +PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= + +[Peer] +PublicKey = xTIBAhtodjb6e697QjLERt1NAB4mZqp8Dg= +AllowedIPs = 10.192.122.3/32, 10.192.124.0/24 diff --git a/test/testfiles/wireguard/wireguard-fail-publickey.json b/test/testfiles/wireguard/wireguard-fail-publickey.json new file mode 100644 index 000000000..ce0ebad66 --- /dev/null +++ b/test/testfiles/wireguard/wireguard-fail-publickey.json @@ -0,0 +1,22 @@ +{ + "container_id": "someID", + "container_name": "wireguard_test_container", + "networks": { + "wg": { + "options": { + "config": "test/testfiles/wireguard/wireguard-fail-publickey.conf" + }, + "interface_name": "wg-test" + } + }, + "network_info": { + "wg": { + "dns_enabled": false, + "driver": "wireguard", + "id": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e", + "internal": false, + "ipv6_enabled": false, + "name": "wg" + } + } +} diff --git a/test/testfiles/wireguard/wireguard.conf b/test/testfiles/wireguard/wireguard.conf new file mode 100644 index 000000000..5ae9152ba --- /dev/null +++ b/test/testfiles/wireguard/wireguard.conf @@ -0,0 +1,21 @@ +[Interface] +Address = 2001::1/64 +Address = 10.10.0.1/16 +Address = 10.11.1.1 +Address = dd01:129d:3:a992:11da:aa22:93df:1 +ListenPort = 51820 +PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk= + +[Peer] +PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg= +PresharedKey = 0kR9GwMot6pWR9DwT7yPyEGVDaC1C2x3zXlcgXuVEc8= +AllowedIPs = 10.10.0.2, 10.11.1.0/24 +Endpoint = 123.45.67.89:12345 + +[Peer] +PublicKey = gN65BkIKy1eCE9pP1wdc8ROUtkHLF2PfAqYdyYBz6EA= +AllowedIPs = ffff:ffff::/32 + +[Peer] +PublicKey = fMyt1P5L9yGCY41Zk8NviMqqj0S8NS5Ta9GtqwHa1Sw= +AllowedIPs = ffff::abcd, 192.168.0.0/16 diff --git a/test/testfiles/wireguard/wireguard.json b/test/testfiles/wireguard/wireguard.json new file mode 100644 index 000000000..c62cd23a6 --- /dev/null +++ b/test/testfiles/wireguard/wireguard.json @@ -0,0 +1,22 @@ +{ + "container_id": "someID", + "container_name": "wireguard_test_container", + "networks": { + "wg": { + "options": { + "config": "test/testfiles/wireguard/wireguard.conf" + }, + "interface_name": "wg-test" + } + }, + "network_info": { + "wg": { + "dns_enabled": false, + "driver": "wireguard", + "id": "53ce4390f2adb1681eb1a90ec8b48c49c015e0a8d336c197637e7f65e365fa9e", + "internal": false, + "ipv6_enabled": false, + "name": "wg" + } + } +}