perf: add RPC auth profiling diagnostics (#5775)

perf: add rpc auth profiling diagnostics

Co-authored-by: heihutu <heihutu@gmail.com>
Co-authored-by: zhi22915 <qiuzgang@gmail.com>
This commit is contained in:
houseme
2026-08-06 21:33:17 +08:00
committed by GitHub
parent e26b869259
commit fc0de983d8
8 changed files with 244 additions and 6 deletions
+1 -1
View File
@@ -439,7 +439,7 @@ pub mod rpc {
gen_tonic_replay_scope_headers, gen_tonic_signature_headers, gen_tonic_signature_interceptor,
node_service_time_out_client, node_service_time_out_client_no_auth, normalize_tonic_rpc_audience,
set_tonic_canonical_body_digest, sign_ns_scanner_capability, sign_tonic_rpc_response_proof, tonic_boot_epoch_challenge,
tonic_boot_epoch_response_headers, verify_rpc_signature, verify_tonic_boot_epoch_response,
tonic_boot_epoch_response_headers, tonic_rpc_auth_failure_reason, verify_rpc_signature, verify_tonic_boot_epoch_response,
verify_tonic_canonical_body_digest, verify_tonic_mutation_body_digest, verify_tonic_rpc_response_proof,
verify_tonic_rpc_signature, verify_tonic_rpc_signature_with_bootstrap,
};
@@ -847,6 +847,46 @@ pub fn verify_tonic_rpc_signature_with_bootstrap(
)
}
pub fn tonic_rpc_auth_failure_reason(error: &std::io::Error) -> &'static str {
match error.to_string().as_str() {
"Missing RPC audience" => "missing_audience",
"Invalid RPC request path" => "invalid_request_path",
"RPC replay-scoped authentication required" => "replay_scope_required",
"Missing RPC replay scope version" => "missing_replay_scope_version",
"Unsupported RPC replay scope version" => "unsupported_replay_scope_version",
"Missing RPC replay scope signature" => "missing_replay_scope_signature",
"Missing RPC replay scope nonce" => "missing_replay_scope_nonce",
"Invalid RPC replay scope nonce" => "invalid_replay_scope_nonce",
"Missing RPC boot epoch" => "missing_boot_epoch",
"Invalid RPC boot epoch" => "invalid_boot_epoch",
"Invalid RPC replay scope signature" => "invalid_replay_scope_signature",
"RPC boot epoch is stale" => "stale_boot_epoch",
"RPC request replay detected" => "replay_detected",
"RPC replay cache capacity exceeded" => "replay_cache_capacity",
"RPC replay cache unavailable" => "replay_cache_unavailable",
"RPC replay expiry overflow" => "replay_expiry_overflow",
"RPC request timestamp expired after clock regression" => "timestamp_expired_after_clock_regression",
"RPC v2 authentication required" => "v2_required",
"Missing RPC auth version" => "missing_v2_auth_version",
"Unsupported RPC auth version" => "unsupported_v2_auth_version",
"Missing RPC v2 signature" => "missing_v2_signature",
"Invalid RPC v2 signature" => "invalid_v2_signature",
"Missing timestamp header" => "missing_timestamp",
"Invalid timestamp format" => "invalid_timestamp",
"Request timestamp expired" => "timestamp_expired",
"Missing RPC nonce" => "missing_v2_nonce",
"Invalid RPC nonce" => "invalid_v2_nonce",
"Invalid unsigned RPC nonce" => "invalid_unsigned_v2_nonce",
"Missing RPC content SHA-256" => "missing_content_sha256",
"Invalid RPC content SHA-256" => "invalid_content_sha256",
"Missing signature header" => "missing_v1_signature",
"Invalid signature" => "invalid_v1_signature",
"Invalid RPC HMAC key" => "invalid_hmac_key",
message if message.contains(RPC_SECRET_REQUIRED_OPERATOR_MESSAGE) => "missing_rpc_secret",
_ => "unknown",
}
}
fn verify_tonic_rpc_signature_with_policy(
audience: &str,
path: &str,
@@ -1699,6 +1739,31 @@ mod tests {
assert!(verify_tonic_boot_epoch_response("node-a:9000", Uuid::new_v4(), &headers).is_err());
}
#[test]
fn tonic_rpc_auth_failure_reason_maps_security_relevant_errors() {
for (message, reason) in [
("Invalid RPC v2 signature", "invalid_v2_signature"),
("RPC replay-scoped authentication required", "replay_scope_required"),
("Missing RPC replay scope signature", "missing_replay_scope_signature"),
("RPC boot epoch is stale", "stale_boot_epoch"),
("RPC request replay detected", "replay_detected"),
("Request timestamp expired", "timestamp_expired"),
("Missing RPC content SHA-256", "missing_content_sha256"),
("Invalid RPC content SHA-256", "invalid_content_sha256"),
] {
assert_eq!(
tonic_rpc_auth_failure_reason(&std::io::Error::other(message)),
reason,
"message {message:?} should map to a stable low-cardinality reason"
);
}
}
#[test]
fn tonic_rpc_auth_failure_reason_falls_back_for_unclassified_errors() {
assert_eq!(tonic_rpc_auth_failure_reason(&std::io::Error::other("opaque failure")), "unknown");
}
#[test]
fn malformed_v2_auth_does_not_downgrade_to_valid_legacy_signature() {
ensure_test_rpc_secret();
+2 -2
View File
@@ -34,8 +34,8 @@ pub use client::{
pub use http_auth::{
TONIC_RPC_PREFIX, build_auth_headers, gen_signature_headers, gen_tonic_replay_scope_headers, gen_tonic_signature_headers,
normalize_tonic_rpc_audience, set_tonic_canonical_body_digest, set_tonic_mutation_body_digest, sign_ns_scanner_capability,
sign_tonic_rpc_response_proof, tonic_boot_epoch_challenge, tonic_boot_epoch_response_headers, verify_ns_scanner_capability,
verify_rpc_signature, verify_tonic_boot_epoch_response, verify_tonic_canonical_body_digest,
sign_tonic_rpc_response_proof, tonic_boot_epoch_challenge, tonic_boot_epoch_response_headers, tonic_rpc_auth_failure_reason,
verify_ns_scanner_capability, verify_rpc_signature, verify_tonic_boot_epoch_response, verify_tonic_canonical_body_digest,
verify_tonic_mutation_body_digest, verify_tonic_rpc_response_proof, verify_tonic_rpc_signature,
verify_tonic_rpc_signature_with_bootstrap,
};