wick_config/config/
lockdown_config.rs1#![allow(missing_docs)] use std::collections::{HashMap, HashSet};
3use std::path::{Path, PathBuf};
4
5use asset_container::AssetManager;
6use tracing::trace;
7use wick_asset_reference::AssetReference;
8
9use crate::audit::Audit;
10use crate::config::template_config::Renderable;
11use crate::{config, Result};
12mod resources;
13pub use resources::*;
14
15#[derive(
16 Debug, Clone, derive_builder::Builder, derive_asset_container::AssetManager, property::Property, serde::Serialize,
17)]
18#[property(get(public), set(public), mut(public, suffix = "_mut"))]
19#[asset(asset(AssetReference))]
20#[must_use]
21pub struct LockdownConfiguration {
25 #[asset(skip)]
27 #[property(skip)]
28 #[serde(skip_serializing_if = "Option::is_none")]
29 pub(crate) source: Option<PathBuf>,
30
31 #[asset(skip)]
33 #[builder(default)]
34 #[serde(skip_serializing_if = "Option::is_none")]
35 pub(crate) metadata: Option<config::Metadata>,
36
37 #[asset(skip)]
39 #[serde(skip_serializing_if = "Vec::is_empty")]
40 pub(crate) resources: Vec<ResourceRestriction>,
41
42 #[asset(skip)]
44 #[builder(default)]
45 #[property(skip)]
46 #[serde(skip_serializing_if = "Option::is_none")]
47 pub(crate) env: Option<HashMap<String, String>>,
48}
49
50impl LockdownConfiguration {
51 #[must_use]
53 pub fn version(&self) -> Option<&str> {
54 self.metadata.as_ref().map(|m| m.version.as_str())
55 }
56
57 pub(crate) fn initialize(&mut self) -> Result<&Self> {
59 trace!(
61 resource_restrictions = ?self.resources,
62 "initializing lockdown configuration"
63 );
64 self
65 .resources
66 .render_config(self.source.as_deref(), None, self.env.as_ref())?;
67
68 Ok(self)
69 }
70
71 pub fn set_source(&mut self, source: &Path) {
73 let source = source.to_path_buf();
74 self.source = Some(source);
75 }
76
77 pub(super) fn update_baseurls(&self) {
78 #[allow(clippy::expect_used)]
79 let mut source = self.source.clone().expect("No source set for this configuration");
80 if !source.is_dir() {
82 source.pop();
83 }
84 self.set_baseurl(&source);
85 }
86
87 #[must_use]
89 pub const fn env(&self) -> Option<&HashMap<String, String>> {
90 None
91 }
92
93 #[allow(clippy::missing_const_for_fn)]
95 pub fn validate(&self) -> Result<()> {
96 Ok(())
98 }
99}
100
101impl Renderable for LockdownConfiguration {
102 fn render_config(
103 &mut self,
104 source: Option<&Path>,
105 root_config: Option<&wick_packet::RuntimeConfig>,
106 env: Option<&HashMap<String, String>>,
107 ) -> Result<()> {
108 self.resources.render_config(source, root_config, env)?;
109 Ok(())
110 }
111}
112
113impl From<Vec<Audit>> for LockdownConfiguration {
114 fn from(value: Vec<Audit>) -> Self {
115 let mut url_restrictions: Vec<UrlRestriction> = Vec::new();
116 let mut volume_restrictions: Vec<VolumeRestriction> = Vec::new();
117 let mut tcpport_restrictions: Vec<PortRestriction> = Vec::new();
118 let mut udpport_restrictions: Vec<PortRestriction> = Vec::new();
119 let mut restrictions: Vec<ResourceRestriction> = Vec::new();
120 let mut reverse_map: HashMap<&crate::audit::AuditedResource, HashSet<&String>> = HashMap::new();
121
122 for audit in &value {
123 for resource in &audit.resources {
124 let entry = reverse_map.entry(&resource.resource).or_insert_with(HashSet::new);
125 entry.insert(&audit.name);
126 }
127 }
128
129 for (resource, components) in reverse_map {
130 let components: Vec<_> = components.iter().map(|s| (*s).clone()).collect();
131 match resource {
132 crate::audit::AuditedResource::TcpPort(v) => tcpport_restrictions.push(PortRestriction::new_from_template(
133 components,
134 &v.address,
135 v.port.to_string(),
136 )),
137 crate::audit::AuditedResource::UdpPort(v) => udpport_restrictions.push(PortRestriction::new_from_template(
138 components,
139 &v.address,
140 v.port.to_string(),
141 )),
142 crate::audit::AuditedResource::Url(v) => {
143 url_restrictions.push(UrlRestriction::new_from_template(components, v.url.as_str()));
144 }
145 crate::audit::AuditedResource::Volume(v) => volume_restrictions.push(VolumeRestriction::new_from_template(
146 components,
147 v.path.to_string_lossy(),
148 )),
149 }
150 }
151
152 restrictions.extend(tcpport_restrictions.into_iter().map(ResourceRestriction::TcpPort));
153 restrictions.extend(udpport_restrictions.into_iter().map(ResourceRestriction::UdpPort));
154 restrictions.extend(url_restrictions.into_iter().map(ResourceRestriction::Url));
155 restrictions.extend(volume_restrictions.into_iter().map(ResourceRestriction::Volume));
156
157 LockdownConfiguration {
158 source: None,
159 metadata: None,
160 resources: restrictions,
161 env: None,
162 }
163 }
164}