release: NX9-WG v1.0.0
This commit is contained in:
1 parent
c8a9b7cde6
commit
4dfe42fe68
42 files changed
+4689
-336
No files matched your search
@@ -234,3 +234,178 @@ async fn test_networks_and_firewall_rest_lifecycle() {
|
||||
assert_eq!(rule_val["name"], "Allow HTTPS");
|
||||
assert_eq!(rule_val["priority"], 10);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_list_all_peers_collection_endpoint() {
|
||||
let (app, cookie) = setup_test_app().await;
|
||||
|
||||
// 1. Verify unauthenticated GET /api/v1/peers returns 401 Unauthorized
|
||||
let unauth_req = Request::builder()
|
||||
.uri("/api/v1/peers")
|
||||
.body(Body::empty())
|
||||
.unwrap();
|
||||
let unauth_resp = app.clone().oneshot(unauth_req).await.unwrap();
|
||||
assert_eq!(unauth_resp.status(), StatusCode::UNAUTHORIZED);
|
||||
|
||||
// 2. Create first interface (wg0)
|
||||
let iface0_req = Request::builder()
|
||||
.method("POST")
|
||||
.uri("/api/v1/interfaces")
|
||||
.header(header::COOKIE, &cookie)
|
||||
.header(header::CONTENT_TYPE, "application/json")
|
||||
.body(Body::from(
|
||||
json!({
|
||||
"name": "wg0",
|
||||
"listen_port": 51820,
|
||||
"address_v4": "10.100.0.1/24"
|
||||
})
|
||||
.to_string(),
|
||||
))
|
||||
.unwrap();
|
||||
let iface0_resp = app.clone().oneshot(iface0_req).await.unwrap();
|
||||
assert_eq!(iface0_resp.status(), StatusCode::OK);
|
||||
let iface0_val: Value =
|
||||
serde_json::from_slice(&to_bytes(iface0_resp.into_body(), usize::MAX).await.unwrap())
|
||||
.unwrap();
|
||||
let iface0_id = iface0_val["id"].as_str().unwrap();
|
||||
|
||||
// 3. Create second interface (wg1)
|
||||
let iface1_req = Request::builder()
|
||||
.method("POST")
|
||||
.uri("/api/v1/interfaces")
|
||||
.header(header::COOKIE, &cookie)
|
||||
.header(header::CONTENT_TYPE, "application/json")
|
||||
.body(Body::from(
|
||||
json!({
|
||||
"name": "wg1",
|
||||
"listen_port": 51821,
|
||||
"address_v4": "10.200.0.1/24"
|
||||
})
|
||||
.to_string(),
|
||||
))
|
||||
.unwrap();
|
||||
let iface1_resp = app.clone().oneshot(iface1_req).await.unwrap();
|
||||
assert_eq!(iface1_resp.status(), StatusCode::OK);
|
||||
let iface1_val: Value =
|
||||
serde_json::from_slice(&to_bytes(iface1_resp.into_body(), usize::MAX).await.unwrap())
|
||||
.unwrap();
|
||||
let iface1_id = iface1_val["id"].as_str().unwrap();
|
||||
|
||||
// 4. Create 2 peers under wg0
|
||||
let peer_alice_req = Request::builder()
|
||||
.method("POST")
|
||||
.uri(format!("/api/v1/interfaces/{iface0_id}/peers"))
|
||||
.header(header::COOKIE, &cookie)
|
||||
.header(header::CONTENT_TYPE, "application/json")
|
||||
.body(Body::from(
|
||||
json!({
|
||||
"name": "peer-alice",
|
||||
"allowed_ips": "10.100.0.2/32"
|
||||
})
|
||||
.to_string(),
|
||||
))
|
||||
.unwrap();
|
||||
let resp_alice = app.clone().oneshot(peer_alice_req).await.unwrap();
|
||||
assert_eq!(resp_alice.status(), StatusCode::OK);
|
||||
|
||||
let peer_bob_req = Request::builder()
|
||||
.method("POST")
|
||||
.uri(format!("/api/v1/interfaces/{iface0_id}/peers"))
|
||||
.header(header::COOKIE, &cookie)
|
||||
.header(header::CONTENT_TYPE, "application/json")
|
||||
.body(Body::from(
|
||||
json!({
|
||||
"name": "peer-bob",
|
||||
"allowed_ips": "10.100.0.3/32"
|
||||
})
|
||||
.to_string(),
|
||||
))
|
||||
.unwrap();
|
||||
let resp_bob = app.clone().oneshot(peer_bob_req).await.unwrap();
|
||||
assert_eq!(resp_bob.status(), StatusCode::OK);
|
||||
|
||||
// 5. Create 1 peer under wg1
|
||||
let peer_charlie_req = Request::builder()
|
||||
.method("POST")
|
||||
.uri(format!("/api/v1/interfaces/{iface1_id}/peers"))
|
||||
.header(header::COOKIE, &cookie)
|
||||
.header(header::CONTENT_TYPE, "application/json")
|
||||
.body(Body::from(
|
||||
json!({
|
||||
"name": "peer-charlie",
|
||||
"allowed_ips": "10.200.0.2/32"
|
||||
})
|
||||
.to_string(),
|
||||
))
|
||||
.unwrap();
|
||||
let resp_charlie = app.clone().oneshot(peer_charlie_req).await.unwrap();
|
||||
assert_eq!(resp_charlie.status(), StatusCode::OK);
|
||||
|
||||
// 6. Test GET /api/v1/peers (All peers across all interfaces)
|
||||
let list_all_req = Request::builder()
|
||||
.uri("/api/v1/peers")
|
||||
.header(header::COOKIE, &cookie)
|
||||
.body(Body::empty())
|
||||
.unwrap();
|
||||
let list_all_resp = app.clone().oneshot(list_all_req).await.unwrap();
|
||||
assert_eq!(list_all_resp.status(), StatusCode::OK);
|
||||
|
||||
let all_peers_bytes = to_bytes(list_all_resp.into_body(), usize::MAX)
|
||||
.await
|
||||
.unwrap();
|
||||
let all_peers: Vec<Value> = serde_json::from_slice(&all_peers_bytes).unwrap();
|
||||
assert_eq!(
|
||||
all_peers.len(),
|
||||
3,
|
||||
"GET /api/v1/peers must return all 3 peers across both interfaces"
|
||||
);
|
||||
|
||||
let peer_names: Vec<&str> = all_peers
|
||||
.iter()
|
||||
.map(|p| p["name"].as_str().unwrap())
|
||||
.collect();
|
||||
assert!(peer_names.contains(&"peer-alice"));
|
||||
assert!(peer_names.contains(&"peer-bob"));
|
||||
assert!(peer_names.contains(&"peer-charlie"));
|
||||
|
||||
// Verify representative fields are present and valid
|
||||
for p in &all_peers {
|
||||
assert!(p["id"].is_string());
|
||||
assert!(p["public_key"].is_string());
|
||||
assert!(p["interface_id"].is_string());
|
||||
assert!(p["state"].is_string());
|
||||
assert!(p["allowed_ips"].is_string());
|
||||
}
|
||||
|
||||
// 7. Verify interface-scoped endpoint still works and returns only that interface's peers
|
||||
let list_iface0_req = Request::builder()
|
||||
.uri(format!("/api/v1/interfaces/{iface0_id}/peers"))
|
||||
.header(header::COOKIE, &cookie)
|
||||
.body(Body::empty())
|
||||
.unwrap();
|
||||
let iface0_peers_resp = app.clone().oneshot(list_iface0_req).await.unwrap();
|
||||
assert_eq!(iface0_peers_resp.status(), StatusCode::OK);
|
||||
let iface0_peers: Vec<Value> = serde_json::from_slice(
|
||||
&to_bytes(iface0_peers_resp.into_body(), usize::MAX)
|
||||
.await
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(iface0_peers.len(), 2, "wg0 must return exactly 2 peers");
|
||||
|
||||
let list_iface1_req = Request::builder()
|
||||
.uri(format!("/api/v1/interfaces/{iface1_id}/peers"))
|
||||
.header(header::COOKIE, &cookie)
|
||||
.body(Body::empty())
|
||||
.unwrap();
|
||||
let iface1_peers_resp = app.oneshot(list_iface1_req).await.unwrap();
|
||||
assert_eq!(iface1_peers_resp.status(), StatusCode::OK);
|
||||
let iface1_peers: Vec<Value> = serde_json::from_slice(
|
||||
&to_bytes(iface1_peers_resp.into_body(), usize::MAX)
|
||||
.await
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(iface1_peers.len(), 1, "wg1 must return exactly 1 peer");
|
||||
assert_eq!(iface1_peers[0]["name"], "peer-charlie");
|
||||
}
|
||||
Reference in new issue
Block a user