Skip to content

Commit d7be22b

Browse files
committed
feat: auto-generate random BROKER_JWT_SECRET if not provided
- validator-node generates random UUID as JWT secret on startup - Sets BROKER_JWT_SECRET env var so challenge-orchestrator uses same secret - challenge-orchestrator uses OnceLock for consistent secret across all containers - Ensures broker always requires JWT auth for security
1 parent a980e47 commit d7be22b

File tree

2 files changed

+38
-21
lines changed

2 files changed

+38
-21
lines changed

bins/validator-node/src/main.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,9 +347,19 @@ async fn main() -> Result<()> {
347347
// Container broker
348348
info!("Container broker on port {}...", args.broker_port);
349349
let broker = Arc::new(ContainerBroker::with_policy(SecurityPolicy::default()).await?);
350+
351+
// Use provided JWT secret or generate a random one for this session
352+
let jwt_secret = args.broker_jwt_secret.clone().unwrap_or_else(|| {
353+
let secret = uuid::Uuid::new_v4().to_string();
354+
info!("Generated random BROKER_JWT_SECRET for this session");
355+
// Set env var so challenge-orchestrator uses the same secret
356+
std::env::set_var("BROKER_JWT_SECRET", &secret);
357+
secret
358+
});
359+
350360
let ws_config = WsConfig {
351361
bind_addr: format!("0.0.0.0:{}", args.broker_port),
352-
jwt_secret: args.broker_jwt_secret.clone(),
362+
jwt_secret: Some(jwt_secret),
353363
allowed_challenges: vec![],
354364
max_connections_per_challenge: 10,
355365
};

crates/challenge-orchestrator/src/docker.rs

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -600,26 +600,33 @@ impl DockerClient {
600600
platform_host, broker_port
601601
));
602602

603-
// Pass JWT token for broker authentication (if set)
604-
if let Ok(jwt_secret) = std::env::var("BROKER_JWT_SECRET") {
605-
// Generate a JWT token for this challenge
606-
// Token includes challenge_id and validator_hotkey for authorization
607-
let challenge_id = config.challenge_id.to_string();
608-
let owner_id =
609-
std::env::var("VALIDATOR_HOTKEY").unwrap_or_else(|_| "unknown".to_string());
610-
611-
// Use secure_container_runtime to generate token (3600s = 1 hour TTL)
612-
if let Ok(token) = secure_container_runtime::generate_token(
613-
&challenge_id,
614-
&owner_id,
615-
&jwt_secret,
616-
3600,
617-
) {
618-
env.push(format!("CONTAINER_BROKER_JWT={}", token));
619-
debug!(challenge = %config.name, "Generated broker JWT token");
620-
} else {
621-
warn!(challenge = %config.name, "Failed to generate broker JWT token");
622-
}
603+
// Pass JWT token for broker authentication
604+
// Use BROKER_JWT_SECRET if set, otherwise generate a random one
605+
let jwt_secret = std::env::var("BROKER_JWT_SECRET").unwrap_or_else(|_| {
606+
use std::sync::OnceLock;
607+
static RANDOM_SECRET: OnceLock<String> = OnceLock::new();
608+
RANDOM_SECRET
609+
.get_or_init(|| {
610+
let secret = uuid::Uuid::new_v4().to_string();
611+
info!("Generated random BROKER_JWT_SECRET for this session");
612+
secret
613+
})
614+
.clone()
615+
});
616+
617+
// Generate a JWT token for this challenge
618+
// Token includes challenge_id and validator_hotkey for authorization
619+
let challenge_id = config.challenge_id.to_string();
620+
let owner_id = std::env::var("VALIDATOR_HOTKEY").unwrap_or_else(|_| "unknown".to_string());
621+
622+
// Use secure_container_runtime to generate token (3600s = 1 hour TTL)
623+
if let Ok(token) =
624+
secure_container_runtime::generate_token(&challenge_id, &owner_id, &jwt_secret, 3600)
625+
{
626+
env.push(format!("CONTAINER_BROKER_JWT={}", token));
627+
debug!(challenge = %config.name, "Generated broker JWT token");
628+
} else {
629+
warn!(challenge = %config.name, "Failed to generate broker JWT token");
623630
}
624631

625632
// Create container config

0 commit comments

Comments
 (0)