116 lines
4.0 KiB
Rust
116 lines
4.0 KiB
Rust
use crate::common::TestServer;
|
|
use serde_json::json;
|
|
|
|
#[tokio::test]
|
|
async fn create_list_and_applicable_scans() {
|
|
let server = TestServer::start().await;
|
|
|
|
// Initially empty.
|
|
let resp = server.get("/api/v1/targets").await;
|
|
assert_eq!(resp.status(), 200);
|
|
let body: serde_json::Value = resp.json().await.unwrap();
|
|
assert_eq!(body["data"].as_array().unwrap().len(), 0);
|
|
|
|
// Create a web-app target with a git repo + a live URL.
|
|
let resp = server
|
|
.post(
|
|
"/api/v1/targets",
|
|
&json!({
|
|
"name": "acme-web",
|
|
"target_type": "web_app",
|
|
"artifacts": [
|
|
{ "kind": "git_repo", "source_ref": "https://git/acme.git", "branch": "main" },
|
|
{ "kind": "live_url", "source_ref": "https://acme.example.com" }
|
|
]
|
|
}),
|
|
)
|
|
.await;
|
|
assert_eq!(resp.status(), 200);
|
|
let body: serde_json::Value = resp.json().await.unwrap();
|
|
let id = body["data"]["_id"]["$oid"].as_str().unwrap().to_string();
|
|
assert!(!id.is_empty());
|
|
assert_eq!(body["data"]["artifacts"].as_array().unwrap().len(), 2);
|
|
|
|
// List returns it.
|
|
let resp = server.get("/api/v1/targets").await;
|
|
let body: serde_json::Value = resp.json().await.unwrap();
|
|
assert_eq!(body["data"].as_array().unwrap().len(), 1);
|
|
|
|
// Applicable scans: SAST present + DAST offered (live URL present), pentest supported.
|
|
let resp = server
|
|
.get(&format!("/api/v1/targets/{id}/applicable-scans"))
|
|
.await;
|
|
assert_eq!(resp.status(), 200);
|
|
let body: serde_json::Value = resp.json().await.unwrap();
|
|
let scans = body["data"]["scans"].as_array().unwrap();
|
|
let names: Vec<&str> = scans.iter().filter_map(|s| s["scan"].as_str()).collect();
|
|
assert!(names.contains(&"sast"));
|
|
assert!(names.contains(&"dast"));
|
|
assert_eq!(body["data"]["pentest_supported"], true);
|
|
|
|
server.cleanup().await;
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn detect_classifies_a_plc_target() {
|
|
let server = TestServer::start().await;
|
|
|
|
// A PLC project artifact is a strong kind-based signal.
|
|
let resp = server
|
|
.post(
|
|
"/api/v1/targets",
|
|
&json!({
|
|
"name": "line-controller",
|
|
"target_type": "backend_service", // deliberately wrong; detect should suggest PLC
|
|
"artifacts": [
|
|
{ "kind": "plc_project", "source_ref": "line.xml", "plc_format": "plcopen_xml" }
|
|
]
|
|
}),
|
|
)
|
|
.await;
|
|
let body: serde_json::Value = resp.json().await.unwrap();
|
|
let id = body["data"]["_id"]["$oid"].as_str().unwrap().to_string();
|
|
|
|
let resp = server
|
|
.post(&format!("/api/v1/targets/{id}/detect"), &json!({}))
|
|
.await;
|
|
assert_eq!(resp.status(), 200);
|
|
let body: serde_json::Value = resp.json().await.unwrap();
|
|
assert_eq!(body["data"]["classification"]["suggested"], "plc_sps");
|
|
|
|
server.cleanup().await;
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn add_artifact_and_delete_target() {
|
|
let server = TestServer::start().await;
|
|
|
|
let resp = server
|
|
.post(
|
|
"/api/v1/targets",
|
|
&json!({ "name": "svc", "target_type": "backend_service" }),
|
|
)
|
|
.await;
|
|
let body: serde_json::Value = resp.json().await.unwrap();
|
|
let id = body["data"]["_id"]["$oid"].as_str().unwrap().to_string();
|
|
|
|
// Attach a git repo.
|
|
let resp = server
|
|
.post(
|
|
&format!("/api/v1/targets/{id}/artifacts"),
|
|
&json!({ "kind": "git_repo", "source_ref": "https://git/svc.git" }),
|
|
)
|
|
.await;
|
|
assert_eq!(resp.status(), 200);
|
|
let body: serde_json::Value = resp.json().await.unwrap();
|
|
assert_eq!(body["data"]["artifacts"].as_array().unwrap().len(), 1);
|
|
|
|
// Delete it.
|
|
let resp = server.delete(&format!("/api/v1/targets/{id}")).await;
|
|
assert_eq!(resp.status(), 200);
|
|
let resp = server.get(&format!("/api/v1/targets/{id}")).await;
|
|
assert_eq!(resp.status(), 404);
|
|
|
|
server.cleanup().await;
|
|
}
|