You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iggy.apache.org by pi...@apache.org on 2026/03/18 20:11:13 UTC
(iggy) branch improve_http_secret created (now 48fa292f6)
This is an automated email from the ASF dual-hosted git repository.
piotr pushed a change to branch improve_http_secret
in repository https://gitbox.apache.org/repos/asf/iggy.git
at 48fa292f6 feat(security): generate random JWT secrets when not configured
This branch includes the following new commits:
new 48fa292f6 feat(security): generate random JWT secrets when not configured
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(iggy) 01/01: feat(security): generate random JWT secrets when not configured
Posted by pi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
piotr pushed a commit to branch improve_http_secret
in repository https://gitbox.apache.org/repos/asf/iggy.git
commit 48fa292f6ee17d419908f7f4e0d1e01e9ed9e5f6
Author: spetz <pi...@gmail.com>
AuthorDate: Wed Mar 18 21:11:04 2026 +0100
feat(security): generate random JWT secrets when not configured
---
Cargo.toml | 55 ++++------------------------------
core/ai/mcp/Cargo.toml | 6 +---
core/configs/src/server_config/http.rs | 8 -----
core/integration/Cargo.toml | 7 +----
core/server/config.toml | 6 ++--
core/server/src/http/http_server.rs | 25 ++++++++++++++--
6 files changed, 35 insertions(+), 72 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
index 539251436..e6ebfb7f9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -97,19 +97,7 @@ clap_complete = "4.5.66"
clock = { path = "core/clock" }
colored = "3.1.1"
comfy-table = "7.2.2"
-compio = { version = "0.18.0", features = [
- "runtime",
- "macros",
- "io-uring",
- "time",
- "rustls",
- "ring",
- "net",
- "quic",
- "tls",
- "ws",
- "fs",
-] }
+compio = { version = "0.18.0", features = ["runtime", "macros", "io-uring", "time", "rustls", "ring", "net", "quic", "tls", "ws", "fs"] }
# Pin compio-driver >= 0.11.2 to fix musl compilation (compio-rs/compio#668)
compio-driver = "0.11.3"
configs = { path = "core/configs", version = "0.1.0" }
@@ -188,22 +176,9 @@ octocrab = "0.49.5"
once_cell = "1.21.3"
opentelemetry = { version = "0.31.0", features = ["trace", "logs"] }
opentelemetry-appender-tracing = { version = "0.31.1", features = ["log"] }
-opentelemetry-otlp = { version = "0.31.0", features = [
- "logs",
- "trace",
- "grpc-tonic",
- "http",
- "http-proto",
- "reqwest-client",
-] }
+opentelemetry-otlp = { version = "0.31.0", features = ["logs", "trace", "grpc-tonic", "http", "http-proto", "reqwest-client"] }
opentelemetry-semantic-conventions = "0.31.0"
-opentelemetry_sdk = { version = "0.31.0", features = [
- "logs",
- "trace",
- "experimental_async_runtime",
- "experimental_logs_batch_log_processor_with_async_runtime",
- "experimental_trace_batch_span_processor_with_async_runtime",
-] }
+opentelemetry_sdk = { version = "0.31.0", features = ["logs", "trace", "experimental_async_runtime", "experimental_logs_batch_log_processor_with_async_runtime", "experimental_trace_batch_span_processor_with_async_runtime"] }
papaya = "0.2.3"
parquet = "57.3.0"
partitions = { path = "core/partitions" }
@@ -248,13 +223,7 @@ server = { path = "core/server" }
simd-json = { version = "0.17.0", features = ["serde_impl"] }
slab = "0.4.12"
socket2 = "0.6.3"
-sqlx = { version = "0.8.6", features = [
- "runtime-tokio-rustls",
- "postgres",
- "chrono",
- "uuid",
- "json",
-] }
+sqlx = { version = "0.8.6", features = ["runtime-tokio-rustls", "postgres", "chrono", "uuid", "json"] }
static-toml = "1.3.0"
strum = { version = "0.28.0", features = ["derive"] }
strum_macros = "0.28.0"
@@ -273,11 +242,7 @@ tower-http = { version = "0.6.8", features = ["add-extension", "cors", "trace"]
tracing = "0.1.44"
tracing-appender = "0.2.4"
tracing-opentelemetry = "0.32.1"
-tracing-subscriber = { version = "0.3.22", default-features = false, features = [
- "fmt",
- "env-filter",
- "ansi",
-] }
+tracing-subscriber = { version = "0.3.22", default-features = false, features = ["fmt", "env-filter", "ansi"] }
trait-variant = "0.1.2"
tungstenite = "0.28.0"
twox-hash = { version = "2.1.2", features = ["xxhash32"] }
@@ -286,15 +251,7 @@ uuid = { version = "1.22.0", features = ["v4", "v7", "fast-rng", "serde", "zeroc
vergen-git2 = { version = "9.1.0", features = ["build", "cargo", "rustc", "si"] }
walkdir = "2.5.0"
wasm-bindgen = "0.2"
-web-sys = { version = "0.3", features = [
- "Window",
- "Location",
- "HtmlSelectElement",
- "Clipboard",
- "Navigator",
- "ResizeObserver",
- "ResizeObserverEntry",
-] }
+web-sys = { version = "0.3", features = ["Window", "Location", "HtmlSelectElement", "Clipboard", "Navigator", "ResizeObserver", "ResizeObserverEntry"] }
webpki-roots = "1.0.6"
yew = { version = "0.22", features = ["csr"] }
yew-router = "0.19"
diff --git a/core/ai/mcp/Cargo.toml b/core/ai/mcp/Cargo.toml
index 071e8ae36..97a2d76fb 100644
--- a/core/ai/mcp/Cargo.toml
+++ b/core/ai/mcp/Cargo.toml
@@ -41,11 +41,7 @@ opentelemetry-appender-tracing = { workspace = true }
opentelemetry-otlp = { workspace = true }
opentelemetry-semantic-conventions = { workspace = true }
opentelemetry_sdk = { workspace = true, features = ["rt-tokio"] }
-rmcp = { workspace = true, features = [
- "server",
- "transport-io",
- "transport-streamable-http-server",
-] }
+rmcp = { workspace = true, features = ["server", "transport-io", "transport-streamable-http-server"] }
serde = { workspace = true }
serde_json = { workspace = true }
socket2 = { workspace = true }
diff --git a/core/configs/src/server_config/http.rs b/core/configs/src/server_config/http.rs
index b19b53cae..f3c2956f7 100644
--- a/core/configs/src/server_config/http.rs
+++ b/core/configs/src/server_config/http.rs
@@ -115,10 +115,6 @@ impl HttpJwtConfig {
}
pub fn get_decoding_key(&self) -> Result<DecodingKey, IggyError> {
- if self.decoding_secret.is_empty() {
- return Err(IggyError::InvalidJwtSecret);
- }
-
Ok(match self.get_decoding_secret() {
JwtSecret::Default(ref secret) => DecodingKey::from_secret(secret.as_ref()),
JwtSecret::Base64(ref secret) => {
@@ -128,10 +124,6 @@ impl HttpJwtConfig {
}
pub fn get_encoding_key(&self) -> Result<EncodingKey, IggyError> {
- if self.encoding_secret.is_empty() {
- return Err(IggyError::InvalidJwtSecret);
- }
-
Ok(match self.get_encoding_secret() {
JwtSecret::Default(ref secret) => EncodingKey::from_secret(secret.as_ref()),
JwtSecret::Base64(ref secret) => {
diff --git a/core/integration/Cargo.toml b/core/integration/Cargo.toml
index 9851e5be0..59c24537d 100644
--- a/core/integration/Cargo.toml
+++ b/core/integration/Cargo.toml
@@ -55,12 +55,7 @@ rcgen = { workspace = true }
reqwest = { workspace = true }
reqwest-middleware = { workspace = true }
reqwest-retry = { workspace = true }
-rmcp = { workspace = true, features = [
- "client",
- "reqwest",
- "transport-streamable-http-client",
- "transport-streamable-http-client-reqwest",
-] }
+rmcp = { workspace = true, features = ["client", "reqwest", "transport-streamable-http-client", "transport-streamable-http-client-reqwest"] }
secrecy = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
diff --git a/core/server/config.toml b/core/server/config.toml
index 03d0135f8..b3be68e58 100644
--- a/core/server/config.toml
+++ b/core/server/config.toml
@@ -114,10 +114,12 @@ clock_skew = "5 s"
not_before = "0 s"
# Secret key for encoding JWTs.
-encoding_secret = "top_secret$iggy123$_jwt_HS256_key#!"
+# If left empty, a secure random secret will be generated on each server start.
+encoding_secret = ""
# Secret key for decoding JWTs.
-decoding_secret = "top_secret$iggy123$_jwt_HS256_key#!"
+# If left empty, a secure random secret will be generated on each server start.
+decoding_secret = ""
# Indicates if the secret key is base64 encoded.
# `true` means the secret is base64 encoded.
diff --git a/core/server/src/http/http_server.rs b/core/server/src/http/http_server.rs
index 4e71f3fe1..d83e401e3 100644
--- a/core/server/src/http/http_server.rs
+++ b/core/server/src/http/http_server.rs
@@ -30,6 +30,7 @@ use crate::shard::task_registry::ShutdownToken;
use crate::shard::tasks::periodic::spawn_jwt_token_cleaner;
use crate::shard::transmission::event::ShardEvent;
use crate::streaming::persistence::persister::PersisterKind;
+use crate::streaming::utils::crypto;
use axum::extract::DefaultBodyLimit;
use axum::extract::connect_info::Connected;
use axum::http::Method;
@@ -45,7 +46,7 @@ use std::path::PathBuf;
use std::rc::Rc;
use std::sync::Arc;
use tower_http::cors::{AllowOrigin, CorsLayer};
-use tracing::{error, info};
+use tracing::{error, info, warn};
#[derive(Debug, Clone, Copy)]
pub struct CompioSocketAddr(pub SocketAddr);
@@ -268,7 +269,27 @@ async fn build_app_state(
tokens_path = shard.config.system.get_state_tokens_path();
}
- let jwt_manager = JwtManager::from_config(persister, &tokens_path, &config.jwt);
+ let mut jwt_config = config.jwt.clone();
+ let encoding_empty = jwt_config.encoding_secret.is_empty();
+ let decoding_empty = jwt_config.decoding_secret.is_empty();
+ if encoding_empty || decoding_empty {
+ let secret = crypto::generate_secret(32..64);
+ let redacted = secret.chars().take(3).collect::<String>();
+ if encoding_empty {
+ jwt_config.encoding_secret = secret.clone();
+ warn!(
+ "JWT encoding secret is not configured - generated a random secret: {redacted}***. JWT tokens will be invalidated on server restart. Set 'encoding_secret' in the config to use a persistent secret."
+ );
+ }
+ if decoding_empty {
+ jwt_config.decoding_secret = secret;
+ warn!(
+ "JWT decoding secret is not configured - generated a random secret: {redacted}***. JWT tokens will be invalidated on server restart. Set 'decoding_secret' in the config to use a persistent secret."
+ );
+ }
+ }
+
+ let jwt_manager = JwtManager::from_config(persister, &tokens_path, &jwt_config);
if let Err(e) = jwt_manager {
panic!("Failed to initialize JWT manager: {e}");
}