Skip to content

Commit

Permalink
feat: dynamic IpAddressAllow
Browse files Browse the repository at this point in the history
  • Loading branch information
desbma committed Feb 7, 2025
1 parent d8aa8b5 commit 4928a4c
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 3 deletions.
8 changes: 8 additions & 0 deletions src/summarize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ pub(crate) trait ValueCounted {
fn one() -> Self;
}

// TODO merge this with SetSpecifier
/// Quantify something that is done or denied
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
pub(crate) enum CountableSetSpecifier<T> {
Expand Down Expand Up @@ -214,6 +215,13 @@ impl<T: Eq + Ord + Clone + Display + ValueCounted + Sub<Output = T> + Add<Output
CountableSetSpecifier::All => vec![T::min_value()..=T::max_value()],
}
}

pub(crate) fn excluded_elements(&self) -> Vec<T> {
match self {
CountableSetSpecifier::AllExcept(vec) => vec.to_owned(),
_ => todo!(),
}
}
}

/// Socket activity
Expand Down
59 changes: 56 additions & 3 deletions src/systemd/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1972,21 +1972,74 @@ pub(crate) fn build_options(
// https://www.freedesktop.org/software/systemd/man/latest/systemd.resource-control.html#IPAddressAllow=ADDRESS%5B/PREFIXLENGTH%5D%E2%80%A6
if hardening_opts.network_firewalling {
options.push(OptionDescription {
// Use this option as a simple "deny all" (not a list), and the updater will do the hard work of whitelisting with IPAddressAllow
name: "IPAddressDeny",
possible_values: vec![OptionValueDescription {
value: OptionValue::String("any".into()),
desc: OptionEffect::Simple(OptionValueEffect::DenyAction(
ProgramAction::NetworkActivity(NetworkActivity {
af: SetSpecifier::All,
af: SetSpecifier::Some(vec![SocketFamily::Ipv4, SocketFamily::Ipv6]),
proto: SetSpecifier::All,
kind: SetSpecifier::Some(NetworkActivityKind::ADDRESSED.to_vec()),
local_port: CountableSetSpecifier::All,
address: CountableSetSpecifier::All,
}),
)),
}],
updater: None, // TODO
updater: Some(OptionUpdater {
effect: |effect, action, _| {
let OptionValueEffect::DenyAction(ProgramAction::NetworkActivity(effect_na)) =
effect
else {
return None;
};
let ProgramAction::NetworkActivity(NetworkActivity {
af: SetSpecifier::One(SocketFamily::Ipv4),
address: CountableSetSpecifier::One(action_addr),
..
}) = action
else {
return None;
};
let mut new_effect_address = effect_na.address.clone();
new_effect_address.remove(action_addr);
Some(OptionValueEffect::DenyAction(
ProgramAction::NetworkActivity(NetworkActivity {
address: new_effect_address,
..effect_na.to_owned()
}),
))
},
options: |effect, _| match effect {
OptionValueEffect::DenyAction(ProgramAction::NetworkActivity(
NetworkActivity { address, .. },
)) => {
vec![
OptionWithValue {
name: "IPAddressDeny",
value: OptionValue::String("any".into()),
},
OptionWithValue {
name: "IPAddressAllow",
value: OptionValue::List(ListOptionValue {
values: address
.excluded_elements()
.into_iter()
.map(|e| e.to_string())
.collect(),
value_if_empty: None,
option_prefix: "",
elem_prefix: "",
repeat_option: false,
mode: ListMode::WhiteList,
mergeable_paths: false,
}),
},
]
}
_ => vec![],
},
dynamic_option_names: vec!["IPAddressDeny", "IPAddressAllow"],
}),
});
}

Expand Down

0 comments on commit 4928a4c

Please sign in to comment.