0.34.6_repo_cleanup
This commit is contained in:
1 parent
ce1a90397c
commit
133d2f0f91
273 files changed
+5969
-6926
No files matched your search
+110
-63
@@ -315,7 +315,6 @@ mod tests {
|
||||
.unwrap();
|
||||
assert_eq!(response.status(), StatusCode::FORBIDDEN);
|
||||
}
|
||||
// Origin on an ordinary same-origin GET may be absent, or may match.
|
||||
for origin in [None, Some("http://127.0.0.1:9090")] {
|
||||
let mut request = Request::builder()
|
||||
.uri("/api/auth/session")
|
||||
@@ -902,7 +901,6 @@ mod tests {
|
||||
.await
|
||||
.unwrap();
|
||||
if path == "/logs" {
|
||||
// The operational log route is private even on browser refresh.
|
||||
assert_eq!(public.status(), StatusCode::UNAUTHORIZED);
|
||||
assert_eq!(json_body(public).await, json!({"error":"auth.required"}));
|
||||
} else {
|
||||
@@ -1243,7 +1241,6 @@ mod tests {
|
||||
.body(Body::from("{}"))
|
||||
.unwrap()
|
||||
};
|
||||
// Certificate API credentials cannot trigger an all-certificate reload.
|
||||
let response = router
|
||||
.clone()
|
||||
.oneshot(external(
|
||||
@@ -1254,8 +1251,6 @@ mod tests {
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(response.status(), StatusCode::FORBIDDEN);
|
||||
// The allowlisted ID passes the auth gate and reaches the handler; this
|
||||
// fixture intentionally has no such configured certificate, so it is 404.
|
||||
let response = router
|
||||
.clone()
|
||||
.oneshot(external(
|
||||
@@ -1266,7 +1261,6 @@ mod tests {
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
||||
// A reload-only token cannot use the deploy endpoint at all.
|
||||
let response = router
|
||||
.clone()
|
||||
.oneshot(
|
||||
@@ -1281,7 +1275,6 @@ mod tests {
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(response.status(), StatusCode::FORBIDDEN);
|
||||
// A different ID is rejected by the credential grant before the handler.
|
||||
let response = router
|
||||
.clone()
|
||||
.oneshot(external(
|
||||
@@ -1320,8 +1313,6 @@ mod tests {
|
||||
.unwrap();
|
||||
assert_eq!(response.status(), StatusCode::FORBIDDEN);
|
||||
|
||||
// This fixture has no certificate directory. An out-of-scope credential
|
||||
// must see only the grant error, never the storage availability error.
|
||||
assert_eq!(
|
||||
json_body(response).await,
|
||||
json!({"error":"certificate_api.certificate_forbidden"})
|
||||
@@ -1482,7 +1473,6 @@ mod tests {
|
||||
assert!(detail["credential"].get("token_hash").is_none());
|
||||
let created_at = detail["credential"]["created_at"].clone();
|
||||
|
||||
// A bearer-only automation client cannot read or modify management records.
|
||||
let denied = router
|
||||
.clone()
|
||||
.oneshot(
|
||||
@@ -1526,7 +1516,6 @@ mod tests {
|
||||
.unwrap();
|
||||
assert_eq!(wildcard.status(), StatusCode::UNPROCESSABLE_ENTITY);
|
||||
|
||||
// An edit changes only metadata and grants, not the current bearer secret.
|
||||
let edited = router.clone().oneshot(admin(
|
||||
Method::PATCH, "/api/certificate-api/certbot-prod",
|
||||
json!({"comment":"updated owner", "certificate_ids":["new-cert", "new-cert"], "allow_deploy":true}),
|
||||
@@ -1895,8 +1884,6 @@ mod tests {
|
||||
"backend_table_sort":"requests",
|
||||
"backend_table_descending":true
|
||||
});
|
||||
// Older clients may omit fields added since their preferences were
|
||||
// saved. The API returns and stores the typed, defaulted document.
|
||||
let normalized = serde_json::to_value(
|
||||
serde_json::from_value::<AdminPreferences>(selected.clone()).unwrap(),
|
||||
)
|
||||
@@ -1943,7 +1930,6 @@ mod tests {
|
||||
serde_json::from_str(&store.admin_preferences("owner").await.unwrap().unwrap())
|
||||
.unwrap();
|
||||
assert_eq!(saved, normalized);
|
||||
// Preferences must also survive a subsequent authenticated read.
|
||||
let persisted = router
|
||||
.clone()
|
||||
.oneshot(
|
||||
@@ -1976,7 +1962,6 @@ mod tests {
|
||||
}
|
||||
}
|
||||
assert_eq!(json_body(persisted).await, upgraded);
|
||||
// Wrong allowlist value is rejected even if the rest is valid.
|
||||
let mut invalid = selected.clone();
|
||||
invalid["refresh"]["traffic_seconds"] = json!(4);
|
||||
let rejected = router
|
||||
@@ -2120,8 +2105,6 @@ mod tests {
|
||||
if valid_csrf {
|
||||
req = req.header("x-csrf-token", &csrf);
|
||||
}
|
||||
// This fixture has no certificate directory: valid auth reaches the
|
||||
// 409 precondition, never a child process, DNS update or CA request.
|
||||
let response = router
|
||||
.clone()
|
||||
.oneshot(req.body(Body::from("{}")).unwrap())
|
||||
@@ -2898,7 +2881,6 @@ mod tests {
|
||||
.collect::<Vec<_>>(),
|
||||
vec![Some(200), Some(404), Some(500), None]
|
||||
);
|
||||
// Page two must reflect the sorted complete scan, not a local page sort.
|
||||
assert_eq!(records[1]["status"], 404);
|
||||
sort_file_log_records(&mut records, "status", true);
|
||||
assert_eq!(
|
||||
@@ -3099,8 +3081,6 @@ mod tests {
|
||||
assert_eq!(live.status(), StatusCode::OK);
|
||||
let live = json_body(live).await;
|
||||
assert!(live.get("metrics").is_some());
|
||||
// Compact snapshots contain only already-collected data required for
|
||||
// fast Overview charts, not the expensive System details document.
|
||||
assert!(live["live_system"].get("sampled_at_ms").is_some());
|
||||
assert!(live["live_system"].get("process_cpu_percent").is_some());
|
||||
assert!(live["live_system"].get("process_rss_bytes").is_some());
|
||||
@@ -3170,7 +3150,7 @@ mod tests {
|
||||
}
|
||||
value.overview_seconds = 3;
|
||||
assert!(validate_refresh_preferences(&value).is_ok());
|
||||
value.overview_seconds = 2; // previous installations stay valid
|
||||
value.overview_seconds = 2;
|
||||
assert!(validate_refresh_preferences(&value).is_ok());
|
||||
value.overview_seconds = 1;
|
||||
for seconds in [1, 2, 4, 31] {
|
||||
@@ -3256,8 +3236,6 @@ mod tests {
|
||||
"CSRF {method} {path}"
|
||||
);
|
||||
}
|
||||
// The valid session and CSRF continue to work for a benign mutation,
|
||||
// proving the failed requests above did not revoke the cookie.
|
||||
let response = router
|
||||
.oneshot(
|
||||
request("/api/auth/logout")
|
||||
@@ -3341,8 +3319,6 @@ mod tests {
|
||||
config.administration.public_origin = Some("https://panel.example.test".into());
|
||||
let (router, store, _dir, secret, csrf) = fixture_with_config(config).await;
|
||||
let cookie = format!("{}={secret}", auth::COOKIE_NAME);
|
||||
// Without an explicit origin pin, 0.31.3 rejected this session GET as
|
||||
// external_scheme although the browser address remained correct.
|
||||
let result = router
|
||||
.clone()
|
||||
.oneshot(
|
||||
@@ -3367,8 +3343,6 @@ mod tests {
|
||||
.unwrap();
|
||||
assert!(session_cookie.contains("; Secure"));
|
||||
|
||||
// The incoming admin Host may itself be the pinned public DNS name.
|
||||
// There is no separate allowed_hosts entry in the saved configuration.
|
||||
let pinned_host = Request::builder()
|
||||
.uri("/api/auth/session")
|
||||
.header("host", "panel.example.test")
|
||||
@@ -3383,8 +3357,6 @@ mod tests {
|
||||
StatusCode::OK
|
||||
);
|
||||
|
||||
// Explicit Origin, CSRF token and app request marker remain mandatory
|
||||
// for a state-changing request even when XFP contains multiple hops.
|
||||
let unauthorized = router
|
||||
.clone()
|
||||
.oneshot(
|
||||
@@ -3484,8 +3456,6 @@ mod tests {
|
||||
assert_eq!(result.status(), StatusCode::FORBIDDEN,
|
||||
"must reject forwarded-host={xfh}, proto={xfp}, origin={origin}, fetch={fetch_site}");
|
||||
}
|
||||
// Credential-bearing certificate automation does not inherit the
|
||||
// browser-origin override, even through the same trusted admin socket.
|
||||
let automation = router
|
||||
.clone()
|
||||
.oneshot(
|
||||
@@ -3582,10 +3552,8 @@ mod tests {
|
||||
assert!(payload["config"].get("storage").is_none());
|
||||
assert_eq!(payload["storage"]["mode"], "sqlite");
|
||||
assert!(payload["storage"]["config_path"].is_null());
|
||||
assert!(payload["storage"]["database_path"].is_null()); // fixture omits data_dir
|
||||
assert!(payload["storage"]["database_path"].is_null());
|
||||
|
||||
// The old GET endpoint is gone. A dynamic PUT-only section route may
|
||||
// match the path, but it must not respond to GET.
|
||||
let old_route = router
|
||||
.oneshot(
|
||||
request("/api/config/storage")
|
||||
@@ -3669,15 +3637,38 @@ mod tests {
|
||||
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();
|
||||
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"));
|
||||
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"] {
|
||||
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);
|
||||
@@ -3687,21 +3678,52 @@ mod tests {
|
||||
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!(
|
||||
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"]);
|
||||
assert_eq!(
|
||||
summary["vhosts"]["enabled"],
|
||||
snapshot["summary"]["vhosts"]["enabled"]
|
||||
);
|
||||
assert_eq!(
|
||||
summary["backends"]["total"],
|
||||
snapshot["summary"]["backends"]["total"]
|
||||
);
|
||||
store.close().await;
|
||||
}
|
||||
|
||||
@@ -3710,12 +3732,20 @@ mod tests {
|
||||
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());
|
||||
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}"));
|
||||
let mut request =
|
||||
request("/api/metrics/json").header("authorization", format!("Bearer {token}"));
|
||||
if let Some(peer) = peer {
|
||||
request = request.extension(PeerAddr(peer.parse().unwrap()));
|
||||
}
|
||||
@@ -3723,19 +3753,36 @@ mod tests {
|
||||
};
|
||||
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();
|
||||
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())); }
|
||||
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!(
|
||||
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());
|
||||
|
||||
Reference in new issue
Block a user