fix: redact observation source debug output

This commit is contained in:
Keisuke Hirata 2026-06-26 15:27:08 +09:00
parent aeb12b3b8e
commit 38ff7d8f80
No known key found for this signature in database

View File

@ -10,7 +10,7 @@ use tokio_tungstenite::tungstenite::{Error as TungsteniteError, Message as Tungs
use worker_runtime::http_server::{RuntimeWorkerEventWsEnvelope, RuntimeWorkerEventWsFrame}; use worker_runtime::http_server::{RuntimeWorkerEventWsEnvelope, RuntimeWorkerEventWsFrame};
/// Backend-private source for a runtime worker observation stream. /// Backend-private source for a runtime worker observation stream.
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, PartialEq, Eq)]
pub struct RuntimeObservationSourceConfig { pub struct RuntimeObservationSourceConfig {
pub runtime_id: String, pub runtime_id: String,
pub worker_id: String, pub worker_id: String,
@ -18,6 +18,20 @@ pub struct RuntimeObservationSourceConfig {
pub bearer_token: Option<String>, pub bearer_token: Option<String>,
} }
impl std::fmt::Debug for RuntimeObservationSourceConfig {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RuntimeObservationSourceConfig")
.field("runtime_id", &self.runtime_id)
.field("worker_id", &self.worker_id)
.field("endpoint", &"<backend-private>")
.field(
"bearer_token",
&self.bearer_token.as_ref().map(|_| "<redacted>"),
)
.finish()
}
}
/// Event consumed from a Runtime-owned worker observation WebSocket. /// Event consumed from a Runtime-owned worker observation WebSocket.
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct RuntimeObservationUpstreamEvent { pub struct RuntimeObservationUpstreamEvent {
@ -181,12 +195,21 @@ pub struct BackendObservationOpen {
} }
/// Backend-owned in-memory v0 observation proxy state. /// Backend-owned in-memory v0 observation proxy state.
#[derive(Clone, Debug)] #[derive(Clone)]
pub struct BackendObservationProxy { pub struct BackendObservationProxy {
sources: Arc<BTreeMap<ObservationKey, RuntimeObservationSourceConfig>>, sources: Arc<BTreeMap<ObservationKey, RuntimeObservationSourceConfig>>,
state: Arc<Mutex<BackendObservationState>>, state: Arc<Mutex<BackendObservationState>>,
} }
impl std::fmt::Debug for BackendObservationProxy {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("BackendObservationProxy")
.field("source_count", &self.sources.len())
.field("state", &"<omitted>")
.finish()
}
}
impl BackendObservationProxy { impl BackendObservationProxy {
pub fn new(sources: Vec<RuntimeObservationSourceConfig>) -> Self { pub fn new(sources: Vec<RuntimeObservationSourceConfig>) -> Self {
let sources = sources let sources = sources
@ -475,3 +498,56 @@ impl RuntimeWsObservationClient {
} }
} }
} }
#[cfg(test)]
mod tests {
use super::*;
fn sensitive_source() -> RuntimeObservationSourceConfig {
RuntimeObservationSourceConfig {
runtime_id: "remote-runtime".to_string(),
worker_id: "worker-1".to_string(),
endpoint: "wss://remote.example.invalid/private/workers/worker-1/events/ws".to_string(),
bearer_token: Some("top-secret-bearer-token".to_string()),
}
}
#[test]
fn runtime_observation_source_debug_redacts_endpoint_and_token() {
let debug = format!("{:?}", sensitive_source());
assert!(debug.contains("remote-runtime"));
assert!(debug.contains("worker-1"));
assert!(debug.contains("<backend-private>"));
assert!(debug.contains("<redacted>"));
for forbidden in [
"remote.example.invalid",
"/private/workers/worker-1/events/ws",
"top-secret-bearer-token",
] {
assert!(
!debug.contains(forbidden),
"debug leaked {forbidden}: {debug}"
);
}
}
#[test]
fn backend_observation_proxy_debug_redacts_contained_sources() {
let proxy = BackendObservationProxy::new(vec![sensitive_source()]);
let debug = format!("{proxy:?}");
assert!(debug.contains("BackendObservationProxy"));
assert!(debug.contains("source_count"));
for forbidden in [
"remote.example.invalid",
"/private/workers/worker-1/events/ws",
"top-secret-bearer-token",
] {
assert!(
!debug.contains(forbidden),
"debug leaked {forbidden}: {debug}"
);
}
}
}