This commit is contained in:
Mateusz Gruszczyński committed 2026-10-19 15:40:37 +02:00
1 parent 34fb534e02
commit b2b5b45d8a
22 files changed
+2146 -107

No files matched your search

+79
View File
@@ -2250,6 +2250,7 @@ mod tests {
"/api/acme",
"/api/auth/session",
"/api/metrics",
"/api/metrics/json",
"/metrics",
"/docs/openapi.json",
"/docs/content.json",
@@ -3664,6 +3665,84 @@ mod tests {
store.close().await;
}
#[tokio::test]
async fn json_metrics_api_is_authenticated_and_matches_prometheus_families() {
let (router, store, _dir, secret, _) = fixture().await;
let cookie = format!("{}={secret}", auth::COOKIE_NAME);
let snapshot = router.clone().oneshot(
request("/api/metrics/json").header("cookie", &cookie)
.body(Body::empty()).unwrap()
).await.unwrap();
assert_eq!(snapshot.status(), StatusCode::OK);
assert!(snapshot.headers()["content-type"].to_str().unwrap().starts_with("application/json"));
let snapshot = json_body(snapshot).await;
for field in ["summary", "vhosts", "requests", "system", "cache", "backends", "web_server",
"streams", "docker", "traffic", "transform", "logging", "capacity", "prometheus"] {
assert!(snapshot.get(field).is_some(), "missing: {field}");
}
assert_eq!(snapshot["vhosts"]["total"], 0);
assert_eq!(snapshot["vhosts"]["enabled"], 0);
assert_eq!(snapshot["vhosts"]["disabled"], 0);
assert_eq!(snapshot["summary"]["vhosts"]["enabled"], 0);
assert_eq!(snapshot["summary"]["backends"]["total"], 0);
assert!(snapshot["summary"]["traffic"]["bytes_total"].is_number());
assert!(snapshot["prometheus"]["samples"]["rust_proxy_requests_total"].is_array());
assert_eq!(snapshot["prometheus"]["types"]["rust_proxy_requests_total"], "counter");
assert!(general_api_token_allowed(&Method::GET, "/api/metrics/json", "ro"));
assert!(general_api_token_allowed(&Method::GET, "/api/metrics/summary", "ro"));
assert!(!general_api_token_allowed(&Method::POST, "/api/metrics/json", "rw"));
assert!(!general_api_token_allowed(&Method::POST, "/api/metrics/summary", "rw"));
let summary = router.clone().oneshot(
request("/api/metrics/summary").header("cookie", &cookie)
.body(Body::empty()).unwrap()
).await.unwrap();
assert_eq!(summary.status(), StatusCode::OK);
assert_eq!(summary.headers()["cache-control"], "no-store");
let summary = json_body(summary).await;
assert!(summary.get("prometheus").is_none());
assert_eq!(summary["vhosts"]["enabled"], snapshot["summary"]["vhosts"]["enabled"]);
assert_eq!(summary["backends"]["total"], snapshot["summary"]["backends"]["total"]);
store.close().await;
}
#[tokio::test]
async fn json_metrics_accepts_ro_bearer_only_from_allowed_peer() {
let (router, store, _dir, _, _) = fixture().await;
let token = "T".repeat(64);
let cidrs = vec!["127.0.0.1/32".to_string()];
assert!(store.create_api_token(
"api-monitor", &auth::secret_hash(&token), "ro", "monitor test", &cidrs, "owner"
).await.unwrap());
let build = |peer: Option<&str>| {
let mut request = request("/api/metrics/json")
.header("authorization", format!("Bearer {token}"));
if let Some(peer) = peer {
request = request.extension(PeerAddr(peer.parse().unwrap()));
}
request.body(Body::empty()).unwrap()
};
let response = router.clone().oneshot(build(None)).await.unwrap();
assert_eq!(response.status(), StatusCode::FORBIDDEN);
let response = router.clone().oneshot(build(Some("127.0.0.1:12345"))).await.unwrap();
assert_eq!(response.status(), StatusCode::OK);
let response = json_body(response).await;
assert!(response["prometheus"]["samples"].is_object());
assert!(response.get("config").is_none());
let summarize = |peer: Option<&str>| {
let mut req = request("/api/metrics/summary")
.header("authorization", format!("Bearer {token}"));
if let Some(peer) = peer { req = req.extension(PeerAddr(peer.parse().unwrap())); }
req.body(Body::empty()).unwrap()
};
assert_eq!(router.clone().oneshot(summarize(None)).await.unwrap().status(), StatusCode::FORBIDDEN);
let summary = router.oneshot(summarize(Some("127.0.0.1:12345"))).await.unwrap();
assert_eq!(summary.status(), StatusCode::OK);
let summary = json_body(summary).await;
assert!(summary["traffic"]["requests_total"].is_number());
assert!(summary.get("prometheus").is_none());
store.close().await;
}
#[test]
fn storage_metadata_is_exposed_only_through_configuration_get_to_api_tokens() {
assert!(general_api_token_allowed(&Method::GET, "/api/config", "ro"));