diff --git a/zebra-node-services/Cargo.toml b/zebra-node-services/Cargo.toml index 9042d3e5cfc..cc0a33033f0 100644 --- a/zebra-node-services/Cargo.toml +++ b/zebra-node-services/Cargo.toml @@ -27,7 +27,6 @@ getblocktemplate-rpcs = [ # Tool and test features rpc-client = [ - "base64", "color-eyre", "jsonrpc-core", "reqwest", @@ -43,7 +42,6 @@ zebra-chain = { path = "../zebra-chain" , version = "1.0.0-beta.39" } # Optional dependencies # Tool and test feature rpc-client -base64 = { version = "0.22.1", optional = true } color-eyre = { version = "0.6.3", optional = true } jsonrpc-core = { version = "18.0.0", optional = true } # Security: avoid default dependency on openssl diff --git a/zebra-node-services/src/rpc_client.rs b/zebra-node-services/src/rpc_client.rs index 61c14b72c96..7f5ffbf192e 100644 --- a/zebra-node-services/src/rpc_client.rs +++ b/zebra-node-services/src/rpc_client.rs @@ -4,7 +4,6 @@ use std::net::SocketAddr; -use base64::{engine::general_purpose::URL_SAFE, Engine as _}; use reqwest::Client; use crate::BoxError; @@ -14,16 +13,14 @@ use crate::BoxError; pub struct RpcRequestClient { client: Client, rpc_address: SocketAddr, - auth_cookie: String, } impl RpcRequestClient { /// Creates new RPCRequestSender - pub fn new(rpc_address: SocketAddr, auth_cookie: String) -> Self { + pub fn new(rpc_address: SocketAddr) -> Self { Self { client: Client::new(), rpc_address, - auth_cookie, } } @@ -42,13 +39,6 @@ impl RpcRequestClient { r#"{{"jsonrpc": "2.0", "method": "{method}", "params": {params}, "id":123 }}"# )) .header("Content-Type", "application/json") - .header( - "Authorization", - format!( - "Basic {}", - URL_SAFE.encode(format!("__cookie__:{}", &self.auth_cookie)) - ), - ) .send() .await } diff --git a/zebra-rpc/src/config.rs b/zebra-rpc/src/config.rs index ee26f679de3..cd851211529 100644 --- a/zebra-rpc/src/config.rs +++ b/zebra-rpc/src/config.rs @@ -76,6 +76,9 @@ pub struct Config { /// The directory where Zebra stores RPC cookies. pub cookie_dir: PathBuf, + + /// Enable cookie-based authentication for RPCs. + pub enable_cookie_auth: bool, } // This impl isn't derivable because it depends on features. @@ -100,8 +103,11 @@ impl Default for Config { // Debug options are always off by default. debug_force_finished_sync: false, - // + // Use the default cache dir for cookies. cookie_dir: default_cache_dir(), + + // Enable cookie-based authentication by default. + enable_cookie_auth: true, } } } diff --git a/zebra-rpc/src/server/http_request_compatibility.rs b/zebra-rpc/src/server/http_request_compatibility.rs index ac09e72e443..f2780938393 100644 --- a/zebra-rpc/src/server/http_request_compatibility.rs +++ b/zebra-rpc/src/server/http_request_compatibility.rs @@ -176,6 +176,9 @@ impl FixHttpRequestMiddleware { /// Check if the request is authenticated. pub fn check_credentials(&self, headers: &header::HeaderMap) -> bool { + if !self.0.enable_cookie_auth { + return true; + } headers .get(header::AUTHORIZATION) .and_then(|auth_header| auth_header.to_str().ok()) diff --git a/zebra-rpc/src/server/tests/vectors.rs b/zebra-rpc/src/server/tests/vectors.rs index ae670108f8d..8ffc3386a0d 100644 --- a/zebra-rpc/src/server/tests/vectors.rs +++ b/zebra-rpc/src/server/tests/vectors.rs @@ -47,6 +47,7 @@ fn rpc_server_spawn(parallel_cpu_threads: bool) { parallel_cpu_threads: if parallel_cpu_threads { 2 } else { 1 }, debug_force_finished_sync: false, cookie_dir: Default::default(), + enable_cookie_auth: false, }; let rt = tokio::runtime::Runtime::new().unwrap(); @@ -136,6 +137,7 @@ fn rpc_server_spawn_unallocated_port(parallel_cpu_threads: bool, do_shutdown: bo parallel_cpu_threads: if parallel_cpu_threads { 0 } else { 1 }, debug_force_finished_sync: false, cookie_dir: Default::default(), + enable_cookie_auth: false, }; let rt = tokio::runtime::Runtime::new().unwrap(); @@ -218,6 +220,7 @@ fn rpc_server_spawn_port_conflict() { parallel_cpu_threads: 1, debug_force_finished_sync: false, cookie_dir: Default::default(), + enable_cookie_auth: false, }; let rt = tokio::runtime::Runtime::new().unwrap(); @@ -330,6 +333,7 @@ fn rpc_server_spawn_port_conflict_parallel_auto() { parallel_cpu_threads: 2, debug_force_finished_sync: false, cookie_dir: Default::default(), + enable_cookie_auth: false, }; let rt = tokio::runtime::Runtime::new().unwrap(); diff --git a/zebra-rpc/src/sync.rs b/zebra-rpc/src/sync.rs index 0e3349b15bc..475177cc1d4 100644 --- a/zebra-rpc/src/sync.rs +++ b/zebra-rpc/src/sync.rs @@ -57,10 +57,8 @@ impl TrustedChainSync { rpc_address: SocketAddr, db: ZebraDb, non_finalized_state_sender: tokio::sync::watch::Sender, - cookie_dir: std::path::PathBuf, ) -> (LatestChainTip, ChainTipChange, JoinHandle<()>) { - let auth_cookie = crate::server::cookie::get(cookie_dir).expect("cookie should exist"); - let rpc_client = RpcRequestClient::new(rpc_address, auth_cookie); + let rpc_client = RpcRequestClient::new(rpc_address); let non_finalized_state = NonFinalizedState::new(&db.network()); let (chain_tip_sender, latest_chain_tip, chain_tip_change) = ChainTipSender::new(None, &db.network()); @@ -318,7 +316,6 @@ impl TrustedChainSync { /// a [`JoinHandle`] for the sync task. pub fn init_read_state_with_syncer( state_config: zebra_state::Config, - rpc_config: crate::config::Config, network: &Network, rpc_address: SocketAddr, ) -> tokio::task::JoinHandle< @@ -340,13 +337,8 @@ pub fn init_read_state_with_syncer( let (read_state, db, non_finalized_state_sender) = spawn_init_read_only(state_config, &network).await?; - let (latest_chain_tip, chain_tip_change, sync_task) = TrustedChainSync::spawn( - rpc_address, - db, - non_finalized_state_sender, - rpc_config.cookie_dir, - ) - .await; + let (latest_chain_tip, chain_tip_change, sync_task) = + TrustedChainSync::spawn(rpc_address, db, non_finalized_state_sender).await; Ok((read_state, latest_chain_tip, chain_tip_change, sync_task)) }) } diff --git a/zebra-scan/src/bin/scanner/main.rs b/zebra-scan/src/bin/scanner/main.rs index 092f0d2c1c5..e7ec853125f 100644 --- a/zebra-scan/src/bin/scanner/main.rs +++ b/zebra-scan/src/bin/scanner/main.rs @@ -7,7 +7,6 @@ use structopt::StructOpt; use tracing::*; use zebra_chain::{block::Height, parameters::Network}; -use zebra_rpc::config::Config as RpcConfig; use zebra_state::SaplingScanningKey; use core::net::SocketAddr; @@ -75,13 +74,10 @@ async fn main() -> Result<(), Box> { db_config, }; - let rpc_config = RpcConfig::default(); - // Get a read-only state and the database. let (read_state, _latest_chain_tip, chain_tip_change, sync_task) = zebra_rpc::sync::init_read_state_with_syncer( state_config, - rpc_config, &network, args.zebra_rpc_listen_addr, ) diff --git a/zebra-utils/src/bin/zebra-checkpoints/main.rs b/zebra-utils/src/bin/zebra-checkpoints/main.rs index a2cffdf9b74..cff158b5ca2 100644 --- a/zebra-utils/src/bin/zebra-checkpoints/main.rs +++ b/zebra-utils/src/bin/zebra-checkpoints/main.rs @@ -30,7 +30,6 @@ use zebra_node_services::{ constants::{MAX_CHECKPOINT_BYTE_COUNT, MAX_CHECKPOINT_HEIGHT_GAP}, rpc_client::RpcRequestClient, }; -use zebra_rpc::{config::Config as RpcConfig, server::cookie}; use zebra_utils::init_tracing; pub mod args; @@ -61,8 +60,7 @@ where let addr = our_args .addr .unwrap_or_else(|| "127.0.0.1:8232".parse().expect("valid address")); - let auth_cookie = cookie::get(RpcConfig::default().cookie_dir).expect("cookie should exist"); - let client = RpcRequestClient::new(addr, auth_cookie); + let client = RpcRequestClient::new(addr); // Launch a request with the RPC method and arguments // diff --git a/zebrad/tests/acceptance.rs b/zebrad/tests/acceptance.rs index b98996c95c4..002c12eb3e4 100644 --- a/zebrad/tests/acceptance.rs +++ b/zebrad/tests/acceptance.rs @@ -165,10 +165,7 @@ use zebra_chain::{ use zebra_consensus::ParameterCheckpoint; use zebra_node_services::rpc_client::RpcRequestClient; -use zebra_rpc::{ - config::Config as RpcConfig, - server::{cookie, OPENED_RPC_ENDPOINT_MSG}, -}; +use zebra_rpc::server::OPENED_RPC_ENDPOINT_MSG; use zebra_state::{constants::LOCK_FILE_ERROR, state_database_format_version_in_code}; @@ -1596,11 +1593,8 @@ async fn rpc_endpoint(parallel_cpu_threads: bool) -> Result<()> { // Wait until port is open. let rpc_address = read_listen_addr_from_logs(&mut child, OPENED_RPC_ENDPOINT_MSG)?; - // Get the auth cookie - let auth_cookie = - zebra_rpc::server::cookie::get(config.rpc.cookie_dir).expect("cookie should exist"); // Create an http client - let client = RpcRequestClient::new(rpc_address, auth_cookie); + let client = RpcRequestClient::new(rpc_address); // Make the call to the `getinfo` RPC method let res = client.call("getinfo", "[]".to_string()).await?; @@ -1656,12 +1650,8 @@ async fn rpc_endpoint_client_content_type() -> Result<()> { // Wait until port is open. let rpc_address = read_listen_addr_from_logs(&mut child, OPENED_RPC_ENDPOINT_MSG)?; - // Get the auth cookie - let auth_cookie = - zebra_rpc::server::cookie::get(config.rpc.cookie_dir).expect("cookie should exist"); - // Create an http client - let client = RpcRequestClient::new(rpc_address, auth_cookie); + let client = RpcRequestClient::new(rpc_address); // Call to `getinfo` RPC method with a no content type. let res = client @@ -1746,12 +1736,8 @@ fn non_blocking_logger() -> Result<()> { // Wait until port is open. let rpc_address = read_listen_addr_from_logs(&mut child, OPENED_RPC_ENDPOINT_MSG)?; - // Get the auth cookie - let auth_cookie = - zebra_rpc::server::cookie::get(config.rpc.cookie_dir).expect("cookie should exist"); - // Create an http client - let client = RpcRequestClient::new(rpc_address, auth_cookie); + let client = RpcRequestClient::new(rpc_address); // Most of Zebra's lines are 100-200 characters long, so 500 requests should print enough to fill the unix pipe, // fill the channel that tracing logs are queued onto, and drop logs rather than block execution. @@ -2422,10 +2408,7 @@ async fn fully_synced_rpc_test() -> Result<()> { zebrad.expect_stdout_line_matches(format!("Opened RPC endpoint at {zebra_rpc_address}"))?; - // Get the auth cookie - let auth_cookie = cookie::get(RpcConfig::default().cookie_dir).expect("cookie should exist"); - - let client = RpcRequestClient::new(zebra_rpc_address, auth_cookie); + let client = RpcRequestClient::new(zebra_rpc_address); // Make a getblock test that works only on synced node (high block number). // The block is before the mandatory checkpoint, so the checkpoint cached state can be used @@ -2865,14 +2848,9 @@ async fn fully_synced_rpc_z_getsubtreesbyindex_snapshot_test() -> Result<()> { // Wait for zebrad to load the full cached blockchain. zebrad.expect_stdout_line_matches(SYNC_FINISHED_REGEX)?; - // Get the auth cookie - let auth_cookie = cookie::get(RpcConfig::default().cookie_dir).expect("cookie should exist"); - // Create an http client - let client = RpcRequestClient::new( - zebra_rpc_address.expect("already checked that address is valid"), - auth_cookie, - ); + let client = + RpcRequestClient::new(zebra_rpc_address.expect("already checked that address is valid")); // Create test vector matrix let zcashd_test_vectors = vec![ @@ -3024,7 +3002,6 @@ async fn trusted_chain_sync_handles_forks_correctly() -> Result<()> { let (read_state, _latest_chain_tip, mut chain_tip_change, _sync_task) = zebra_rpc::sync::init_read_state_with_syncer( config.state.clone(), - config.rpc, &config.network.network, rpc_address, ) @@ -3042,10 +3019,7 @@ async fn trusted_chain_sync_handles_forks_correctly() -> Result<()> { tracing::info!("got genesis chain tip change, submitting more blocks .."); - // Get the auth cookie - let auth_cookie = cookie::get(config.state.cache_dir).expect("cookie should exist"); - - let rpc_client = RpcRequestClient::new(rpc_address, auth_cookie); + let rpc_client = RpcRequestClient::new(rpc_address); let mut blocks = Vec::new(); for _ in 0..10 { let (block, height) = rpc_client.submit_block_from_template().await?; @@ -3239,7 +3213,6 @@ async fn trusted_chain_sync_handles_forks_correctly() -> Result<()> { let (_read_state, _latest_chain_tip, mut chain_tip_change, _sync_task) = zebra_rpc::sync::init_read_state_with_syncer( config.state, - config.rpc, &config.network.network, rpc_address, ) diff --git a/zebrad/tests/common/cached_state.rs b/zebrad/tests/common/cached_state.rs index ac00e471b77..e7dca5075cb 100644 --- a/zebrad/tests/common/cached_state.rs +++ b/zebrad/tests/common/cached_state.rs @@ -23,7 +23,6 @@ use zebra_chain::{ }; use zebra_node_services::rpc_client::RpcRequestClient; -use zebra_rpc::{config::Config as RpcConfig, server::cookie}; use zebra_state::{ChainTipChange, LatestChainTip, MAX_BLOCK_REORG_HEIGHT}; use zebra_test::command::TestChild; @@ -230,11 +229,8 @@ pub async fn get_raw_future_blocks( true, )?; - // Get the auth cookie - let auth_cookie = cookie::get(RpcConfig::default().cookie_dir).expect("cookie should exist"); - // Create an http client - let rpc_client = RpcRequestClient::new(rpc_address, auth_cookie); + let rpc_client = RpcRequestClient::new(rpc_address); let blockchain_info: serde_json::Value = serde_json::from_str( &rpc_client diff --git a/zebrad/tests/common/checkpoints.rs b/zebrad/tests/common/checkpoints.rs index 2ac45e808c0..c1c0ae44716 100644 --- a/zebrad/tests/common/checkpoints.rs +++ b/zebrad/tests/common/checkpoints.rs @@ -20,7 +20,6 @@ use zebra_chain::{ }; use zebra_consensus::MAX_CHECKPOINT_HEIGHT_GAP; use zebra_node_services::rpc_client::RpcRequestClient; -use zebra_rpc::{config::Config as RpcConfig, server::cookie}; use zebra_state::state_database_format_version_in_code; use zebra_test::{ args, @@ -505,8 +504,7 @@ pub fn wait_for_zebra_checkpoints_generation< /// Returns an approximate `zebrad` tip height, using JSON-RPC. #[tracing::instrument] pub async fn zebrad_tip_height(zebra_rpc_address: SocketAddr) -> Result { - let auth_cookie = cookie::get(RpcConfig::default().cookie_dir).expect("cookie should exist"); - let client = RpcRequestClient::new(zebra_rpc_address, auth_cookie); + let client = RpcRequestClient::new(zebra_rpc_address); let zebrad_blockchain_info = client .text_from_call("getblockchaininfo", "[]".to_string()) diff --git a/zebrad/tests/common/config.rs b/zebrad/tests/common/config.rs index d6ee45f52ee..4b3f86201fd 100644 --- a/zebrad/tests/common/config.rs +++ b/zebrad/tests/common/config.rs @@ -166,6 +166,7 @@ pub fn rpc_port_config( // Default config, users who want to detect port conflicts configure this config.rpc.parallel_cpu_threads = 1; } + config.rpc.enable_cookie_auth = false; Ok(config) } diff --git a/zebrad/tests/common/configs/v2.0.0-rc.0.toml b/zebrad/tests/common/configs/v2.0.0-rc.0.toml index 70ba534e611..7f2276e63aa 100644 --- a/zebrad/tests/common/configs/v2.0.0-rc.0.toml +++ b/zebrad/tests/common/configs/v2.0.0-rc.0.toml @@ -63,6 +63,7 @@ peerset_initial_target_size = 25 [rpc] cookie_dir = "cache_dir" debug_force_finished_sync = false +enable_cookie_auth = true parallel_cpu_threads = 0 [state] diff --git a/zebrad/tests/common/get_block_template_rpcs/get_block_template.rs b/zebrad/tests/common/get_block_template_rpcs/get_block_template.rs index 442c8d2dca4..b13c7f04236 100644 --- a/zebrad/tests/common/get_block_template_rpcs/get_block_template.rs +++ b/zebrad/tests/common/get_block_template_rpcs/get_block_template.rs @@ -16,15 +16,11 @@ use zebra_chain::{ serialization::ZcashSerialize, }; use zebra_node_services::rpc_client::RpcRequestClient; -use zebra_rpc::{ - config::Config as RpcConfig, - methods::get_block_template_rpcs::{ - get_block_template::{ - proposal::TimeSource, GetBlockTemplate, JsonParameters, ProposalResponse, - }, - types::get_block_template::proposal_block_from_template, +use zebra_rpc::methods::get_block_template_rpcs::{ + get_block_template::{ + proposal::TimeSource, GetBlockTemplate, JsonParameters, ProposalResponse, }, - server::cookie, + types::get_block_template::proposal_block_from_template, }; use crate::common::{ @@ -98,8 +94,7 @@ pub(crate) async fn run() -> Result<()> { true, )?; - let auth_cookie = cookie::get(RpcConfig::default().cookie_dir).expect("cookie should exist"); - let client = RpcRequestClient::new(rpc_address, auth_cookie); + let client = RpcRequestClient::new(rpc_address); tracing::info!( "calling getblocktemplate RPC method at {rpc_address}, \ diff --git a/zebrad/tests/common/get_block_template_rpcs/get_peer_info.rs b/zebrad/tests/common/get_block_template_rpcs/get_peer_info.rs index e745ef9cead..dd30954948c 100644 --- a/zebrad/tests/common/get_block_template_rpcs/get_peer_info.rs +++ b/zebrad/tests/common/get_block_template_rpcs/get_peer_info.rs @@ -4,10 +4,7 @@ use color_eyre::eyre::{eyre, Context, Result}; use zebra_chain::parameters::Network; use zebra_node_services::rpc_client::RpcRequestClient; -use zebra_rpc::{ - config::Config as RpcConfig, methods::get_block_template_rpcs::types::peer_info::PeerInfo, - server::cookie, -}; +use zebra_rpc::methods::get_block_template_rpcs::types::peer_info::PeerInfo; use crate::common::{ launch::{can_spawn_zebrad_for_test_type, spawn_zebrad_for_rpc}, @@ -41,11 +38,8 @@ pub(crate) async fn run() -> Result<()> { tracing::info!(?rpc_address, "zebrad opened its RPC port",); - // Get the auth cookie - let auth_cookie = cookie::get(RpcConfig::default().cookie_dir).expect("cookie should exist"); - // call `getpeerinfo` RPC method - let peer_info_result: Vec = RpcRequestClient::new(rpc_address, auth_cookie) + let peer_info_result: Vec = RpcRequestClient::new(rpc_address) .json_result_from_call("getpeerinfo", "[]".to_string()) .await .map_err(|err| eyre!(err))?; diff --git a/zebrad/tests/common/get_block_template_rpcs/submit_block.rs b/zebrad/tests/common/get_block_template_rpcs/submit_block.rs index e02227102ac..399efc8d99e 100644 --- a/zebrad/tests/common/get_block_template_rpcs/submit_block.rs +++ b/zebrad/tests/common/get_block_template_rpcs/submit_block.rs @@ -12,7 +12,6 @@ use color_eyre::eyre::{Context, Result}; use zebra_chain::parameters::Network; use zebra_node_services::rpc_client::RpcRequestClient; -use zebra_rpc::{config::Config as RpcConfig, server::cookie}; use crate::common::{ cached_state::get_raw_future_blocks, @@ -64,10 +63,8 @@ pub(crate) async fn run() -> Result<()> { tracing::info!(?rpc_address, "zebrad opened its RPC port",); - let auth_cookie = cookie::get(RpcConfig::default().cookie_dir).expect("cookie should exist"); - // Create an http client - let client = RpcRequestClient::new(rpc_address, auth_cookie); + let client = RpcRequestClient::new(rpc_address); for raw_block in raw_blocks { let res = client diff --git a/zebrad/tests/common/lightwalletd/sync.rs b/zebrad/tests/common/lightwalletd/sync.rs index f9d3a72e027..8dce05a9150 100644 --- a/zebrad/tests/common/lightwalletd/sync.rs +++ b/zebrad/tests/common/lightwalletd/sync.rs @@ -9,7 +9,6 @@ use std::{ use tempfile::TempDir; use zebra_node_services::rpc_client::RpcRequestClient; -use zebra_rpc::{config::Config as RpcConfig, server::cookie}; use zebra_test::prelude::*; use crate::common::{launch::ZebradTestDirExt, test_type::TestType}; @@ -205,9 +204,7 @@ pub fn are_zebrad_and_lightwalletd_tips_synced( let lightwalletd_tip_height = (lightwalletd_next_height - 1) as u64; // Get the block tip from zebrad - let auth_cookie = - cookie::get(RpcConfig::default().cookie_dir).expect("cookie should exist"); - let client = RpcRequestClient::new(zebra_rpc_address, auth_cookie); + let client = RpcRequestClient::new(zebra_rpc_address); let zebrad_blockchain_info = client .text_from_call("getblockchaininfo", "[]".to_string()) .await?; diff --git a/zebrad/tests/common/regtest.rs b/zebrad/tests/common/regtest.rs index fae5c57e7ab..bf1cba697de 100644 --- a/zebrad/tests/common/regtest.rs +++ b/zebrad/tests/common/regtest.rs @@ -17,7 +17,6 @@ use zebra_chain::{ }; use zebra_node_services::rpc_client::RpcRequestClient; use zebra_rpc::{ - config::Config as RpcConfig, constants::MISSING_BLOCK_ERROR_CODE, methods::{ get_block_template_rpcs::{ @@ -28,7 +27,7 @@ use zebra_rpc::{ }, hex_data::HexData, }, - server::{cookie, OPENED_RPC_ENDPOINT_MSG}, + server::OPENED_RPC_ENDPOINT_MSG, }; use zebra_test::args; @@ -74,8 +73,7 @@ pub(crate) async fn submit_blocks_test() -> Result<()> { /// Get block templates and submit blocks async fn submit_blocks(network: Network, rpc_address: SocketAddr) -> Result<()> { - let auth_cookie = cookie::get(RpcConfig::default().cookie_dir).expect("cookie should exist"); - let client = RpcRequestClient::new(rpc_address, auth_cookie); + let client = RpcRequestClient::new(rpc_address); for _ in 1..=NUM_BLOCKS_TO_SUBMIT { let (mut block, height) = client