From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id 25AD41FF163 for ; Thu, 10 Oct 2024 18:03:15 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id E063C1ED9B; Thu, 10 Oct 2024 18:03:20 +0200 (CEST) From: Stefan Hanreich To: pve-devel@lists.proxmox.com Date: Thu, 10 Oct 2024 17:56:31 +0200 Message-Id: <20241010155637.255451-20-s.hanreich@proxmox.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20241010155637.255451-1-s.hanreich@proxmox.com> References: <20241010155637.255451-1-s.hanreich@proxmox.com> MIME-Version: 1.0 X-SPAM-LEVEL: Spam detection results: 0 AWL -0.252 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment KAM_LAZY_DOMAIN_SECURITY 1 Sending domain does not have any anti-forgery methods RDNS_NONE 0.793 Delivered to internal network by a host with no rDNS SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_NONE 0.001 SPF: sender does not publish an SPF Record Subject: [pve-devel] [PATCH proxmox-firewall v2 19/25] config: tests: add support for loading sdn and ipam config X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Proxmox VE development discussion Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pve-devel-bounces@lists.proxmox.com Sender: "pve-devel" Also add example SDN configuration files that get automatically loaded, which can be used for future tests. Signed-off-by: Stefan Hanreich --- proxmox-firewall/src/config.rs | 69 +++++++++++++++++++ .../tests/input/.running-config.json | 45 ++++++++++++ proxmox-firewall/tests/input/ipam.db | 32 +++++++++ proxmox-firewall/tests/integration_tests.rs | 10 +++ proxmox-nftables/src/types.rs | 2 +- 5 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 proxmox-firewall/tests/input/.running-config.json create mode 100644 proxmox-firewall/tests/input/ipam.db diff --git a/proxmox-firewall/src/config.rs b/proxmox-firewall/src/config.rs index 5bd2512..c27aac6 100644 --- a/proxmox-firewall/src/config.rs +++ b/proxmox-firewall/src/config.rs @@ -16,6 +16,10 @@ use proxmox_ve_config::guest::{GuestEntry, GuestMap}; use proxmox_nftables::command::{CommandOutput, Commands, List, ListOutput}; use proxmox_nftables::types::ListChain; use proxmox_nftables::NftClient; +use proxmox_ve_config::sdn::{ + config::{RunningConfig, SdnConfig}, + ipam::{Ipam, IpamJson}, +}; pub trait FirewallConfigLoader { fn cluster(&self) -> Result>, Error>; @@ -27,6 +31,8 @@ pub trait FirewallConfigLoader { guest: &GuestEntry, ) -> Result>, Error>; fn guest_firewall_config(&self, vmid: &Vmid) -> Result>, Error>; + fn sdn_running_config(&self) -> Result>, Error>; + fn ipam(&self) -> Result>, Error>; } #[derive(Default)] @@ -58,6 +64,9 @@ fn open_config_file(path: &str) -> Result, Error> { const CLUSTER_CONFIG_PATH: &str = "/etc/pve/firewall/cluster.fw"; const HOST_CONFIG_PATH: &str = "/etc/pve/local/host.fw"; +const SDN_RUNNING_CONFIG_PATH: &str = "/etc/pve/sdn/.running-config"; +const SDN_IPAM_PATH: &str = "/etc/pve/priv/ipam.db"; + impl FirewallConfigLoader for PveFirewallConfigLoader { fn cluster(&self) -> Result>, Error> { log::info!("loading cluster config"); @@ -119,6 +128,32 @@ impl FirewallConfigLoader for PveFirewallConfigLoader { Ok(None) } + + fn sdn_running_config(&self) -> Result>, Error> { + log::info!("loading SDN running-config"); + + let fd = open_config_file(SDN_RUNNING_CONFIG_PATH)?; + + if let Some(file) = fd { + let buf_reader = Box::new(BufReader::new(file)) as Box; + return Ok(Some(buf_reader)); + } + + Ok(None) + } + + fn ipam(&self) -> Result>, Error> { + log::info!("loading IPAM config"); + + let fd = open_config_file(SDN_IPAM_PATH)?; + + if let Some(file) = fd { + let buf_reader = Box::new(BufReader::new(file)) as Box; + return Ok(Some(buf_reader)); + } + + Ok(None) + } } pub trait NftConfigLoader { @@ -150,6 +185,8 @@ pub struct FirewallConfig { host_config: HostConfig, guest_config: BTreeMap, nft_config: BTreeMap, + sdn_config: Option, + ipam_config: Option, } impl FirewallConfig { @@ -207,6 +244,28 @@ impl FirewallConfig { Ok(guests) } + pub fn parse_sdn( + firewall_loader: &dyn FirewallConfigLoader, + ) -> Result, Error> { + Ok(match firewall_loader.sdn_running_config()? { + Some(data) => { + let running_config: RunningConfig = serde_json::from_reader(data)?; + Some(SdnConfig::try_from(running_config)?) + } + _ => None, + }) + } + + pub fn parse_ipam(firewall_loader: &dyn FirewallConfigLoader) -> Result, Error> { + Ok(match firewall_loader.ipam()? { + Some(data) => { + let raw_ipam: IpamJson = serde_json::from_reader(data)?; + Some(Ipam::try_from(raw_ipam)?) + } + _ => None, + }) + } + pub fn parse_nft( nft_loader: &dyn NftConfigLoader, ) -> Result, Error> { @@ -233,6 +292,8 @@ impl FirewallConfig { cluster_config: Self::parse_cluster(firewall_loader)?, host_config: Self::parse_host(firewall_loader)?, guest_config: Self::parse_guests(firewall_loader)?, + sdn_config: Self::parse_sdn(firewall_loader)?, + ipam_config: Self::parse_ipam(firewall_loader)?, nft_config: Self::parse_nft(nft_loader)?, }) } @@ -253,6 +314,14 @@ impl FirewallConfig { &self.nft_config } + pub fn sdn(&self) -> Option<&SdnConfig> { + self.sdn_config.as_ref() + } + + pub fn ipam(&self) -> Option<&Ipam> { + self.ipam_config.as_ref() + } + pub fn is_enabled(&self) -> bool { self.cluster().is_enabled() && self.host().nftables() } diff --git a/proxmox-firewall/tests/input/.running-config.json b/proxmox-firewall/tests/input/.running-config.json new file mode 100644 index 0000000..a4511f0 --- /dev/null +++ b/proxmox-firewall/tests/input/.running-config.json @@ -0,0 +1,45 @@ +{ + "subnets": { + "ids": { + "test-10.101.0.0-16": { + "gateway": "10.101.1.1", + "snat": 1, + "vnet": "public", + "dhcp-range": [ + "start-address=10.101.99.100,end-address=10.101.99.200" + ], + "type": "subnet" + }, + "test-fd80::-64": { + "snat": 1, + "gateway": "fd80::1", + "dhcp-range": [ + "start-address=fd80::1000,end-address=fd80::ffff" + ], + "vnet": "public", + "type": "subnet" + } + } + }, + "version": 49, + "vnets": { + "ids": { + "public": { + "zone": "test", + "type": "vnet" + } + } + }, + "zones": { + "ids": { + "test": { + "dhcp": "dnsmasq", + "ipam": "pve", + "type": "simple" + } + } + }, + "controllers": { + "ids": {} + } +} diff --git a/proxmox-firewall/tests/input/ipam.db b/proxmox-firewall/tests/input/ipam.db new file mode 100644 index 0000000..ac2901e --- /dev/null +++ b/proxmox-firewall/tests/input/ipam.db @@ -0,0 +1,32 @@ +{ + "zones": { + "public": { + "subnets": { + "10.101.0.0/16": { + "ips": { + "10.101.1.1": { + "gateway": 1 + }, + "10.101.1.100": { + "vmid": "101", + "mac": "BC:24:11:11:22:33", + "hostname": null + } + } + }, + "fd80::/64": { + "ips": { + "fd80::1": { + "gateway": 1 + }, + "fd80::1000": { + "mac": "BC:24:11:11:22:33", + "vmid": "101", + "hostname": "test-vm" + } + } + } + } + } + } +} diff --git a/proxmox-firewall/tests/integration_tests.rs b/proxmox-firewall/tests/integration_tests.rs index e9baffe..5de1a4e 100644 --- a/proxmox-firewall/tests/integration_tests.rs +++ b/proxmox-firewall/tests/integration_tests.rs @@ -69,6 +69,16 @@ impl FirewallConfigLoader for MockFirewallConfigLoader { Ok(None) } + + fn sdn_running_config(&self) -> Result>, Error> { + Ok(Some(Box::new( + include_str!("input/.running-config.json").as_bytes(), + ))) + } + + fn ipam(&self) -> Result>, Error> { + Ok(Some(Box::new(include_str!("input/ipam.db").as_bytes()))) + } } struct MockNftConfigLoader {} diff --git a/proxmox-nftables/src/types.rs b/proxmox-nftables/src/types.rs index a83e958..3101436 100644 --- a/proxmox-nftables/src/types.rs +++ b/proxmox-nftables/src/types.rs @@ -636,7 +636,7 @@ impl SetName { }; let name = match name.scope() { - IpsetScope::Datacenter => name.to_string(), + IpsetScope::Datacenter | IpsetScope::Sdn => name.to_string(), IpsetScope::Guest => { if let Some(vmid) = vmid { format!("guest-{vmid}/{}", name.name()) -- 2.39.5 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel