Skip to content

Commit

Permalink
add a enable_cookie auth option to config and use it in all tests
Browse files Browse the repository at this point in the history
  • Loading branch information
oxarbitrage committed Oct 13, 2024
1 parent 7a7c14a commit f02159e
Show file tree
Hide file tree
Showing 20 changed files with 47 additions and 114 deletions.
1 change: 0 additions & 1 deletion Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6172,7 +6172,6 @@ dependencies = [
name = "zebra-node-services"
version = "1.0.0-beta.39"
dependencies = [
"base64 0.22.1",
"color-eyre",
"jsonrpc-core",
"reqwest",
Expand Down
3 changes: 0 additions & 3 deletions zebra-node-services/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ getblocktemplate-rpcs = [
# Tool and test features

rpc-client = [
"base64",
"color-eyre",
"jsonrpc-core",
"reqwest",
Expand All @@ -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
Expand All @@ -54,7 +52,6 @@ tokio = { version = "1.40.0", features = ["time", "sync"] }

[dev-dependencies]

base64 = "0.22.1"
color-eyre = "0.6.3"
jsonrpc-core = "18.0.0"
reqwest = { version = "0.11.26", default-features = false, features = ["rustls-tls"] }
Expand Down
12 changes: 1 addition & 11 deletions zebra-node-services/src/rpc_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
use std::net::SocketAddr;

use base64::{engine::general_purpose::URL_SAFE, Engine as _};
use reqwest::Client;

use crate::BoxError;
Expand All @@ -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,
}
}

Expand All @@ -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
}
Expand Down
8 changes: 7 additions & 1 deletion zebra-rpc/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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,
}
}
}
3 changes: 3 additions & 0 deletions zebra-rpc/src/server/http_request_compatibility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
4 changes: 4 additions & 0 deletions zebra-rpc/src/server/tests/vectors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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();
Expand Down
20 changes: 6 additions & 14 deletions zebra-rpc/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,8 @@ impl TrustedChainSync {
rpc_address: SocketAddr,
db: ZebraDb,
non_finalized_state_sender: tokio::sync::watch::Sender<NonFinalizedState>,
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());
Expand Down Expand Up @@ -317,8 +315,7 @@ impl TrustedChainSync {
/// Returns a [`ReadStateService`], [`LatestChainTip`], [`ChainTipChange`], and
/// a [`JoinHandle`] for the sync task.
pub fn init_read_state_with_syncer(
state_config: zebra_state::Config,
rpc_config: crate::config::Config,
config: zebra_state::Config,
network: &Network,
rpc_address: SocketAddr,
) -> tokio::task::JoinHandle<
Expand All @@ -334,19 +331,14 @@ pub fn init_read_state_with_syncer(
> {
let network = network.clone();
tokio::spawn(async move {
if state_config.ephemeral {
if config.ephemeral {
return Err("standalone read state service cannot be used with ephemeral state".into());
}

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;
spawn_init_read_only(config, &network).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))
})
}
Expand Down
4 changes: 0 additions & 4 deletions zebra-scan/src/bin/scanner/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -75,13 +74,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
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,
)
Expand Down
4 changes: 1 addition & 3 deletions zebra-utils/src/bin/zebra-checkpoints/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
//
Expand Down
47 changes: 9 additions & 38 deletions zebrad/tests/acceptance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,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};

#[cfg(not(target_os = "windows"))]
Expand Down Expand Up @@ -1596,11 +1591,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?;
Expand Down Expand Up @@ -1656,12 +1648,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
Expand Down Expand Up @@ -1746,12 +1734,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.
Expand Down Expand Up @@ -2422,10 +2406,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
Expand Down Expand Up @@ -2865,14 +2846,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![
Expand Down Expand Up @@ -3023,8 +2999,7 @@ async fn trusted_chain_sync_handles_forks_correctly() -> Result<()> {
// Spawn a read state with the RPC syncer to check that it has the same best chain as Zebra
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.state,
&config.network.network,
rpc_address,
)
Expand All @@ -3042,10 +3017,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?;
Expand Down Expand Up @@ -3239,7 +3211,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,
)
Expand Down
7 changes: 1 addition & 6 deletions zebrad/tests/common/cached_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ use zebra_chain::{
serialization::ZcashDeserializeInto,
};
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;

Expand Down Expand Up @@ -230,11 +228,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
Expand Down
4 changes: 1 addition & 3 deletions zebrad/tests/common/checkpoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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<Height> {
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())
Expand Down
1 change: 1 addition & 0 deletions zebrad/tests/common/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
1 change: 1 addition & 0 deletions zebrad/tests/common/configs/v2.0.0-rc.0.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
Loading

0 comments on commit f02159e

Please sign in to comment.