diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 46799747c..081a3f939 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -96,13 +96,3 @@ jobs: concurrency: group: ${{ github.workflow }}-clock-rocks-${{ github.ref || github.run_id }} cancel-in-progress: true - - e2e-admin-password: - name: E2E Admin Password - uses: ./.github/workflows/_setup-e2e.yml - with: - justfile_recipe: "e2e-admin-password" - - concurrency: - group: ${{ github.workflow }}-admin-password-${{ github.ref || github.run_id }} - cancel-in-progress: true diff --git a/e2e/cloudwalk-contracts/integration/test/leader-follower-change.test.ts b/e2e/cloudwalk-contracts/integration/test/leader-follower-change.test.ts index e556e5897..132118801 100644 --- a/e2e/cloudwalk-contracts/integration/test/leader-follower-change.test.ts +++ b/e2e/cloudwalk-contracts/integration/test/leader-follower-change.test.ts @@ -16,7 +16,7 @@ describe("Leader & Follower change integration test", function () { const version = await sendWithRetry("stratus_version", []); expect(version).to.have.nested.property("git.commit"); expect(version.git.commit).to.be.a("string"); - expect(version.git.commit.length).to.be.oneOf([7, 8]); + expect(version.git.commit).to.have.lengthOf(7); }); it("Validate initial Follower state, health and version", async function () { @@ -32,7 +32,7 @@ describe("Leader & Follower change integration test", function () { const version = await sendWithRetry("stratus_version", []); expect(version).to.have.nested.property("git.commit"); expect(version.git.commit).to.be.a("string"); - expect(version.git.commit.length).to.be.oneOf([7, 8]); + expect(version.git.commit).to.have.lengthOf(7); }); it("Change Leader to Leader should return false", async function () { diff --git a/e2e/test/admin/e2e-admin-password-disabled.test.ts b/e2e/test/admin/e2e-admin-password-disabled.test.ts deleted file mode 100644 index 5bc24036f..000000000 --- a/e2e/test/admin/e2e-admin-password-disabled.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { expect } from "chai"; - -import { send, sendReset } from "../helpers/rpc"; - -describe("Admin Password (without password set)", () => { - before(async () => { - await sendReset(); - }); - - it("should accept requests without password", async () => { - const result = await send("stratus_enableTransactions", []); - expect(result).to.be.true; - - // Cleanup - disable transactions - await send("stratus_disableTransactions", []); - }); - - it("should accept requests with any password", async () => { - const headers = { Authorization: "Password random123" }; - const result = await send("stratus_enableTransactions", [], headers); - expect(result).to.be.true; - - // Cleanup - disable transactions - await send("stratus_disableTransactions", [], headers); - }); -}); diff --git a/e2e/test/admin/e2e-admin-password-enabled.test.ts b/e2e/test/admin/e2e-admin-password-enabled.test.ts deleted file mode 100644 index 0f20ae660..000000000 --- a/e2e/test/admin/e2e-admin-password-enabled.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { expect } from "chai"; - -import { send, sendAndGetError, sendReset } from "../helpers/rpc"; - -describe("Admin Password (with password set)", () => { - before(async () => { - await sendReset(); - }); - - it("should reject requests without password", async () => { - const error = await sendAndGetError("stratus_enableTransactions", []); - console.log(error); - expect(error.code).eq(-32009); // Internal error - expect(error.message).to.contain("Incorrect password"); - }); - - it("should reject requests with wrong password", async () => { - const headers = { Authorization: "Password wrong123" }; - const error = await sendAndGetError("stratus_enableTransactions", [], headers); - expect(error.code).eq(-32009); // Internal error - expect(error.message).to.contain("Incorrect password"); - }); - - it("should accept requests with correct password", async () => { - const headers = { Authorization: "Password test123" }; - const result = await send("stratus_enableTransactions", [], headers); - expect(result).to.be.true; - - // Cleanup - disable transactions - await send("stratus_disableTransactions", [], headers); - }); -}); diff --git a/e2e/test/helpers/rpc.ts b/e2e/test/helpers/rpc.ts index 57c46de59..a3cacafb7 100644 --- a/e2e/test/helpers/rpc.ts +++ b/e2e/test/helpers/rpc.ts @@ -111,11 +111,7 @@ if (process.env.RPC_LOG) { // Sends an RPC request to the blockchain, returning full response. let requestId = 0; -export async function sendAndGetFullResponse( - method: string, - params: any[] = [], - headers: Record = {}, -): Promise { +export async function sendAndGetFullResponse(method: string, params: any[] = []): Promise { for (let i = 0; i < params.length; ++i) { const param = params[i]; if (param instanceof Account) { @@ -134,14 +130,8 @@ export async function sendAndGetFullResponse( console.log("REQ ->", JSON.stringify(payload)); } - // prepare headers - const requestHeaders = { - "Content-Type": "application/json", - ...headers, - }; - // execute request and log response - const response = await axios.post(providerUrl, payload, { headers: requestHeaders }); + const response = await axios.post(providerUrl, payload, { headers: { "Content-Type": "application/json" } }); if (process.env.RPC_LOG) { console.log("RESP <-", JSON.stringify(response.data)); } @@ -150,19 +140,15 @@ export async function sendAndGetFullResponse( } // Sends an RPC request to the blockchain, returning its result field. -export async function send(method: string, params: any[] = [], headers: Record = {}): Promise { - const response = await sendAndGetFullResponse(method, params, headers); +export async function send(method: string, params: any[] = []): Promise { + const response = await sendAndGetFullResponse(method, params); return response.data.result; } // Sends an RPC request to the blockchain, returning its error field. // Use it when you expect the RPC call to fail. -export async function sendAndGetError( - method: string, - params: any[] = [], - headers: Record = {}, -): Promise { - const response = await sendAndGetFullResponse(method, params, headers); +export async function sendAndGetError(method: string, params: any[] = []): Promise { + const response = await sendAndGetFullResponse(method, params); return response.data.error; } diff --git a/justfile b/justfile index f388f65a4..b97c82bc7 100644 --- a/justfile +++ b/justfile @@ -159,25 +159,6 @@ e2e network="stratus" block_modes="automine" test="": fi done -# E2E: Execute admin password tests -e2e-admin-password: - #!/bin/bash - just build - - # Start Stratus with password set - just _log "Running admin password tests with password set" - ADMIN_PASSWORD=test123 just run -a 0.0.0.0:3000 & - just _wait_for_stratus - cd e2e && npx hardhat test test/admin/e2e-admin-password-enabled.test.ts --network stratus - killport 3000 - - # Start Stratus without password set - just _log "Running admin password tests without password set" - just run -a 0.0.0.0:3000 & - just _wait_for_stratus - cd e2e && npx hardhat test test/admin/e2e-admin-password-disabled.test.ts --network stratus - killport 3000 - # E2E: Starts and execute Hardhat tests in Hardhat e2e-hardhat block-mode="automine" test="": #!/bin/bash @@ -618,4 +599,4 @@ stratus-test-coverage *args="": -rm utils/deploy/deploy_02.log */ - cargo llvm-cov report {{args}} + cargo llvm-cov report {{args}} \ No newline at end of file diff --git a/src/eth/primitives/stratus_error.rs b/src/eth/primitives/stratus_error.rs index 1176586b4..039db494f 100644 --- a/src/eth/primitives/stratus_error.rs +++ b/src/eth/primitives/stratus_error.rs @@ -192,10 +192,6 @@ pub enum StratusError { #[strum(props(kind = "server_state"))] StratusNotFollower, - #[error("Incorrect password, cancelling operation.")] - #[strum(props(kind = "server_state"))] - InvalidPassword, - #[error("Stratus node is already in the process of changing mode.")] #[strum(props(kind = "server_state"))] ModeChangeInProgress, diff --git a/src/eth/rpc/rpc_http_middleware.rs b/src/eth/rpc/rpc_http_middleware.rs index 3511f5546..608f8166f 100644 --- a/src/eth/rpc/rpc_http_middleware.rs +++ b/src/eth/rpc/rpc_http_middleware.rs @@ -12,7 +12,6 @@ use reqwest::header::HeaderMap; use reqwest::header::HeaderValue; use tower::Service; -use crate::eth::primitives::StratusError; use crate::eth::rpc::RpcClientApp; use crate::ext::not; @@ -37,46 +36,12 @@ where fn call(&mut self, mut request: HttpRequest) -> Self::Future { let client_app = parse_client_app(request.headers(), request.uri()); - let authentication = parse_admin_password(request.headers()); request.extensions_mut().insert(client_app); - request.extensions_mut().insert(authentication); Box::pin(self.service.call(request).map_err(Into::into)) } } -#[derive(Debug, Clone)] -pub enum Authentication { - Admin, - None, -} - -impl Authentication { - pub fn auth_admin(&self) -> Result<(), StratusError> { - if matches!(self, Authentication::Admin) { - return Ok(()); - } - Err(StratusError::InvalidPassword) - } -} - -/// Checks if the provided admin password is correct -fn parse_admin_password(headers: &HeaderMap) -> Authentication { - let real_pass = match std::env::var("ADMIN_PASSWORD") { - Ok(pass) if !pass.is_empty() => pass, - _ => return Authentication::Admin, - }; - - match headers - .get("Authorization") - .and_then(|val| val.to_str().ok()) - .and_then(|val| val.strip_prefix("Password ")) - { - Some(password) if password == real_pass => Authentication::Admin, - _ => Authentication::None, - } -} - /// Extracts the client application name from the `app` query parameter. fn parse_client_app(headers: &HeaderMap, uri: &Uri) -> RpcClientApp { fn try_query_params(uri: &Uri) -> Option { diff --git a/src/eth/rpc/rpc_middleware.rs b/src/eth/rpc/rpc_middleware.rs index 9f648c243..d777ea060 100644 --- a/src/eth/rpc/rpc_middleware.rs +++ b/src/eth/rpc/rpc_middleware.rs @@ -87,8 +87,6 @@ impl<'a> RpcServiceT<'a> for RpcMiddleware { _ => None, }; - let is_admin = request.extensions.is_admin(); - let client = if let Some(tx_client) = tx.as_ref().and_then(|tx| tx.client.as_ref()) { let val = tx_client.clone(); request.extensions_mut().insert(val); @@ -117,7 +115,6 @@ impl<'a> RpcServiceT<'a> for RpcMiddleware { rpc_tx_function = %tx.as_ref().map(|tx|tx.function).or_empty(), rpc_tx_from = %tx.as_ref().and_then(|tx|tx.from).or_empty(), rpc_tx_to = %tx.as_ref().and_then(|tx|tx.to).or_empty(), - is_admin = %is_admin, "rpc request" ); diff --git a/src/eth/rpc/rpc_parser.rs b/src/eth/rpc/rpc_parser.rs index e4f654839..793603c5f 100644 --- a/src/eth/rpc/rpc_parser.rs +++ b/src/eth/rpc/rpc_parser.rs @@ -5,7 +5,6 @@ use jsonrpsee::Extensions; use rlp::Decodable; use tracing::Span; -use super::rpc_http_middleware::Authentication; use crate::eth::primitives::StratusError; use crate::eth::rpc::rpc_client_app::RpcClientApp; use crate::ext::type_basename; @@ -16,12 +15,6 @@ pub trait RpcExtensionsExt { /// Returns the client performing the JSON-RPC request. fn rpc_client(&self) -> &RpcClientApp; - /// Returns current Authentication. - fn authentication(&self) -> &Authentication; - - /// Returns wheather admin authentication suceeded. - fn is_admin(&self) -> bool; - /// Enters RpcMiddleware request span if present. fn enter_middleware_span(&self) -> Option>; } @@ -31,14 +24,6 @@ impl RpcExtensionsExt for Extensions { self.get::().unwrap_or(&RpcClientApp::Unknown) } - fn authentication(&self) -> &Authentication { - self.get::().unwrap_or(&Authentication::None) - } - - fn is_admin(&self) -> bool { - matches!(self.authentication(), Authentication::Admin) - } - fn enter_middleware_span(&self) -> Option> { self.get::().map(|s| s.enter()).map(EnteredWrap::new) } diff --git a/src/eth/rpc/rpc_server.rs b/src/eth/rpc/rpc_server.rs index 412ee3dde..65ad2f8a8 100644 --- a/src/eth/rpc/rpc_server.rs +++ b/src/eth/rpc/rpc_server.rs @@ -321,7 +321,6 @@ fn stratus_reset(_: Params<'_>, ctx: Arc, _: Extensions) -> Result = Lazy::new(|| Semaphore::new(1)); async fn stratus_change_to_leader(_: Params<'_>, ctx: Arc, ext: Extensions) -> Result { - ext.authentication().auth_admin()?; let permit = MODE_CHANGE_SEMAPHORE.try_acquire(); let _permit: SemaphorePermit = match permit { Ok(permit) => permit, @@ -371,7 +370,6 @@ async fn stratus_change_to_leader(_: Params<'_>, ctx: Arc, ext: Exte } async fn stratus_change_to_follower(params: Params<'_>, ctx: Arc, ext: Extensions) -> Result { - ext.authentication().auth_admin()?; let permit = MODE_CHANGE_SEMAPHORE.try_acquire(); let _permit: SemaphorePermit = match permit { Ok(permit) => permit, @@ -425,8 +423,7 @@ async fn stratus_change_to_follower(params: Params<'_>, ctx: Arc, ex Ok(json!(true)) } -async fn stratus_init_importer(params: Params<'_>, ctx: Arc, ext: Extensions) -> Result { - ext.authentication().auth_admin()?; +async fn stratus_init_importer(params: Params<'_>, ctx: Arc, _: Extensions) -> Result { let (params, external_rpc) = next_rpc_param::(params.sequence())?; let (params, external_rpc_ws) = next_rpc_param::(params)?; let (params, raw_external_rpc_timeout) = next_rpc_param::(params)?; @@ -452,8 +449,7 @@ async fn stratus_init_importer(params: Params<'_>, ctx: Arc, ext: Ex importer_config.init_follower_importer(ctx).await } -fn stratus_shutdown_importer(_: Params<'_>, ctx: &RpcContext, ext: &Extensions) -> Result { - ext.authentication().auth_admin()?; +fn stratus_shutdown_importer(_: Params<'_>, ctx: &RpcContext, _: &Extensions) -> Result { if GlobalState::get_node_mode() != NodeMode::Follower { tracing::error!("node is currently not a follower"); return Err(StratusError::StratusNotFollower); @@ -472,10 +468,8 @@ fn stratus_shutdown_importer(_: Params<'_>, ctx: &RpcContext, ext: &Extensions) Ok(json!(true)) } -async fn stratus_change_miner_mode(params: Params<'_>, ctx: Arc, ext: Extensions) -> Result { - ext.authentication().auth_admin()?; +async fn stratus_change_miner_mode(params: Params<'_>, ctx: Arc, _: Extensions) -> Result { let (_, mode_str) = next_rpc_param::(params.sequence())?; - let mode = MinerMode::from_str(&mode_str).map_err(|e| { tracing::error!(reason = ?e, "failed to parse miner mode"); StratusError::MinerModeParamInvalid @@ -536,40 +530,34 @@ async fn change_miner_mode(new_mode: MinerMode, ctx: &RpcContext) -> Result, _: &RpcContext, ext: &Extensions) -> Result { - ext.authentication().auth_admin()?; +fn stratus_enable_unknown_clients(_: Params<'_>, _: &RpcContext, _: &Extensions) -> bool { GlobalState::set_unknown_client_enabled(true); - Ok(GlobalState::is_unknown_client_enabled()) + GlobalState::is_unknown_client_enabled() } -fn stratus_disable_unknown_clients(_: Params<'_>, _: &RpcContext, ext: &Extensions) -> Result { - ext.authentication().auth_admin()?; +fn stratus_disable_unknown_clients(_: Params<'_>, _: &RpcContext, _: &Extensions) -> bool { GlobalState::set_unknown_client_enabled(false); - Ok(GlobalState::is_unknown_client_enabled()) + GlobalState::is_unknown_client_enabled() } -fn stratus_enable_transactions(_: Params<'_>, _: &RpcContext, ext: &Extensions) -> Result { - ext.authentication().auth_admin()?; +fn stratus_enable_transactions(_: Params<'_>, _: &RpcContext, _: &Extensions) -> bool { GlobalState::set_transactions_enabled(true); - Ok(GlobalState::is_transactions_enabled()) + GlobalState::is_transactions_enabled() } -fn stratus_disable_transactions(_: Params<'_>, _: &RpcContext, ext: &Extensions) -> Result { - ext.authentication().auth_admin()?; +fn stratus_disable_transactions(_: Params<'_>, _: &RpcContext, _: &Extensions) -> bool { GlobalState::set_transactions_enabled(false); - Ok(GlobalState::is_transactions_enabled()) + GlobalState::is_transactions_enabled() } -fn stratus_enable_miner(_: Params<'_>, ctx: &RpcContext, ext: &Extensions) -> Result { - ext.authentication().auth_admin()?; +fn stratus_enable_miner(_: Params<'_>, ctx: &RpcContext, _: &Extensions) -> bool { ctx.miner.unpause(); - Ok(true) + true } -fn stratus_disable_miner(_: Params<'_>, ctx: &RpcContext, ext: &Extensions) -> Result { - ext.authentication().auth_admin()?; +fn stratus_disable_miner(_: Params<'_>, ctx: &RpcContext, _: &Extensions) -> bool { ctx.miner.pause(); - Ok(false) + false } /// Returns the count of executed transactions waiting to enter the next block.