From 004c219643ae42c0c1afcdb835542e53b581bfa3 Mon Sep 17 00:00:00 2001 From: jorgeantonio21 Date: Thu, 1 Sep 2022 11:49:22 +0100 Subject: [PATCH] fix: add Grpc authentication to merge mining proxy (see issue #4587) (#4592) Description --- It is desirable that the Merge mining proxy has a GRPC authenticated wallet client connection. Motivation and Context --- Contrary to the Mining wallet client connection, the merge mining proxy does not have GRPC authentication currently. This issue aims to add it to GRPC auth in the merge mining proxy. Fixes https://github.com/tari-project/tari/issues/4587. How Has This Been Tested? --- Existing unit tests --- Cargo.lock | 1 + .../tari_merge_mining_proxy/Cargo.toml | 1 + .../src/block_template_protocol.rs | 10 ++++--- .../tari_merge_mining_proxy/src/config.rs | 4 +++ .../tari_merge_mining_proxy/src/error.rs | 7 ++++- .../tari_merge_mining_proxy/src/main.rs | 27 +++++++++++++++++-- .../tari_merge_mining_proxy/src/proxy.rs | 5 ++-- .../config/presets/f_merge_mining_proxy.toml | 3 +++ 8 files changed, 50 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 86694d42ee..6717ff4a2a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5133,6 +5133,7 @@ dependencies = [ "tari_app_grpc", "tari_app_utilities", "tari_common", + "tari_common_types", "tari_comms", "tari_core", "tari_crypto", diff --git a/applications/tari_merge_mining_proxy/Cargo.toml b/applications/tari_merge_mining_proxy/Cargo.toml index 72c6a0fb8d..ea22b06b8a 100644 --- a/applications/tari_merge_mining_proxy/Cargo.toml +++ b/applications/tari_merge_mining_proxy/Cargo.toml @@ -14,6 +14,7 @@ envlog = ["env_logger"] [dependencies] tari_app_grpc = { path = "../tari_app_grpc" } tari_common = { path = "../../common" } +tari_common_types = { path = "../../base_layer/common_types" } tari_comms = { path = "../../comms/core" } tari_core = { path = "../../base_layer/core", default-features = false, features = ["transactions"] } tari_app_utilities = { path = "../tari_app_utilities" } diff --git a/applications/tari_merge_mining_proxy/src/block_template_protocol.rs b/applications/tari_merge_mining_proxy/src/block_template_protocol.rs index 29a48e6f2f..d7ccc67a6e 100644 --- a/applications/tari_merge_mining_proxy/src/block_template_protocol.rs +++ b/applications/tari_merge_mining_proxy/src/block_template_protocol.rs @@ -25,7 +25,7 @@ use std::cmp; use log::*; -use tari_app_grpc::tari_rpc as grpc; +use tari_app_grpc::{authentication::ClientAuthenticationInterceptor, tari_rpc as grpc}; use tari_core::proof_of_work::{monero_rx, monero_rx::FixedByteArray, Difficulty}; use crate::{ @@ -39,13 +39,17 @@ const LOG_TARGET: &str = "tari_mm_proxy::proxy::block_template_protocol"; /// Structure holding grpc connections. pub struct BlockTemplateProtocol<'a> { base_node_client: &'a mut grpc::base_node_client::BaseNodeClient, - wallet_client: &'a mut grpc::wallet_client::WalletClient, + wallet_client: &'a mut grpc::wallet_client::WalletClient< + tonic::codegen::InterceptedService, + >, } impl<'a> BlockTemplateProtocol<'a> { pub fn new( base_node_client: &'a mut grpc::base_node_client::BaseNodeClient, - wallet_client: &'a mut grpc::wallet_client::WalletClient, + wallet_client: &'a mut grpc::wallet_client::WalletClient< + tonic::codegen::InterceptedService, + >, ) -> Self { Self { base_node_client, diff --git a/applications/tari_merge_mining_proxy/src/config.rs b/applications/tari_merge_mining_proxy/src/config.rs index 23549aab1e..0bffda2fa9 100644 --- a/applications/tari_merge_mining_proxy/src/config.rs +++ b/applications/tari_merge_mining_proxy/src/config.rs @@ -22,6 +22,7 @@ use serde::{Deserialize, Serialize}; use tari_common::{configuration::StringList, SubConfigPath}; +use tari_common_types::grpc_authentication::GrpcAuthentication; use tari_comms::multiaddr::Multiaddr; #[derive(Clone, Debug, Deserialize, Serialize)] @@ -41,6 +42,8 @@ pub struct MergeMiningProxyConfig { pub base_node_grpc_address: Multiaddr, /// The Tari console wallet's GRPC address pub console_wallet_grpc_address: Multiaddr, + /// GRPC authentication for console wallet + pub console_wallet_grpc_authentication: GrpcAuthentication, /// Address of the tari_merge_mining_proxy application pub listener_address: Multiaddr, /// In sole merged mining, the block solution is usually submitted to the Monero blockchain (monerod) as well as to @@ -69,6 +72,7 @@ impl Default for MergeMiningProxyConfig { monerod_use_auth: false, base_node_grpc_address: "/ip4/127.0.0.1/tcp/18142".parse().unwrap(), console_wallet_grpc_address: "/ip4/127.0.0.1/tcp/18143".parse().unwrap(), + console_wallet_grpc_authentication: GrpcAuthentication::default(), listener_address: "/ip4/127.0.0.1/tcp/18081".parse().unwrap(), submit_to_origin: true, wait_for_initial_sync_at_startup: true, diff --git a/applications/tari_merge_mining_proxy/src/error.rs b/applications/tari_merge_mining_proxy/src/error.rs index 92fc25651c..0d308d3bf4 100644 --- a/applications/tari_merge_mining_proxy/src/error.rs +++ b/applications/tari_merge_mining_proxy/src/error.rs @@ -26,10 +26,11 @@ use std::io; use hex::FromHexError; use hyper::header::InvalidHeaderValue; +use tari_app_grpc::authentication::BasicAuthError; use tari_common::{ConfigError, ConfigurationError}; use tari_core::{proof_of_work::monero_rx::MergeMineError, transactions::CoinbaseBuildError}; use thiserror::Error; -use tonic::transport; +use tonic::{codegen::http::uri::InvalidUri, transport}; #[derive(Debug, Error)] pub enum MmProxyError { @@ -42,6 +43,8 @@ pub enum MmProxyError { #[from] source: MergeMineError, }, + #[error("Invalid URI: {0}")] + InvalidUriError(#[from] InvalidUri), #[error("Reqwest error: {0}")] ReqwestError(#[from] reqwest::Error), #[error("Missing data:{0}")] @@ -50,6 +53,8 @@ pub enum MmProxyError { IoError(#[from] io::Error), #[error("Tonic transport error: {0}")] TonicTransportError(#[from] transport::Error), + #[error("Grpc authentication error: {0}")] + GRPCAuthenticationError(#[from] BasicAuthError), #[error("GRPC response did not contain the expected field: `{0}`")] GrpcResponseMissingField(&'static str), #[error("Hyper error: {0}")] diff --git a/applications/tari_merge_mining_proxy/src/main.rs b/applications/tari_merge_mining_proxy/src/main.rs index bb5ea7992d..a58230850d 100644 --- a/applications/tari_merge_mining_proxy/src/main.rs +++ b/applications/tari_merge_mining_proxy/src/main.rs @@ -34,6 +34,7 @@ mod test; use std::{ convert::Infallible, io::{stdout, Write}, + str::FromStr, }; use clap::Parser; @@ -42,12 +43,16 @@ use futures::future; use hyper::{service::make_service_fn, Server}; use log::*; use proxy::MergeMiningProxyService; -use tari_app_grpc::tari_rpc as grpc; +use tari_app_grpc::{authentication::ClientAuthenticationInterceptor, tari_rpc as grpc}; use tari_app_utilities::consts; use tari_common::{initialize_logging, load_configuration, DefaultConfigLoader}; use tari_comms::utils::multiaddr::multiaddr_to_socketaddr; use tari_core::proof_of_work::randomx_factory::RandomXFactory; use tokio::time::Duration; +use tonic::{ + codegen::InterceptedService, + transport::{Channel, Endpoint}, +}; use crate::{ block_template_data::BlockTemplateRepository, @@ -57,6 +62,24 @@ use crate::{ }; const LOG_TARGET: &str = "tari_mm_proxy::proxy"; +pub(crate) type WalletGrpcClient = + grpc::wallet_client::WalletClient>; + +async fn connect_wallet_with_authenticator(config: &MergeMiningProxyConfig) -> Result { + let wallet_addr = format!( + "http://{}", + multiaddr_to_socketaddr(&config.console_wallet_grpc_address)? + ); + info!(target: LOG_TARGET, "👛 Connecting to wallet at {}", wallet_addr); + let channel = Endpoint::from_str(&wallet_addr)?.connect().await?; + let wallet_conn = grpc::wallet_client::WalletClient::with_interceptor( + channel, + ClientAuthenticationInterceptor::create(&config.console_wallet_grpc_authentication)?, + ); + + Ok(wallet_conn) +} + #[tokio::main] async fn main() -> Result<(), anyhow::Error> { let terminal_title = format!("Tari Merge Mining Proxy - Version {}", consts::APP_VERSION); @@ -90,7 +113,7 @@ async fn main() -> Result<(), anyhow::Error> { let wallet = multiaddr_to_socketaddr(&config.console_wallet_grpc_address)?; info!(target: LOG_TARGET, "Connecting to wallet at {}", wallet); println!("Connecting to wallet at {}", wallet); - let wallet_client = grpc::wallet_client::WalletClient::connect(format!("http://{}", wallet)).await?; + let wallet_client = connect_wallet_with_authenticator(&config).await?; let listen_addr = multiaddr_to_socketaddr(&config.listener_address)?; let randomx_factory = RandomXFactory::new(config.max_randomx_vms); let xmrig_service = MergeMiningProxyService::new( diff --git a/applications/tari_merge_mining_proxy/src/proxy.rs b/applications/tari_merge_mining_proxy/src/proxy.rs index e67c7fbd76..667cb21320 100644 --- a/applications/tari_merge_mining_proxy/src/proxy.rs +++ b/applications/tari_merge_mining_proxy/src/proxy.rs @@ -54,6 +54,7 @@ use crate::{ common::{json_rpc, monero_rpc::CoreRpcErrorCode, proxy, proxy::convert_json_to_hyper_json_response}, config::MergeMiningProxyConfig, error::MmProxyError, + WalletGrpcClient, }; const LOG_TARGET: &str = "tari_mm_proxy::proxy"; @@ -72,7 +73,7 @@ impl MergeMiningProxyService { config: MergeMiningProxyConfig, http_client: reqwest::Client, base_node_client: grpc::base_node_client::BaseNodeClient, - wallet_client: grpc::wallet_client::WalletClient, + wallet_client: WalletGrpcClient, block_templates: BlockTemplateRepository, randomx_factory: RandomXFactory, ) -> Self { @@ -154,7 +155,7 @@ struct InnerService { block_templates: BlockTemplateRepository, http_client: reqwest::Client, base_node_client: grpc::base_node_client::BaseNodeClient, - wallet_client: grpc::wallet_client::WalletClient, + wallet_client: WalletGrpcClient, initial_sync_achieved: Arc, current_monerod_server: Arc>>, last_assigned_monerod_server: Arc>>, diff --git a/common/config/presets/f_merge_mining_proxy.toml b/common/config/presets/f_merge_mining_proxy.toml index 17935f2129..52bab71161 100644 --- a/common/config/presets/f_merge_mining_proxy.toml +++ b/common/config/presets/f_merge_mining_proxy.toml @@ -42,6 +42,9 @@ monerod_url = [# stagenet # The Tari console wallet's GRPC address. (default = "/ip4/127.0.0.1/tcp/18143") #console_wallet_grpc_address = "/ip4/127.0.0.1/tcp/18143" +# GRPC authentication for the Tari console wallet (default = "none") +#wallet_grpc_authentication = { username: "miner", password: "$argon..." } + # Address of the tari_merge_mining_proxy application. (default = "/ip4/127.0.0.1/tcp/18081") #listener_address = "/ip4/127.0.0.1/tcp/18081"