diff --git a/canister/src/main.rs b/canister/src/main.rs index 7e588c26..54ea8ca6 100644 --- a/canister/src/main.rs +++ b/canister/src/main.rs @@ -347,8 +347,7 @@ fn http_request(request: HttpRequest) -> HttpResponse { name = "verifyApiKey", hidden = true )] -async fn verify_api_key(api_key: (SupportedRpcProviderId, Option)) { - let (provider, api_key) = api_key; +async fn verify_api_key((provider, api_key): (SupportedRpcProviderId, Option)) { let api_key = api_key.map(|key| TryFrom::try_from(key).expect("Invalid API key")); if read_state(|state| state.get_api_key(&provider)) != api_key { panic!("API key does not match input") diff --git a/integration_tests/src/lib.rs b/integration_tests/src/lib.rs index e2a09227..1e3364e1 100644 --- a/integration_tests/src/lib.rs +++ b/integration_tests/src/lib.rs @@ -146,7 +146,6 @@ impl Setup { self } - // TODO XC-329: remove verifyApiKey endpoint pub async fn verify_api_key(&self, api_key: (SupportedRpcProviderId, Option)) { let runtime = self.new_pocket_ic_runtime(); runtime @@ -217,6 +216,10 @@ impl Setup { pub fn controller(&self) -> Principal { self.controller } + + pub fn sol_rpc_canister_id(&self) -> CanisterId { + self.sol_rpc_canister_id + } } async fn tick_until_http_request(env: &PocketIc) -> Vec { @@ -250,6 +253,12 @@ fn wallet_wasm() -> Vec { ic_test_utilities_load_wasm::load_wasm(PathBuf::new(), "wallet", &[]) } +impl AsRef for Setup { + fn as_ref(&self) -> &PocketIc { + &self.env + } +} + #[derive(Clone)] pub struct PocketIcRuntime<'a> { env: &'a PocketIc, diff --git a/integration_tests/tests/tests.rs b/integration_tests/tests/tests.rs index 89e05254..a0284f58 100644 --- a/integration_tests/tests/tests.rs +++ b/integration_tests/tests/tests.rs @@ -597,6 +597,8 @@ mod retrieve_logs_tests { mod update_api_key_tests { use super::*; + use candid::{encode_args, Principal}; + use pocket_ic::{ErrorCode, RejectCode, RejectResponse}; #[tokio::test] async fn should_update_api_key() { @@ -651,6 +653,36 @@ mod update_api_key_tests { )]) .await; } + + #[tokio::test] + async fn should_prevent_unauthorized_call_to_verify_api_key() { + let setup = Setup::new().await.with_mock_api_keys().await; + let args = (SupportedRpcProviderId::AlchemyMainnet, Some("test-key")); + + for unauthorized_principal in [Principal::anonymous(), DEFAULT_CALLER_TEST_ID] { + let result = setup + .as_ref() + .query_call( + setup.sol_rpc_canister_id(), + unauthorized_principal, + "verifyApiKey", + encode_args(args).unwrap(), + ) + .await; + + assert_eq!( + result, + Err(RejectResponse { + reject_code: RejectCode::CanisterReject, + reject_message: "You are not authorized".to_string(), + error_code: ErrorCode::CanisterRejectedMessage, + certified: false, + }) + ); + } + + setup.drop().await; + } } mod canister_upgrade_tests {