fix: pentest session ID propagation, target name resolution, BSON field paths
- Set session.id from insert_one result so orchestrator has the ID - Enrich sessions with target_name by joining DAST targets in server fns - Fix _id.$oid BSON field path for target dropdown and session list - Fix send_message URL to /chat (was /messages) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -76,7 +76,7 @@ pub async fn create_session(
|
|||||||
let mut session = PentestSession::new(req.target_id.clone(), strategy);
|
let mut session = PentestSession::new(req.target_id.clone(), strategy);
|
||||||
session.repo_id = target.repo_id.clone();
|
session.repo_id = target.repo_id.clone();
|
||||||
|
|
||||||
agent
|
let insert_result = agent
|
||||||
.db
|
.db
|
||||||
.pentest_sessions()
|
.pentest_sessions()
|
||||||
.insert_one(&session)
|
.insert_one(&session)
|
||||||
@@ -88,6 +88,9 @@ pub async fn create_session(
|
|||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
// Set the generated ID back on the session so the orchestrator has it
|
||||||
|
session.id = insert_result.inserted_id.as_object_id();
|
||||||
|
|
||||||
let initial_message = req.message.unwrap_or_else(|| {
|
let initial_message = req.message.unwrap_or_else(|| {
|
||||||
format!(
|
format!(
|
||||||
"Begin a {} penetration test against {} ({}). \
|
"Begin a {} penetration test against {} ({}). \
|
||||||
|
|||||||
@@ -34,14 +34,50 @@ pub struct AttackChainResponse {
|
|||||||
pub async fn fetch_pentest_sessions() -> Result<PentestSessionsResponse, ServerFnError> {
|
pub async fn fetch_pentest_sessions() -> Result<PentestSessionsResponse, ServerFnError> {
|
||||||
let state: super::server_state::ServerState =
|
let state: super::server_state::ServerState =
|
||||||
dioxus_fullstack::FullstackContext::extract().await?;
|
dioxus_fullstack::FullstackContext::extract().await?;
|
||||||
|
|
||||||
|
// Fetch sessions
|
||||||
let url = format!("{}/api/v1/pentest/sessions", state.agent_api_url);
|
let url = format!("{}/api/v1/pentest/sessions", state.agent_api_url);
|
||||||
let resp = reqwest::get(&url)
|
let resp = reqwest::get(&url)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(e.to_string()))?;
|
.map_err(|e| ServerFnError::new(e.to_string()))?;
|
||||||
let body: PentestSessionsResponse = resp
|
let mut body: PentestSessionsResponse = resp
|
||||||
.json()
|
.json()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(e.to_string()))?;
|
.map_err(|e| ServerFnError::new(e.to_string()))?;
|
||||||
|
|
||||||
|
// Fetch DAST targets to resolve target names
|
||||||
|
let targets_url = format!("{}/api/v1/dast/targets", state.agent_api_url);
|
||||||
|
if let Ok(tresp) = reqwest::get(&targets_url).await {
|
||||||
|
if let Ok(tbody) = tresp.json::<serde_json::Value>().await {
|
||||||
|
let targets = tbody.get("data").and_then(|v| v.as_array());
|
||||||
|
if let Some(targets) = targets {
|
||||||
|
// Build target_id -> name lookup
|
||||||
|
let target_map: std::collections::HashMap<String, String> = targets
|
||||||
|
.iter()
|
||||||
|
.filter_map(|t| {
|
||||||
|
let id = t.get("_id")?.get("$oid")?.as_str()?.to_string();
|
||||||
|
let name = t.get("name")?.as_str()?.to_string();
|
||||||
|
Some((id, name))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// Enrich sessions with target_name
|
||||||
|
for session in body.data.iter_mut() {
|
||||||
|
if let Some(tid) = session.get("target_id").and_then(|v| v.as_str()) {
|
||||||
|
if let Some(name) = target_map.get(tid) {
|
||||||
|
session.as_object_mut().map(|obj| {
|
||||||
|
obj.insert(
|
||||||
|
"target_name".to_string(),
|
||||||
|
serde_json::Value::String(name.clone()),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(body)
|
Ok(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,10 +89,33 @@ pub async fn fetch_pentest_session(id: String) -> Result<PentestSessionResponse,
|
|||||||
let resp = reqwest::get(&url)
|
let resp = reqwest::get(&url)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(e.to_string()))?;
|
.map_err(|e| ServerFnError::new(e.to_string()))?;
|
||||||
let body: PentestSessionResponse = resp
|
let mut body: PentestSessionResponse = resp
|
||||||
.json()
|
.json()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ServerFnError::new(e.to_string()))?;
|
.map_err(|e| ServerFnError::new(e.to_string()))?;
|
||||||
|
|
||||||
|
// Resolve target name from targets list
|
||||||
|
if let Some(tid) = body.data.get("target_id").and_then(|v| v.as_str()) {
|
||||||
|
let targets_url = format!("{}/api/v1/dast/targets", state.agent_api_url);
|
||||||
|
if let Ok(tresp) = reqwest::get(&targets_url).await {
|
||||||
|
if let Ok(tbody) = tresp.json::<serde_json::Value>().await {
|
||||||
|
if let Some(targets) = tbody.get("data").and_then(|v| v.as_array()) {
|
||||||
|
for t in targets {
|
||||||
|
let t_id = t.get("_id").and_then(|v| v.get("$oid")).and_then(|v| v.as_str()).unwrap_or("");
|
||||||
|
if t_id == tid {
|
||||||
|
if let Some(name) = t.get("name").and_then(|v| v.as_str()) {
|
||||||
|
body.data.as_object_mut().map(|obj| {
|
||||||
|
obj.insert("target_name".to_string(), serde_json::Value::String(name.to_string()))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(body)
|
Ok(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,7 +209,7 @@ pub async fn send_pentest_message(
|
|||||||
let state: super::server_state::ServerState =
|
let state: super::server_state::ServerState =
|
||||||
dioxus_fullstack::FullstackContext::extract().await?;
|
dioxus_fullstack::FullstackContext::extract().await?;
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"{}/api/v1/pentest/sessions/{session_id}/messages",
|
"{}/api/v1/pentest/sessions/{session_id}/chat",
|
||||||
state.agent_api_url
|
state.agent_api_url
|
||||||
);
|
);
|
||||||
let client = reqwest::Client::new();
|
let client = reqwest::Client::new();
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ pub fn PentestDashboardPage() -> Element {
|
|||||||
Ok(resp) => {
|
Ok(resp) => {
|
||||||
let session_id = resp
|
let session_id = resp
|
||||||
.data
|
.data
|
||||||
.get("id")
|
.get("_id")
|
||||||
|
.and_then(|v| v.get("$oid"))
|
||||||
.and_then(|v| v.as_str())
|
.and_then(|v| v.as_str())
|
||||||
.unwrap_or("")
|
.unwrap_or("")
|
||||||
.to_string();
|
.to_string();
|
||||||
@@ -241,7 +242,10 @@ pub fn PentestDashboardPage() -> Element {
|
|||||||
div { style: "display: grid; gap: 12px; padding: 16px;",
|
div { style: "display: grid; gap: 12px; padding: 16px;",
|
||||||
for session in sess_list {
|
for session in sess_list {
|
||||||
{
|
{
|
||||||
let id = session.get("id").and_then(|v| v.as_str()).unwrap_or("-").to_string();
|
let id = session.get("_id")
|
||||||
|
.and_then(|v| v.get("$oid"))
|
||||||
|
.and_then(|v| v.as_str())
|
||||||
|
.unwrap_or("-").to_string();
|
||||||
let target_name = session.get("target_name").and_then(|v| v.as_str()).unwrap_or("Unknown Target").to_string();
|
let target_name = session.get("target_name").and_then(|v| v.as_str()).unwrap_or("Unknown Target").to_string();
|
||||||
let status = session.get("status").and_then(|v| v.as_str()).unwrap_or("unknown").to_string();
|
let status = session.get("status").and_then(|v| v.as_str()).unwrap_or("unknown").to_string();
|
||||||
let strategy = session.get("strategy").and_then(|v| v.as_str()).unwrap_or("-").to_string();
|
let strategy = session.get("strategy").and_then(|v| v.as_str()).unwrap_or("-").to_string();
|
||||||
@@ -329,7 +333,10 @@ pub fn PentestDashboardPage() -> Element {
|
|||||||
rsx! {
|
rsx! {
|
||||||
for target in &data.data {
|
for target in &data.data {
|
||||||
{
|
{
|
||||||
let tid = target.get("id").and_then(|v| v.as_str()).unwrap_or("").to_string();
|
let tid = target.get("_id")
|
||||||
|
.and_then(|v| v.get("$oid"))
|
||||||
|
.and_then(|v| v.as_str())
|
||||||
|
.unwrap_or("").to_string();
|
||||||
let tname = target.get("name").and_then(|v| v.as_str()).unwrap_or("Unknown").to_string();
|
let tname = target.get("name").and_then(|v| v.as_str()).unwrap_or("Unknown").to_string();
|
||||||
let turl = target.get("base_url").and_then(|v| v.as_str()).unwrap_or("").to_string();
|
let turl = target.get("base_url").and_then(|v| v.as_str()).unwrap_or("").to_string();
|
||||||
rsx! {
|
rsx! {
|
||||||
|
|||||||
Reference in New Issue
Block a user