feat: JWT secret lifecycle (#1209)

Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>
This commit is contained in:
Andrea Simeoni
2023-02-11 06:50:59 +01:00
committed by GitHub
parent 3d0864bbb9
commit df6ff63806
8 changed files with 165 additions and 7 deletions

View File

@ -20,7 +20,7 @@ reth-consensus = { path = "../../crates/consensus" }
reth-executor = { path = "../../crates/executor" }
reth-eth-wire = { path = "../../crates/net/eth-wire" }
reth-rpc-builder = { path = "../../crates/rpc/rpc-builder" }
# reth-rpc = {path = "../../crates/rpc/rpc"}
reth-rpc = { path = "../../crates/rpc/rpc" }
reth-rlp = { path = "../../crates/rlp" }
reth-network = {path = "../../crates/net/network", features = ["serde"] }
reth-network-api = {path = "../../crates/net/network-api" }
@ -60,4 +60,4 @@ tempfile = { version = "3.3.0" }
backon = "0.2.0"
comfy-table = "6.1.4"
crossterm = "0.25.0"
tui = "0.19.0"
tui = "0.19.0"

View File

@ -1,8 +1,10 @@
//! clap [Args](clap::Args) for RPC related arguments.
use crate::dirs::{JwtSecretPath, PlatformPath};
use clap::Args;
use reth_rpc::{JwtError, JwtSecret};
use reth_rpc_builder::RpcModuleConfig;
use std::net::IpAddr;
use std::{net::IpAddr, path::Path};
/// Parameters for configuring the rpc more granularity via CLI
#[derive(Debug, Args, PartialEq, Default)]
@ -47,6 +49,35 @@ pub struct RpcServerArgs {
/// Filename for IPC socket/pipe within the datadir
#[arg(long)]
pub ipcpath: Option<String>,
/// Path to a JWT secret to use for authenticated RPC endpoints
#[arg(long = "authrpc.jwtsecret", value_name = "PATH", global = true, required = false)]
authrpc_jwtsecret: Option<PlatformPath<JwtSecretPath>>,
}
impl RpcServerArgs {
/// The execution layer and consensus layer clients SHOULD accept a configuration parameter:
/// jwt-secret, which designates a file containing the hex-encoded 256 bit secret key to be used
/// for verifying/generating JWT tokens.
///
/// If such a parameter is given, but the file cannot be read, or does not contain a hex-encoded
/// key of 256 bits, the client SHOULD treat this as an error.
///
/// If such a parameter is not given, the client SHOULD generate such a token, valid for the
/// duration of the execution, and SHOULD store the hex-encoded secret as a jwt.hex file on
/// the filesystem. This file can then be used to provision the counterpart client.
pub(crate) fn jwt_secret(&self) -> Result<JwtSecret, JwtError> {
let arg = self.authrpc_jwtsecret.as_ref();
let path: Option<&Path> = arg.map(|p| p.as_ref());
match path {
Some(fpath) => JwtSecret::from_file(fpath),
None => {
let default_path = PlatformPath::<JwtSecretPath>::default();
let fpath = default_path.as_ref();
JwtSecret::try_create(fpath)
}
}
}
}
#[cfg(test)]

View File

@ -1,4 +1,6 @@
//! CLI definition and entrypoint to executable
use std::str::FromStr;
use crate::{
chain, db,
dirs::{LogsDir, PlatformPath},
@ -10,7 +12,6 @@ use reth_tracing::{
tracing_subscriber::{filter::Directive, registry::LookupSpan},
BoxedLayer, FileWorkerGuard,
};
use std::str::FromStr;
/// Parse CLI options, set up logging and run the chosen command.
pub async fn run() -> eyre::Result<()> {

View File

@ -42,6 +42,13 @@ pub fn logs_dir() -> Option<PathBuf> {
cache_dir().map(|root| root.join("logs"))
}
/// Returns the path to the reth jwtsecret directory.
///
/// Refer to [dirs_next::cache_dir] for cross-platform behavior.
pub fn jwt_secret_dir() -> Option<PathBuf> {
data_dir().map(|root| root.join("jwtsecret"))
}
/// Returns the path to the reth database.
///
/// Refer to [dirs_next::data_dir] for cross-platform behavior.
@ -55,6 +62,19 @@ impl XdgPath for DbPath {
}
}
/// Returns the path to the default JWT secret hex file.
///
/// Refer to [dirs_next::data_dir] for cross-platform behavior.
#[derive(Default, Debug, Clone, PartialEq)]
#[non_exhaustive]
pub struct JwtSecretPath;
impl XdgPath for JwtSecretPath {
fn resolve() -> Option<PathBuf> {
jwt_secret_dir().map(|p| p.join("jwt.hex"))
}
}
/// Returns the path to the default reth configuration file.
///
/// Refer to [dirs_next::config_dir] for cross-platform behavior.
@ -119,7 +139,7 @@ trait XdgPath {
///
/// assert_ne!(default.as_ref(), custom.as_ref());
/// ```
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq)]
pub struct PlatformPath<D>(PathBuf, std::marker::PhantomData<D>);
impl<D> Display for PlatformPath<D> {

View File

@ -4,6 +4,7 @@
no_crate_inject,
attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables))
))]
//! Rust Ethereum (reth) binary executable.
pub mod args;

View File

@ -135,6 +135,10 @@ impl Command {
info!(target: "reth::cli", peer_id = %network.peer_id(), local_addr = %network.local_addr(), "Connected to P2P network");
// TODO: Use the resolved secret to spawn the Engine API server
// Look at `reth_rpc::AuthLayer` for integration hints
let _secret = self.rpc.jwt_secret();
// TODO(mattsse): cleanup, add cli args
let _rpc_server = reth_rpc_builder::launch(
ShareableDatabase::new(db.clone()),