From 2d0fbc6585dc822ac0e72ad523dc36a0cd1d7587 Mon Sep 17 00:00:00 2001 From: 1010adigupta <1010adigupta@gmail.com> Date: Tue, 31 Oct 2023 01:25:25 +0530 Subject: [PATCH 1/6] JSON-RPC auth construction initiated --- crates/rpc/rpc-builder/src/auth.rs | 6 +-- crates/rpc/rpc-builder/src/lib.rs | 66 +++++++++++++++++++++++------- 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/crates/rpc/rpc-builder/src/auth.rs b/crates/rpc/rpc-builder/src/auth.rs index d0450ab4b42f..d427050aac90 100644 --- a/crates/rpc/rpc-builder/src/auth.rs +++ b/crates/rpc/rpc-builder/src/auth.rs @@ -127,7 +127,7 @@ where pub struct AuthServerConfig { /// Where the server should listen. pub(crate) socket_addr: SocketAddr, - /// The secrete for the auth layer of the server. + /// The secret for the auth layer of the server. pub(crate) secret: JwtSecret, /// Configs for JSON-RPC Http. pub(crate) server_config: ServerBuilder, @@ -305,8 +305,8 @@ impl AuthServerHandle { "Bearer {}", self.secret .encode(&Claims { - iat: (SystemTime::now().duration_since(UNIX_EPOCH).unwrap() + - Duration::from_secs(60)) + iat: (SystemTime::now().duration_since(UNIX_EPOCH).unwrap() + + Duration::from_secs(60)) .as_secs(), exp: None, }) diff --git a/crates/rpc/rpc-builder/src/lib.rs b/crates/rpc/rpc-builder/src/lib.rs index 581c4cbcc563..49e245c64884 100644 --- a/crates/rpc/rpc-builder/src/lib.rs +++ b/crates/rpc/rpc-builder/src/lib.rs @@ -121,9 +121,9 @@ use reth_rpc::{ cache::{cache_new_blocks_task, EthStateCache}, gas_oracle::GasPriceOracle, }, - AdminApi, DebugApi, EngineEthApi, EthApi, EthFilter, EthPubSub, EthSubscriptionIdProvider, - NetApi, OtterscanApi, RPCApi, RethApi, TraceApi, TracingCallGuard, TracingCallPool, TxPoolApi, - Web3Api, + AdminApi, AuthLayer, DebugApi, EngineEthApi, EthApi, EthFilter, EthPubSub, + EthSubscriptionIdProvider, JwtAuthValidator, JwtSecret, NetApi, OtterscanApi, RPCApi, RethApi, + TraceApi, TracingCallGuard, TracingCallPool, TxPoolApi, Web3Api, }; use reth_rpc_api::{servers::*, EngineApiServer}; use reth_tasks::{TaskSpawner, TokioTaskExecutor}; @@ -1070,7 +1070,7 @@ where /// Http and WS share the same settings: [`ServerBuilder`]. /// /// Once the [RpcModule] is built via [RpcModuleBuilder] the servers can be started, See also -/// [ServerBuilder::build] and [Server::start](jsonrpsee::server::Server::start). +/// [ServerBuilder::build] and [Server::start](jsonrpc::server::Server::start). #[derive(Default)] pub struct RpcServerConfig { /// Configs for JSON-RPC Http. @@ -1089,6 +1089,8 @@ pub struct RpcServerConfig { ipc_server_config: Option, /// The Endpoint where to launch the ipc server ipc_endpoint: Option, + /// JWT secret for authentication + jwt_secret: Option, } impl fmt::Debug for RpcServerConfig { @@ -1216,9 +1218,9 @@ impl RpcServerConfig { /// /// If no server is configured, no server will be be launched on [RpcServerConfig::start]. pub fn has_server(&self) -> bool { - self.http_server_config.is_some() || - self.ws_server_config.is_some() || - self.ipc_server_config.is_some() + self.http_server_config.is_some() + || self.ws_server_config.is_some() + || self.ipc_server_config.is_some() } /// Returns the [SocketAddr] of the http server @@ -1255,9 +1257,9 @@ impl RpcServerConfig { .unwrap_or(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, DEFAULT_WS_RPC_PORT))); let metrics = RpcServerMetrics::default(); // If both are configured on the same port, we combine them into one server. - if self.http_addr == self.ws_addr && - self.http_server_config.is_some() && - self.ws_server_config.is_some() + if self.http_addr == self.ws_addr + && self.http_server_config.is_some() + && self.ws_server_config.is_some() { let cors = match (self.ws_cors_domains.as_ref(), self.http_cors_domains.as_ref()) { (Some(ws_cors), Some(http_cors)) => { @@ -1266,7 +1268,7 @@ impl RpcServerConfig { http_cors_domains: Some(http_cors.clone()), ws_cors_domains: Some(ws_cors.clone()), } - .into()) + .into()); } Some(ws_cors) } @@ -1292,7 +1294,7 @@ impl RpcServerConfig { http_local_addr: Some(addr), ws_local_addr: Some(addr), server: WsHttpServers::SamePort(server), - }) + }); } let mut http_local_addr = None; @@ -1487,7 +1489,7 @@ impl TransportRpcModules { other: impl Into, ) -> Result { if let Some(ref mut http) = self.http { - return http.merge(other.into()).map(|_| true) + return http.merge(other.into()).map(|_| true); } Ok(false) } @@ -1502,7 +1504,7 @@ impl TransportRpcModules { other: impl Into, ) -> Result { if let Some(ref mut ws) = self.ws { - return ws.merge(other.into()).map(|_| true) + return ws.merge(other.into()).map(|_| true); } Ok(false) } @@ -1517,7 +1519,7 @@ impl TransportRpcModules { other: impl Into, ) -> Result { if let Some(ref mut ipc) = self.ipc { - return ipc.merge(other.into()).map(|_| true) + return ipc.merge(other.into()).map(|_| true); } Ok(false) } @@ -1615,6 +1617,8 @@ enum WsHttpServerKind { Plain(Server), /// Http server with cors WithCors(Server, RpcServerMetrics>), + /// Http server with auth + WithAuth(Server, Identity>, RpcServerMetrics>), } // === impl WsHttpServerKind === @@ -1625,6 +1629,7 @@ impl WsHttpServerKind { match self { WsHttpServerKind::Plain(server) => server.start(module), WsHttpServerKind::WithCors(server) => server.start(module), + WsHttpServerKind::WithAuth(server) => server.start(module), } } @@ -1633,6 +1638,7 @@ impl WsHttpServerKind { builder: ServerBuilder, socket_addr: SocketAddr, cors_domains: Option, + auth_secret: Option, server_kind: ServerKind, metrics: RpcServerMetrics, ) -> Result<(Self, SocketAddr), RpcError> { @@ -1648,6 +1654,17 @@ impl WsHttpServerKind { let local_addr = server.local_addr()?; let server = WsHttpServerKind::WithCors(server); Ok((server, local_addr)) + } + if let Some(secret) = auth_secret { + let middleware = tower::ServiceBuilder::new() + .layer(AuthLayer::new(JwtAuthValidator::new(secret.clone()))); + let server = + builder.set_middleware(middleware).build(socket_addr).await.map_err(|err| { + RpcError::from_jsonrpsee_error(err, ServerKind::Auth(socket_addr)) + })?; + let local_addr = server.local_addr()?; + let server = WsHttpServerKind::WithAuth(server); + Ok((server, local_addr)) } else { let server = builder .set_logger(metrics) @@ -1659,6 +1676,25 @@ impl WsHttpServerKind { Ok((server, local_addr)) } } + + // pub async fn start(self, module: AuthRpcModule) -> Result { + // let Self { socket_addr, secret, server_config } = self; + + // // Create auth middleware. + // let middleware = tower::ServiceBuilder::new() + // .layer(AuthLayer::new(JwtAuthValidator::new(secret.clone()))); + + // // By default, both http and ws are enabled. + // let server = + // server_config.set_middleware(middleware).build(socket_addr).await.map_err(|err| { + // RpcError::from_jsonrpsee_error(err, ServerKind::Auth(socket_addr)) + // })?; + + // let local_addr = server.local_addr()?; + + // let handle = server.start(module.inner); + // Ok(AuthServerHandle { handle, local_addr, secret }) + // } } /// Container type for each transport ie. http, ws, and ipc server From 9bccab8aed0fc1d8990c9a7a7a832283ccd7a7c3 Mon Sep 17 00:00:00 2001 From: 1010adigupta <1010adigupta@gmail.com> Date: Tue, 31 Oct 2023 13:18:42 +0530 Subject: [PATCH 2/6] JSON-RPC auth construction done, CLI args construction remmaining --- crates/rpc/rpc-builder/src/lib.rs | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/crates/rpc/rpc-builder/src/lib.rs b/crates/rpc/rpc-builder/src/lib.rs index 49e245c64884..c2cfddb90c56 100644 --- a/crates/rpc/rpc-builder/src/lib.rs +++ b/crates/rpc/rpc-builder/src/lib.rs @@ -1103,6 +1103,7 @@ impl fmt::Debug for RpcServerConfig { .field("ws_addr", &self.ws_addr) .field("ipc_server_config", &self.ipc_server_config) .field("ipc_endpoint", &self.ipc_endpoint.as_ref().map(|endpoint| endpoint.path())) + .field("jwt_secret", &self.jwt_secret) .finish() } } @@ -1214,6 +1215,12 @@ impl RpcServerConfig { self } + /// Configures the JWT secret for authentication + pub fn with_jwt_secret(mut self, secret: JwtSecret) -> Self { + self.jwt_secret = Some(secret); + self + } + /// Returns true if any server is configured. /// /// If no server is configured, no server will be be launched on [RpcServerConfig::start]. @@ -1278,6 +1285,8 @@ impl RpcServerConfig { } .cloned(); + let secret = self.jwt_secret.take(); + // we merge this into one server using the http setup self.ws_server_config.take(); @@ -1286,6 +1295,7 @@ impl RpcServerConfig { builder, http_socket_addr, cors, + secret, ServerKind::WsHttp(http_socket_addr), metrics.clone(), ) @@ -1308,6 +1318,7 @@ impl RpcServerConfig { builder, ws_socket_addr, self.ws_cors_domains.take(), + self.jwt_secret.take(), ServerKind::WS(ws_socket_addr), metrics.clone(), ) @@ -1322,6 +1333,7 @@ impl RpcServerConfig { builder, http_socket_addr, self.http_cors_domains.take(), + self.jwt_secret.take(), ServerKind::Http(http_socket_addr), metrics.clone(), ) @@ -1655,11 +1667,15 @@ impl WsHttpServerKind { let server = WsHttpServerKind::WithCors(server); Ok((server, local_addr)) } - if let Some(secret) = auth_secret { + else if let Some(secret) = auth_secret { let middleware = tower::ServiceBuilder::new() .layer(AuthLayer::new(JwtAuthValidator::new(secret.clone()))); - let server = - builder.set_middleware(middleware).build(socket_addr).await.map_err(|err| { + let server = builder + .set_middleware(middleware) + .set_logger(metrics) + .build(socket_addr) + .await + .map_err(|err| { RpcError::from_jsonrpsee_error(err, ServerKind::Auth(socket_addr)) })?; let local_addr = server.local_addr()?; From 98d4fe805907352a8b7450e7d3b57b7e13715be9 Mon Sep 17 00:00:00 2001 From: 1010adigupta <1010adigupta@gmail.com> Date: Tue, 31 Oct 2023 13:20:57 +0530 Subject: [PATCH 3/6] Basic formating Basic formating Basic formating --- crates/rpc/rpc-builder/src/auth.rs | 4 +-- crates/rpc/rpc-builder/src/lib.rs | 44 ++++++++---------------------- 2 files changed, 14 insertions(+), 34 deletions(-) diff --git a/crates/rpc/rpc-builder/src/auth.rs b/crates/rpc/rpc-builder/src/auth.rs index d427050aac90..6377cb5972a8 100644 --- a/crates/rpc/rpc-builder/src/auth.rs +++ b/crates/rpc/rpc-builder/src/auth.rs @@ -305,8 +305,8 @@ impl AuthServerHandle { "Bearer {}", self.secret .encode(&Claims { - iat: (SystemTime::now().duration_since(UNIX_EPOCH).unwrap() - + Duration::from_secs(60)) + iat: (SystemTime::now().duration_since(UNIX_EPOCH).unwrap() + + Duration::from_secs(60)) .as_secs(), exp: None, }) diff --git a/crates/rpc/rpc-builder/src/lib.rs b/crates/rpc/rpc-builder/src/lib.rs index c2cfddb90c56..ffe10f6a12cd 100644 --- a/crates/rpc/rpc-builder/src/lib.rs +++ b/crates/rpc/rpc-builder/src/lib.rs @@ -1225,9 +1225,9 @@ impl RpcServerConfig { /// /// If no server is configured, no server will be be launched on [RpcServerConfig::start]. pub fn has_server(&self) -> bool { - self.http_server_config.is_some() - || self.ws_server_config.is_some() - || self.ipc_server_config.is_some() + self.http_server_config.is_some() || + self.ws_server_config.is_some() || + self.ipc_server_config.is_some() } /// Returns the [SocketAddr] of the http server @@ -1264,9 +1264,9 @@ impl RpcServerConfig { .unwrap_or(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, DEFAULT_WS_RPC_PORT))); let metrics = RpcServerMetrics::default(); // If both are configured on the same port, we combine them into one server. - if self.http_addr == self.ws_addr - && self.http_server_config.is_some() - && self.ws_server_config.is_some() + if self.http_addr == self.ws_addr && + self.http_server_config.is_some() && + self.ws_server_config.is_some() { let cors = match (self.ws_cors_domains.as_ref(), self.http_cors_domains.as_ref()) { (Some(ws_cors), Some(http_cors)) => { @@ -1275,7 +1275,7 @@ impl RpcServerConfig { http_cors_domains: Some(http_cors.clone()), ws_cors_domains: Some(ws_cors.clone()), } - .into()); + .into()) } Some(ws_cors) } @@ -1304,7 +1304,7 @@ impl RpcServerConfig { http_local_addr: Some(addr), ws_local_addr: Some(addr), server: WsHttpServers::SamePort(server), - }); + }) } let mut http_local_addr = None; @@ -1501,7 +1501,7 @@ impl TransportRpcModules { other: impl Into, ) -> Result { if let Some(ref mut http) = self.http { - return http.merge(other.into()).map(|_| true); + return http.merge(other.into()).map(|_| true) } Ok(false) } @@ -1516,7 +1516,7 @@ impl TransportRpcModules { other: impl Into, ) -> Result { if let Some(ref mut ws) = self.ws { - return ws.merge(other.into()).map(|_| true); + return ws.merge(other.into()).map(|_| true) } Ok(false) } @@ -1531,7 +1531,7 @@ impl TransportRpcModules { other: impl Into, ) -> Result { if let Some(ref mut ipc) = self.ipc { - return ipc.merge(other.into()).map(|_| true); + return ipc.merge(other.into()).map(|_| true) } Ok(false) } @@ -1666,8 +1666,7 @@ impl WsHttpServerKind { let local_addr = server.local_addr()?; let server = WsHttpServerKind::WithCors(server); Ok((server, local_addr)) - } - else if let Some(secret) = auth_secret { + } else if let Some(secret) = auth_secret { let middleware = tower::ServiceBuilder::new() .layer(AuthLayer::new(JwtAuthValidator::new(secret.clone()))); let server = builder @@ -1692,25 +1691,6 @@ impl WsHttpServerKind { Ok((server, local_addr)) } } - - // pub async fn start(self, module: AuthRpcModule) -> Result { - // let Self { socket_addr, secret, server_config } = self; - - // // Create auth middleware. - // let middleware = tower::ServiceBuilder::new() - // .layer(AuthLayer::new(JwtAuthValidator::new(secret.clone()))); - - // // By default, both http and ws are enabled. - // let server = - // server_config.set_middleware(middleware).build(socket_addr).await.map_err(|err| { - // RpcError::from_jsonrpsee_error(err, ServerKind::Auth(socket_addr)) - // })?; - - // let local_addr = server.local_addr()?; - - // let handle = server.start(module.inner); - // Ok(AuthServerHandle { handle, local_addr, secret }) - // } } /// Container type for each transport ie. http, ws, and ipc server From 8c09936455b77c6c4414be789d43c058a3f61703 Mon Sep 17 00:00:00 2001 From: 1010adigupta <1010adigupta@gmail.com> Date: Wed, 1 Nov 2023 22:58:38 +0530 Subject: [PATCH 4/6] package import correction --- crates/rpc/rpc-builder/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/rpc/rpc-builder/src/lib.rs b/crates/rpc/rpc-builder/src/lib.rs index ffe10f6a12cd..d7dac01ec576 100644 --- a/crates/rpc/rpc-builder/src/lib.rs +++ b/crates/rpc/rpc-builder/src/lib.rs @@ -1070,7 +1070,7 @@ where /// Http and WS share the same settings: [`ServerBuilder`]. /// /// Once the [RpcModule] is built via [RpcModuleBuilder] the servers can be started, See also -/// [ServerBuilder::build] and [Server::start](jsonrpc::server::Server::start). +/// [ServerBuilder::build] and [Server::start](jsonrpsee::server::Server::start). #[derive(Default)] pub struct RpcServerConfig { /// Configs for JSON-RPC Http. From afa6a6748f8499b203cac5e90d4b7e993df8c503 Mon Sep 17 00:00:00 2001 From: 1010adigupta <1010adigupta@gmail.com> Date: Thu, 2 Nov 2023 18:37:53 +0530 Subject: [PATCH 5/6] authentication for cors layer added --- crates/rpc/rpc-builder/src/lib.rs | 42 +++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/crates/rpc/rpc-builder/src/lib.rs b/crates/rpc/rpc-builder/src/lib.rs index d7dac01ec576..ad769bbe35de 100644 --- a/crates/rpc/rpc-builder/src/lib.rs +++ b/crates/rpc/rpc-builder/src/lib.rs @@ -106,6 +106,7 @@ use crate::{auth::AuthRpcModule, error::WsHttpSamePortError, metrics::RpcServerMetrics}; use constants::*; use error::{RpcError, ServerKind}; +use hyper::server; use jsonrpsee::{ server::{IdProvider, Server, ServerHandle}, Methods, RpcModule, @@ -1631,6 +1632,10 @@ enum WsHttpServerKind { WithCors(Server, RpcServerMetrics>), /// Http server with auth WithAuth(Server, Identity>, RpcServerMetrics>), + /// Http server with cors and auth + WithCorsAuth( + Server, Stack>, RpcServerMetrics>, + ), } // === impl WsHttpServerKind === @@ -1642,6 +1647,7 @@ impl WsHttpServerKind { WsHttpServerKind::Plain(server) => server.start(module), WsHttpServerKind::WithCors(server) => server.start(module), WsHttpServerKind::WithAuth(server) => server.start(module), + WsHttpServerKind::WithCorsAuth(server) => server.start(module), } } @@ -1656,16 +1662,32 @@ impl WsHttpServerKind { ) -> Result<(Self, SocketAddr), RpcError> { if let Some(cors) = cors_domains.as_deref().map(cors::create_cors_layer) { let cors = cors.map_err(|err| RpcError::Custom(err.to_string()))?; - let middleware = tower::ServiceBuilder::new().layer(cors); - let server = builder - .set_middleware(middleware) - .set_logger(metrics) - .build(socket_addr) - .await - .map_err(|err| RpcError::from_jsonrpsee_error(err, server_kind))?; - let local_addr = server.local_addr()?; - let server = WsHttpServerKind::WithCors(server); - Ok((server, local_addr)) + if let Some(secret) = auth_secret { + let middleware = tower::ServiceBuilder::new() + .layer(cors) + .layer(AuthLayer::new(JwtAuthValidator::new(secret.clone()))); + + let server = builder + .set_middleware(middleware) + .set_logger(metrics) + .build(socket_addr) + .await + .map_err(|err| RpcError::from_jsonrpsee_error(err, server_kind))?; + let local_addr = server.local_addr()?; + let server = WsHttpServerKind::WithCorsAuth(server); + Ok((server, local_addr)) + } else { + let middleware = tower::ServiceBuilder::new().layer(cors); + let server = builder + .set_middleware(middleware) + .set_logger(metrics) + .build(socket_addr) + .await + .map_err(|err| RpcError::from_jsonrpsee_error(err, server_kind))?; + let local_addr = server.local_addr()?; + let server = WsHttpServerKind::WithCors(server); + Ok((server, local_addr)) + } } else if let Some(secret) = auth_secret { let middleware = tower::ServiceBuilder::new() .layer(AuthLayer::new(JwtAuthValidator::new(secret.clone()))); From ad7fc5f8b3bc815c1fa25f9014f8ce9061303e0e Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Thu, 2 Nov 2023 14:25:54 +0100 Subject: [PATCH 6/6] touchups --- crates/rpc/rpc-builder/src/lib.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/crates/rpc/rpc-builder/src/lib.rs b/crates/rpc/rpc-builder/src/lib.rs index b1436a92c621..ada2b22910ef 100644 --- a/crates/rpc/rpc-builder/src/lib.rs +++ b/crates/rpc/rpc-builder/src/lib.rs @@ -102,7 +102,6 @@ use crate::{auth::AuthRpcModule, error::WsHttpSamePortError, metrics::RpcServerMetrics}; use constants::*; use error::{RpcError, ServerKind}; -use hyper::server; use jsonrpsee::{ server::{IdProvider, Server, ServerHandle}, Methods, RpcModule, @@ -119,8 +118,8 @@ use reth_rpc::{ gas_oracle::GasPriceOracle, }, AdminApi, AuthLayer, BlockingTaskGuard, BlockingTaskPool, DebugApi, EngineEthApi, EthApi, - EthFilter, EthPubSub, EthSubscriptionIdProvider, JwtAuthValidator, NetApi, OtterscanApi, - RPCApi, RethApi, TraceApi, TxPoolApi, Web3Api, + EthFilter, EthPubSub, EthSubscriptionIdProvider, JwtAuthValidator, JwtSecret, NetApi, + OtterscanApi, RPCApi, RethApi, TraceApi, TxPoolApi, Web3Api, }; use reth_rpc_api::{servers::*, EngineApiServer}; use reth_tasks::{TaskSpawner, TokioTaskExecutor}; @@ -1703,7 +1702,9 @@ impl WsHttpServerKind { } } - /// Builds + /// Builds the server according to the given config parameters. + /// + /// Returns the address of the started server. async fn build( builder: ServerBuilder, socket_addr: SocketAddr, @@ -1714,7 +1715,9 @@ impl WsHttpServerKind { ) -> Result<(Self, SocketAddr), RpcError> { if let Some(cors) = cors_domains.as_deref().map(cors::create_cors_layer) { let cors = cors.map_err(|err| RpcError::Custom(err.to_string()))?; + if let Some(secret) = auth_secret { + // stack cors and auth layers let middleware = tower::ServiceBuilder::new() .layer(cors) .layer(AuthLayer::new(JwtAuthValidator::new(secret.clone()))); @@ -1741,6 +1744,7 @@ impl WsHttpServerKind { Ok((server, local_addr)) } } else if let Some(secret) = auth_secret { + // jwt auth layered service let middleware = tower::ServiceBuilder::new() .layer(AuthLayer::new(JwtAuthValidator::new(secret.clone()))); let server = builder @@ -1755,6 +1759,7 @@ impl WsHttpServerKind { let server = WsHttpServerKind::WithAuth(server); Ok((server, local_addr)) } else { + // plain server without any middleware let server = builder .set_logger(metrics) .build(socket_addr)