mirror of
https://git.proxmox.com/git/proxmox-perl-rs
synced 2025-05-04 14:37:19 +00:00
add PVE::RS::Firewall::SDN module
Used for obtaining the IPSets that get autogenerated by the nftables firewall. The returned configuration has the same format as the pve-firewall uses internally, making it compatible with the existing pve-firewall code. Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com> Reviewed-by: Wolfgang Bumiller <w.bumiller@proxmox.com> Tested-by: Gabriel Goller <g.goller@proxmox.com> Tested-by: Hannes Dürr <h.duerr@proxmox.com>
This commit is contained in:
parent
ebaf08b8e6
commit
02b7eae00a
@ -45,3 +45,4 @@ proxmox-subscription = "0.5"
|
|||||||
proxmox-sys = "0.6"
|
proxmox-sys = "0.6"
|
||||||
proxmox-tfa = { version = "5", features = ["api"] }
|
proxmox-tfa = { version = "5", features = ["api"] }
|
||||||
proxmox-time = "2"
|
proxmox-time = "2"
|
||||||
|
proxmox-ve-config = { version = "0.1.0" }
|
||||||
|
@ -28,6 +28,7 @@ PERLMOD_GENPACKAGE := /usr/lib/perlmod/genpackage.pl \
|
|||||||
|
|
||||||
PERLMOD_PACKAGES := \
|
PERLMOD_PACKAGES := \
|
||||||
PVE::RS::APT::Repositories \
|
PVE::RS::APT::Repositories \
|
||||||
|
PVE::RS::Firewall::SDN \
|
||||||
PVE::RS::OpenId \
|
PVE::RS::OpenId \
|
||||||
PVE::RS::ResourceScheduling::Static \
|
PVE::RS::ResourceScheduling::Static \
|
||||||
PVE::RS::TFA
|
PVE::RS::TFA
|
||||||
|
1
pve-rs/src/firewall/mod.rs
Normal file
1
pve-rs/src/firewall/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod sdn;
|
130
pve-rs/src/firewall/sdn.rs
Normal file
130
pve-rs/src/firewall/sdn.rs
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
#[perlmod::package(name = "PVE::RS::Firewall::SDN", lib = "pve_rs")]
|
||||||
|
mod export {
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::{fs, io};
|
||||||
|
|
||||||
|
use anyhow::{bail, Context, Error};
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
use proxmox_ve_config::{
|
||||||
|
common::Allowlist,
|
||||||
|
firewall::types::ipset::{IpsetAddress, IpsetEntry},
|
||||||
|
firewall::types::Ipset,
|
||||||
|
guest::types::Vmid,
|
||||||
|
sdn::{
|
||||||
|
config::{RunningConfig, SdnConfig},
|
||||||
|
ipam::{Ipam, IpamJson},
|
||||||
|
VnetName,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, Serialize)]
|
||||||
|
pub struct LegacyIpsetEntry {
|
||||||
|
nomatch: bool,
|
||||||
|
cidr: String,
|
||||||
|
comment: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LegacyIpsetEntry {
|
||||||
|
pub fn from_ipset_entry(entry: &IpsetEntry) -> Vec<LegacyIpsetEntry> {
|
||||||
|
let mut entries = Vec::new();
|
||||||
|
|
||||||
|
match &entry.address {
|
||||||
|
IpsetAddress::Alias(name) => {
|
||||||
|
entries.push(Self {
|
||||||
|
nomatch: entry.nomatch,
|
||||||
|
cidr: name.to_string(),
|
||||||
|
comment: entry.comment.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
IpsetAddress::Cidr(cidr) => {
|
||||||
|
entries.push(Self {
|
||||||
|
nomatch: entry.nomatch,
|
||||||
|
cidr: cidr.to_string(),
|
||||||
|
comment: entry.comment.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
IpsetAddress::Range(range) => {
|
||||||
|
entries.extend(range.to_cidrs().into_iter().map(|cidr| Self {
|
||||||
|
nomatch: entry.nomatch,
|
||||||
|
cidr: cidr.to_string(),
|
||||||
|
comment: entry.comment.clone(),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
entries
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, Serialize)]
|
||||||
|
pub struct SdnFirewallConfig {
|
||||||
|
ipset: HashMap<String, Vec<LegacyIpsetEntry>>,
|
||||||
|
ipset_comments: HashMap<String, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SdnFirewallConfig {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Default::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extend_ipsets(&mut self, ipsets: impl IntoIterator<Item = Ipset>) {
|
||||||
|
for ipset in ipsets {
|
||||||
|
let entries = ipset
|
||||||
|
.iter()
|
||||||
|
.flat_map(LegacyIpsetEntry::from_ipset_entry)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
self.ipset.insert(ipset.name().name().to_string(), entries);
|
||||||
|
|
||||||
|
if let Some(comment) = &ipset.comment {
|
||||||
|
self.ipset_comments
|
||||||
|
.insert(ipset.name().name().to_string(), comment.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const SDN_RUNNING_CONFIG: &str = "/etc/pve/sdn/.running-config";
|
||||||
|
const SDN_IPAM: &str = "/etc/pve/priv/ipam.db";
|
||||||
|
|
||||||
|
#[export]
|
||||||
|
pub fn config(
|
||||||
|
vnet_filter: Option<Vec<VnetName>>,
|
||||||
|
vm_filter: Option<Vec<Vmid>>,
|
||||||
|
) -> Result<SdnFirewallConfig, Error> {
|
||||||
|
let mut refs = SdnFirewallConfig::new();
|
||||||
|
|
||||||
|
match fs::read_to_string(SDN_RUNNING_CONFIG) {
|
||||||
|
Ok(data) => {
|
||||||
|
let running_config: RunningConfig = serde_json::from_str(&data)?;
|
||||||
|
let sdn_config = SdnConfig::try_from(running_config)
|
||||||
|
.with_context(|| "Failed to parse SDN config".to_string())?;
|
||||||
|
|
||||||
|
let allowlist = vnet_filter.map(Allowlist::from_iter);
|
||||||
|
refs.extend_ipsets(sdn_config.ipsets(allowlist.as_ref()));
|
||||||
|
}
|
||||||
|
Err(e) if e.kind() == io::ErrorKind::NotFound => (),
|
||||||
|
Err(e) => {
|
||||||
|
bail!("Cannot open SDN running config: {e:#}");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match fs::read_to_string(SDN_IPAM) {
|
||||||
|
Ok(data) => {
|
||||||
|
let ipam_json: IpamJson = serde_json::from_str(&data)?;
|
||||||
|
let ipam: Ipam = Ipam::try_from(ipam_json)
|
||||||
|
.with_context(|| "Failed to parse IPAM".to_string())?;
|
||||||
|
|
||||||
|
let allowlist = vm_filter.map(Allowlist::from_iter);
|
||||||
|
refs.extend_ipsets(ipam.ipsets(allowlist.as_ref()));
|
||||||
|
}
|
||||||
|
Err(e) if e.kind() == io::ErrorKind::NotFound => (),
|
||||||
|
Err(e) => {
|
||||||
|
bail!("Cannot open IPAM database: {e:#}");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(refs)
|
||||||
|
}
|
||||||
|
}
|
@ -12,6 +12,7 @@ use proxmox_notify::{Config, Notification, Severity};
|
|||||||
pub mod common;
|
pub mod common;
|
||||||
|
|
||||||
pub mod apt;
|
pub mod apt;
|
||||||
|
pub mod firewall;
|
||||||
pub mod openid;
|
pub mod openid;
|
||||||
pub mod resource_scheduling;
|
pub mod resource_scheduling;
|
||||||
pub mod tfa;
|
pub mod tfa;
|
||||||
|
Loading…
Reference in New Issue
Block a user