From 2f55a92b3b176ed548df38a149aee35a523b1da5 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Thu, 10 Oct 2024 12:28:35 +0200 Subject: [PATCH] chore(sidecar): jwt validation in opts --- bolt-sidecar/src/config/mod.rs | 156 ----------------------------- bolt-sidecar/src/config/signing.rs | 33 +++++- 2 files changed, 31 insertions(+), 158 deletions(-) diff --git a/bolt-sidecar/src/config/mod.rs b/bolt-sidecar/src/config/mod.rs index 3dac1c5e4..edc5111d7 100644 --- a/bolt-sidecar/src/config/mod.rs +++ b/bolt-sidecar/src/config/mod.rs @@ -92,162 +92,6 @@ pub struct Opts { pub telemetry: TelemetryOpts, } -/// /// Configuration options for the sidecar. These are parsed from -/// /// command-line options in the form of [`Opts`]. -/// #[derive(Debug, Clone)] -/// pub struct Config { -/// /// Port to listen on for incoming JSON-RPC requests -/// pub rpc_port: u16, -/// /// The Constraints client proxy server port to listen on -/// pub constraints_proxy_port: u16, -/// /// URL for the Constraints sidecar client to use -/// pub constraints_url: Url, -/// /// URL for the beacon client API URL -/// pub beacon_api_url: Url, -/// /// The execution API url -/// pub execution_api_url: Url, -/// /// The engine API url -/// pub engine_api_url: Url, -/// /// URL for the commit-boost sidecar -/// pub commit_boost_url: Option, -/// /// The JWT secret token to authenticate calls to the commit-boost -/// pub commit_boost_jwt_hex: Option, -/// /// Private key to use for signing preconfirmation requests -/// pub private_key: Option, -/// /// The jwt.hex secret to authenticate calls to the engine API -/// pub jwt_hex: String, -/// /// The fee recipient address for fallback blocks -/// pub fee_recipient: Address, -/// /// Operating limits for the sidecar -/// pub limits: Limits, -/// /// Validator indexes of connected validators that the -/// /// sidecar should accept commitments on behalf of -/// pub validator_indexes: ValidatorIndexes, -/// /// Local bulider private key for signing fallback payloads. -/// /// If not provided, a random key will be used. -/// pub builder_private_key: SecretKey, -/// /// The chain on which the sidecar is running -/// pub chain: ChainConfig, -/// /// Metrics port -/// pub metrics_port: u16, -/// /// Toggle for metrics -/// pub disable_metrics: bool, -/// } -/// -/// impl Default for Config { -/// fn default() -> Self { -/// Self { -/// rpc_port: DEFAULT_RPC_PORT, -/// constraints_proxy_port: DEFAULT_CONSTRAINTS_PROXY_PORT, -/// commit_boost_url: None, -/// commit_boost_jwt_hex: None, -/// constraints_url: "http://localhost:3030".parse().expect("Valid URL"), -/// beacon_api_url: "http://localhost:5052".parse().expect("Valid URL"), -/// execution_api_url: "http://localhost:8545".parse().expect("Valid URL"), -/// engine_api_url: "http://localhost:8551".parse().expect("Valid URL"), -/// private_key: Some(random_bls_secret()), -/// jwt_hex: String::new(), -/// fee_recipient: Address::ZERO, -/// builder_private_key: random_bls_secret(), -/// limits: Limits::default(), -/// validator_indexes: ValidatorIndexes::default(), -/// chain: ChainConfig::default(), -/// metrics_port: 0, -/// disable_metrics: false, -/// } -/// } -/// } - -// impl Config { -// /// Parse the command-line options and return a new [`Config`] instance -// pub fn parse_from_cli() -> Result { -// let opts = Opts::parse(); -// Self::try_from(opts) -// } -// } -// -// impl Opts { -// type Error = Report; -// -// fn validate(&self) -> Result { -// let mut config = Config::default(); -// -// if let Some(port) = opts.port { -// config.rpc_port = port; -// } -// -// if let Some(max_commitments) = opts.max_commitments { -// config.limits.max_commitments_per_slot = max_commitments; -// } -// -// if let Some(max_committed_gas) = opts.max_committed_gas { -// config.limits.max_committed_gas_per_slot = max_committed_gas; -// } -// -// if let Some(min_priority_fee) = opts.min_priority_fee { -// config.limits.min_priority_fee = min_priority_fee; -// } -// -// if let Some(commit_boost_url) = &opts.signing.commit_boost_url { -// if let Ok(url) = Url::parse(commit_boost_url) { -// if let Ok(socket_addrs) = url.socket_addrs(|| None) { -// config.commit_boost_url = Some(socket_addrs[0].to_string()); -// } -// } -// } -// -// if let Some(sk) = self.signing.private_key { -// let hex_sk = sk.strip_prefix("0x").unwrap_or(&sk); -// let sk = SecretKey::from_bytes(&hex::decode(hex_sk)?) -// .map_err(|e| eyre!("Failed decoding BLS signer secret key: {:?}", e))?; -// Some(sk) -// } else { -// None -// }; -// -// if let Some(builder_sk) = opts.builder_private_key { -// let hex_sk = builder_sk.strip_prefix("0x").unwrap_or(&builder_sk); -// let sk = SecretKey::from_bytes(&hex::decode(hex_sk)?) -// .map_err(|e| eyre!("Failed decoding BLS builder secret key: {:?}", e))?; -// config.builder_private_key = sk; -// } -// -// config.jwt_hex = if opts.jwt_hex.starts_with("0x") { -// opts.jwt_hex.trim_start_matches("0x").to_string() -// } else if Path::new(&opts.jwt_hex).exists() { -// read_to_string(opts.jwt_hex) -// .map_err(|e| eyre!("Failed reading JWT secret file: {:?}", e))? -// .trim_start_matches("0x") -// .to_string() -// } else { -// opts.jwt_hex -// }; -// -// // Validate the JWT secret -// if config.jwt_hex.len() != 64 { -// bail!("Engine JWT secret must be a 32 byte hex string"); -// } else { -// info!("Engine JWT secret loaded successfully"); -// } -// -// config.constraints_proxy_port = opts.constraints_proxy_port; -// config.engine_api_url = opts.engine_api_url.parse()?; -// config.execution_api_url = opts.execution_api_url.parse()?; -// config.beacon_api_url = opts.beacon_api_url.parse()?; -// config.constraints_url = opts.constraints_url.parse()?; -// -// config.fee_recipient = opts.fee_recipient; -// -// config.validator_indexes = opts.validator_indexes; -// -// config.chain = opts.chain; -// config.metrics_port = opts.telemetry.metrics_port; -// config.disable_metrics = opts.telemetry.disable_metrics; -// -// Ok(config) -// } -// } - #[cfg(test)] mod tests { use super::*; diff --git a/bolt-sidecar/src/config/signing.rs b/bolt-sidecar/src/config/signing.rs index 810dc9fa7..708771904 100644 --- a/bolt-sidecar/src/config/signing.rs +++ b/bolt-sidecar/src/config/signing.rs @@ -1,4 +1,4 @@ -use std::{fmt, net::SocketAddr, ops::Deref}; +use std::{fmt, fs::read_to_string, net::SocketAddr, ops::Deref, path::Path}; use blst::min_pk::SecretKey; use clap::{ArgGroup, Args}; @@ -30,7 +30,7 @@ pub struct SigningOpts { group = "signing-opts", requires("commit_boost_url") )] - pub commit_boost_jwt_hex: Option, + pub commit_boost_jwt_hex: Option, /// The password for the ERC-2335 keystore. /// Reference: https://eips.ethereum.org/EIPS/eip-2335 #[clap(long, env = "BOLT_SIDECAR_KEYSTORE_PASSWORD", group = "signing-opts")] @@ -92,3 +92,32 @@ impl fmt::Display for BlsSecretKey { write!(f, "0x{}", hex::encode(self.0.to_bytes())) } } + +#[derive(Debug, Clone)] +pub struct JwtSecretConfig(pub String); + +impl From<&str> for JwtSecretConfig { + fn from(jwt: &str) -> Self { + let jwt = if jwt.starts_with("0x") { + jwt.trim_start_matches("0x").to_string() + } else if Path::new(&jwt).exists() { + read_to_string(jwt) + .unwrap_or_else(|_| panic!("Failed reading JWT secret file: {:?}", jwt)) + .trim_start_matches("0x") + .to_string() + } else { + jwt.to_string() + }; + + assert!(jwt.len() == 64, "Engine JWT secret must be a 32 byte hex string"); + + Self(jwt) + } +} + +impl Deref for JwtSecretConfig { + type Target = str; + fn deref(&self) -> &Self::Target { + &self.0 + } +}