Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions crates/common/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,25 @@ fn main() {

// Merge base TOML with environment variable overrides and write output.
// Panics if admin endpoints are not covered by a handler.
// Note: placeholder secret rejection is intentionally NOT done here.
// The base trusted-server.toml ships with placeholder secrets that
// production deployments override via TRUSTED_SERVER__* env vars at
// build time. Runtime startup (get_settings) rejects any remaining
// placeholders so a misconfigured deployment fails fast.
let settings = settings::Settings::from_toml_and_env(&toml_content)
.expect("Failed to parse settings at build time");

// Reject placeholder secrets in release builds so a misconfigured
// production deployment fails at compile time rather than at runtime.
// Debug builds (cargo test, cargo build) allow placeholders so that
// the base trusted-server.toml works without env var overrides.
//
// The runtime code uses `cfg(not(debug_assertions))` for the same
// purpose; both align under standard debug/release profiles.
let profile = std::env::var("PROFILE").expect("should have PROFILE set by Cargo");
if profile == "release" {
settings.reject_placeholder_secrets().expect(
"Release build must not contain placeholder secrets. \
Override them with TRUSTED_SERVER__PUBLISHER__PROXY_SECRET \
and TRUSTED_SERVER__SYNTHETIC__SECRET_KEY environment variables.",
);
}

let merged_toml =
toml::to_string_pretty(&settings).expect("Failed to serialize settings to TOML");

Expand Down
5 changes: 3 additions & 2 deletions crates/common/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,9 @@ impl Synthetic {
///
/// Placeholder detection is intentionally **not** performed here because
/// this validator runs at build time (via `from_toml_and_env`) when the
/// config legitimately contains placeholder values. Placeholder rejection
/// happens at runtime via [`Settings::reject_placeholder_secrets`].
/// config may legitimately contain placeholder values (e.g. debug builds).
/// Placeholder rejection happens in release builds at both compile time
/// (`build.rs`) and runtime ([`Settings::reject_placeholder_secrets`]).
///
/// # Errors
///
Expand Down
24 changes: 11 additions & 13 deletions crates/common/src/settings_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ pub fn get_settings() -> Result<Settings, Report<TrustedServerError>> {
message: "Failed to validate configuration".to_string(),
})?;

// Reject known placeholder values for secrets that feed into cryptographic operations.
// Reject known placeholder values for secrets that feed into cryptographic
// operations. Release builds also enforce this at compile time (build.rs),
// so this is a runtime safety net. Debug builds skip the check so the
// default trusted-server.toml works without env var overrides.
#[cfg(not(debug_assertions))]
settings.reject_placeholder_secrets()?;

if !settings.proxy.certificate_check {
Expand Down Expand Up @@ -140,18 +144,12 @@ mod tests {
}

/// Smoke-test the full `get_settings()` pipeline (embedded bytes → UTF-8 →
/// parse → validate → placeholder check). The build-time TOML ships with
/// placeholder secrets, so the expected outcome is an [`InsecureDefault`]
/// error — but reaching that error proves every earlier stage succeeded.
/// parse → validate). Debug builds skip the placeholder-secret check so
/// the default `trusted-server.toml` works without env var overrides.
/// Release builds enforce placeholders at both compile time (`build.rs`)
/// and runtime, but tests run in debug mode.
#[test]
fn get_settings_rejects_embedded_placeholder_secrets() {
let err = super::get_settings().expect_err("should reject embedded placeholder secrets");
assert!(
matches!(
err.current_context(),
TrustedServerError::InsecureDefault { .. }
),
"should fail with InsecureDefault, got: {err}"
);
fn get_settings_allows_placeholders_in_debug_builds() {
super::get_settings().expect("debug builds should allow placeholder secrets");
}
}
Loading