mirror of
https://codeberg.org/likwid/likwid.git
synced 2026-02-09 21:13:09 +00:00
wasm: dedupe capability resolution
This commit is contained in:
parent
91d2f79740
commit
3aba16a8e8
1 changed files with 261 additions and 308 deletions
|
|
@ -23,6 +23,77 @@ pub struct WasmPlugin {
|
|||
limits: ExecutionLimits,
|
||||
}
|
||||
|
||||
async fn capabilities_for_manifest(
|
||||
pool: &PgPool,
|
||||
community_id: Option<Uuid>,
|
||||
manifest_capabilities: &[String],
|
||||
) -> Result<Vec<Capability>, PluginError> {
|
||||
let mut out: Vec<Capability> = Vec::new();
|
||||
|
||||
let (allow_http, allowlist) = if let Some(cid) = community_id {
|
||||
let row = sqlx::query!(
|
||||
r#"SELECT settings as "settings!: serde_json::Value" FROM communities WHERE id = $1"#,
|
||||
cid
|
||||
)
|
||||
.fetch_optional(pool)
|
||||
.await?;
|
||||
|
||||
if let Some(row) = row {
|
||||
let allow_http = row
|
||||
.settings
|
||||
.get("plugin_allow_outbound_http")
|
||||
.and_then(|v: &serde_json::Value| v.as_bool())
|
||||
.unwrap_or(false);
|
||||
|
||||
let allowlist: Vec<String> = row
|
||||
.settings
|
||||
.get("plugin_http_egress_allowlist")
|
||||
.and_then(|v: &serde_json::Value| v.as_array())
|
||||
.map(|arr: &Vec<serde_json::Value>| {
|
||||
arr.iter()
|
||||
.filter_map(|v: &serde_json::Value| v.as_str().map(|s: &str| s.to_string()))
|
||||
.collect()
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
(allow_http, allowlist)
|
||||
} else {
|
||||
(false, Vec::new())
|
||||
}
|
||||
} else {
|
||||
(false, Vec::new())
|
||||
};
|
||||
|
||||
for cap in manifest_capabilities {
|
||||
match cap.as_str() {
|
||||
CAP_OUTBOUND_HTTP => {
|
||||
let allowed = allow_http && !allowlist.is_empty();
|
||||
out.push(Capability {
|
||||
name: cap.clone(),
|
||||
allowed,
|
||||
config: serde_json::json!({"allowlist": allowlist}),
|
||||
});
|
||||
}
|
||||
CAP_SETTINGS | CAP_KV_STORE | CAP_EMIT_EVENTS => {
|
||||
out.push(Capability {
|
||||
name: cap.clone(),
|
||||
allowed: true,
|
||||
config: serde_json::json!({}),
|
||||
});
|
||||
}
|
||||
_ => {
|
||||
out.push(Capability {
|
||||
name: cap.clone(),
|
||||
allowed: false,
|
||||
config: serde_json::json!({}),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
impl WasmPlugin {
|
||||
/// Creates a new WASM plugin from a manifest and compiled module.
|
||||
pub fn new(
|
||||
|
|
@ -46,72 +117,7 @@ impl WasmPlugin {
|
|||
}
|
||||
|
||||
async fn capabilities_for(&self, pool: &PgPool, ctx: &HookContext) -> Result<Vec<Capability>, PluginError> {
|
||||
let mut out: Vec<Capability> = Vec::new();
|
||||
|
||||
// Community policy influences outbound HTTP.
|
||||
let (allow_http, allowlist) = if let Some(cid) = ctx.community_id {
|
||||
let row = sqlx::query!(
|
||||
r#"SELECT settings as "settings!: serde_json::Value" FROM communities WHERE id = $1"#,
|
||||
cid
|
||||
)
|
||||
.fetch_optional(pool)
|
||||
.await?;
|
||||
|
||||
if let Some(row) = row {
|
||||
let allow_http = row
|
||||
.settings
|
||||
.get("plugin_allow_outbound_http")
|
||||
.and_then(|v: &serde_json::Value| v.as_bool())
|
||||
.unwrap_or(false);
|
||||
|
||||
let allowlist: Vec<String> = row
|
||||
.settings
|
||||
.get("plugin_http_egress_allowlist")
|
||||
.and_then(|v: &serde_json::Value| v.as_array())
|
||||
.map(|arr: &Vec<serde_json::Value>| {
|
||||
arr.iter()
|
||||
.filter_map(|v: &serde_json::Value| v.as_str().map(|s: &str| s.to_string()))
|
||||
.collect()
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
(allow_http, allowlist)
|
||||
} else {
|
||||
(false, Vec::new())
|
||||
}
|
||||
} else {
|
||||
(false, Vec::new())
|
||||
};
|
||||
|
||||
for cap in &self.manifest.capabilities {
|
||||
match cap.as_str() {
|
||||
CAP_OUTBOUND_HTTP => {
|
||||
let allowed = allow_http && !allowlist.is_empty();
|
||||
out.push(Capability {
|
||||
name: cap.clone(),
|
||||
allowed,
|
||||
config: serde_json::json!({"allowlist": allowlist}),
|
||||
});
|
||||
}
|
||||
CAP_SETTINGS | CAP_KV_STORE | CAP_EMIT_EVENTS => {
|
||||
out.push(Capability {
|
||||
name: cap.clone(),
|
||||
allowed: true,
|
||||
config: serde_json::json!({}),
|
||||
});
|
||||
}
|
||||
_ => {
|
||||
// Unknown capability is denied by default.
|
||||
out.push(Capability {
|
||||
name: cap.clone(),
|
||||
allowed: false,
|
||||
config: serde_json::json!({}),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(out)
|
||||
capabilities_for_manifest(pool, ctx.community_id, &self.manifest.capabilities).await
|
||||
}
|
||||
|
||||
async fn create_instance(&self, ctx: &HookContext) -> Result<PluginInstance, PluginError> {
|
||||
|
|
@ -173,65 +179,12 @@ impl Plugin for WasmPlugin {
|
|||
let lim = limits_clone.clone();
|
||||
|
||||
Box::pin(async move {
|
||||
let (allow_http, allowlist) = if let Some(cid) = ctx.community_id {
|
||||
let row = sqlx::query!(
|
||||
r#"SELECT settings as "settings!: serde_json::Value" FROM communities WHERE id = $1"#,
|
||||
cid
|
||||
)
|
||||
.fetch_optional(&ctx.pool)
|
||||
.await?;
|
||||
|
||||
if let Some(row) = row {
|
||||
let allow_http = row
|
||||
.settings
|
||||
.get("plugin_allow_outbound_http")
|
||||
.and_then(|v: &serde_json::Value| v.as_bool())
|
||||
.unwrap_or(false);
|
||||
|
||||
let allowlist: Vec<String> = row
|
||||
.settings
|
||||
.get("plugin_http_egress_allowlist")
|
||||
.and_then(|v: &serde_json::Value| v.as_array())
|
||||
.map(|arr: &Vec<serde_json::Value>| {
|
||||
arr.iter()
|
||||
.filter_map(|v: &serde_json::Value| v.as_str().map(|s: &str| s.to_string()))
|
||||
.collect()
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
(allow_http, allowlist)
|
||||
} else {
|
||||
(false, Vec::new())
|
||||
}
|
||||
} else {
|
||||
(false, Vec::new())
|
||||
};
|
||||
|
||||
let mut capabilities: Vec<Capability> = Vec::new();
|
||||
for cap in &manifest_capabilities {
|
||||
match cap.as_str() {
|
||||
CAP_OUTBOUND_HTTP => {
|
||||
let allowed = allow_http && !allowlist.is_empty();
|
||||
capabilities.push(Capability {
|
||||
name: cap.clone(),
|
||||
allowed,
|
||||
config: serde_json::json!({"allowlist": allowlist.clone()}),
|
||||
});
|
||||
}
|
||||
CAP_SETTINGS | CAP_KV_STORE | CAP_EMIT_EVENTS => {
|
||||
capabilities.push(Capability {
|
||||
name: cap.clone(),
|
||||
allowed: true,
|
||||
config: serde_json::json!({}),
|
||||
});
|
||||
}
|
||||
_ => capabilities.push(Capability {
|
||||
name: cap.clone(),
|
||||
allowed: false,
|
||||
config: serde_json::json!({}),
|
||||
}),
|
||||
}
|
||||
}
|
||||
let capabilities = capabilities_for_manifest(
|
||||
&ctx.pool,
|
||||
ctx.community_id,
|
||||
&manifest_capabilities,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let host_state = HostState::new(
|
||||
plugin.clone(),
|
||||
|
|
|
|||
Loading…
Reference in a new issue