From 17c664941f3a1cd7328cd415c8378f34a0e8ce13 Mon Sep 17 00:00:00 2001 From: Serhii Volovyk Date: Mon, 23 Oct 2023 14:46:05 +0300 Subject: [PATCH] new_acc load tests (#325) * new_acc load tests * sign logic added to load tests * short load scenarion updated * recovery pk set in session * fore load scenarios * remove unwraps * use tracing --- .gitignore | 1 + Cargo.lock | 14 +- load-tests/Cargo.toml | 10 ++ load-tests/README.md | 2 +- load-tests/src/constants.rs | 3 + load-tests/src/main.rs | 309 +++++++++++++++++++++++++++++++- load-tests/src/primitives.rs | 20 +++ load-tests/src/utils.rs | 62 +++++++ load-tests/test_plans/short.txt | 2 +- 9 files changed, 410 insertions(+), 13 deletions(-) create mode 100644 load-tests/src/constants.rs create mode 100644 load-tests/src/primitives.rs create mode 100644 load-tests/src/utils.rs diff --git a/.gitignore b/.gitignore index b00bc8dd7..6709739cf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /target .direnv .DS_Store +tmp diff --git a/Cargo.lock b/Cargo.lock index 055342012..88811c78a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2709,9 +2709,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" [[package]] name = "libloading" @@ -2751,10 +2751,20 @@ checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" name = "load-tests" version = "0.1.0" dependencies = [ + "chrono", "goose", "goose-eggs", + "jsonwebtoken", + "mpc-recovery", + "near-crypto 0.17.0", + "near-primitives 0.17.0", + "rand 0.8.5", "reqwest", + "serde", + "serde_json", "tokio", + "tracing", + "tracing-subscriber", ] [[package]] diff --git a/load-tests/Cargo.toml b/load-tests/Cargo.toml index cdf162b82..08a2fe376 100644 --- a/load-tests/Cargo.toml +++ b/load-tests/Cargo.toml @@ -8,3 +8,13 @@ goose = "^0.17" goose-eggs = "0.5.1" tokio = "^1.12" reqwest = "^0.11" +jsonwebtoken = "8.3.0" +near-primitives = "0.17.0" +serde = "1.0.130" +serde_json = "1.0.68" +chrono = "0.4.19" +near-crypto = "0.17.0" +mpc-recovery = { path = "../mpc-recovery" } +rand = "0.8.4" +tracing = "0.1" +tracing-subscriber = { version = "0.3", features = ["env-filter"] } diff --git a/load-tests/README.md b/load-tests/README.md index cde6af722..fd4e1f687 100644 --- a/load-tests/README.md +++ b/load-tests/README.md @@ -5,7 +5,7 @@ This directory contains load tests for the MPC Recovery service. It is build usi To run the tests, you need to have Rust installed. You can install Rust using [rustup](https://rustup.rs/). To start the tests, run the following command: ```bash -cargo run --release -- --host --report-file=load_test_results.html --test-plan "$(cat ./test_plans/short.txt)" +RUST_LOG=info cargo run --release -- --host --report-file=load_test_results.html --test-plan "$(cat ./test_plans/short.txt)" --scenarios simpleMpcPublicKey ``` You can run Load Tests against your local development environment (check `/integration-tests` for more info) or against the staging environment by setting the `--host` parameter. diff --git a/load-tests/src/constants.rs b/load-tests/src/constants.rs new file mode 100644 index 000000000..55c495dd6 --- /dev/null +++ b/load-tests/src/constants.rs @@ -0,0 +1,3 @@ +pub const VALID_OIDC_PROVIDER_KEY: &str = "-----BEGIN RSA PRIVATE KEY-----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-----END RSA PRIVATE KEY-----"; +pub const VALID_OIDC_AUD: &str = "test_audience"; +pub const VALID_OIDC_ISS: &str = "https://securetoken.google.com/test_audience"; diff --git a/load-tests/src/main.rs b/load-tests/src/main.rs index 2e12a8288..ad44303c1 100644 --- a/load-tests/src/main.rs +++ b/load-tests/src/main.rs @@ -1,14 +1,89 @@ -use std::time::Duration; +mod constants; +mod primitives; +pub mod utils; -use goose::prelude::*; -use goose_eggs::{validate_and_load_static_assets, Validate}; +use core::panic; use reqwest::{header::CONTENT_TYPE, Body}; +use std::{time::Duration, vec}; +use tracing_subscriber::{filter, prelude::*}; + +use constants::VALID_OIDC_PROVIDER_KEY; +use goose::prelude::*; +use mpc_recovery::{ + msg::{ + ClaimOidcRequest, MpcPkRequest, NewAccountRequest, SignRequest, UserCredentialsRequest, + UserCredentialsResponse, + }, + sign_node::oidc::OidcToken, + transaction::CreateAccountOptions, + utils::{ + claim_oidc_request_digest, sign_digest, sign_request_digest, + user_credentials_request_digest, + }, +}; +use near_crypto::SecretKey; +use near_primitives::{ + account::{AccessKey, AccessKeyPermission}, + borsh::BorshSerialize, + delegate_action::DelegateAction, + transaction::{Action, AddKeyAction}, + types::AccountId, +}; +use primitives::UserSession; +use rand::{distributions::Alphanumeric, Rng}; +use utils::build_send_and_check_request; #[tokio::main] async fn main() -> Result<(), GooseError> { + let stdout_log = tracing_subscriber::fmt::layer().pretty(); + + tracing_subscriber::registry() + .with(stdout_log.with_filter(filter::LevelFilter::INFO)) + .init(); + GooseAttack::initialize()? .register_scenario( - scenario!("simple_mpc_public_key").register_transaction(transaction!(mpc_public_key)), + scenario!("registration") + .register_transaction(transaction!(prepare_user_credentials).set_sequence(1)) + .register_transaction(transaction!(claim_oidc).set_sequence(2)) + .register_transaction(transaction!(new_account).set_sequence(3)), + ) + .register_scenario( + scenario!("registrationAndSign") + .register_transaction(transaction!(prepare_user_credentials).set_sequence(1)) + .register_transaction(transaction!(claim_oidc).set_sequence(2)) + .register_transaction(transaction!(new_account).set_sequence(3)) + .register_transaction(transaction!(user_credentials).set_sequence(4)) + .register_transaction( + transaction!(sign) + .set_sequence(5) + .set_weight(1000) // In this scenario we are mostly testing /sign functionality + .expect("Failed to set weight"), + ), + ) + .register_scenario( + scenario!("simpleClaimOidc") + .register_transaction(transaction!(prepare_user_credentials).set_sequence(1)) + .register_transaction( + transaction!(claim_oidc) + .set_sequence(2) + .set_weight(100) + .expect("Failed to set weight"), + ), + ) + .register_scenario( + scenario!("simpleUserCredentials") + .register_transaction(transaction!(prepare_user_credentials).set_sequence(1)) + .register_transaction(transaction!(claim_oidc).set_sequence(2)) + .register_transaction( + transaction!(user_credentials) + .set_sequence(3) + .set_weight(100) + .expect("Failed to set weight"), + ), + ) + .register_scenario( + scenario!("simpleMpcPublicKey").register_transaction(transaction!(mpc_public_key)), ) .execute() .await?; @@ -16,10 +91,75 @@ async fn main() -> Result<(), GooseError> { Ok(()) } -async fn mpc_public_key(user: &mut GooseUser) -> TransactionResult { +async fn prepare_user_credentials(user: &mut GooseUser) -> TransactionResult { + tracing::info!("prepare_user_credentials"); + // Generate 2 key pairs + let fa_sk = SecretKey::from_random(near_crypto::KeyType::ED25519); + let la_sk = SecretKey::from_random(near_crypto::KeyType::ED25519); + + // Create JWT with random sub (usually done by OIDC Provider) + let oidc_token = OidcToken::new(&utils::create_jwt_token( + VALID_OIDC_PROVIDER_KEY, + constants::VALID_OIDC_AUD, + constants::VALID_OIDC_ISS, + None, + )); + + // Generate random near account id + let account_id_rand: String = rand::thread_rng() + .sample_iter(&Alphanumeric) + .take(10) + .map(char::from) + .collect(); + + let near_account_id: AccountId = format!("acc-{}.near", account_id_rand.to_lowercase()) + .try_into() + .expect("Failed to generate random account Id"); + + let session = UserSession { + jwt_token: oidc_token, + near_account_id, + fa_sk, + la_sk, + recovery_pk: None, + }; + + user.set_session_data(session); + + Ok(()) +} + +async fn user_credentials(user: &mut GooseUser) -> TransactionResult { + tracing::info!("user_credentials"); + let sesion = user + .get_session_data::() + .expect("Session Data must be set"); + + let oidc_token = sesion.jwt_token.clone(); + let fa_sk = sesion.fa_sk.clone(); + let fa_pk = fa_sk.public_key(); + let la_sk = sesion.la_sk.clone(); + let near_account_id = sesion.near_account_id.clone(); + + let user_credentials_request_digest = + user_credentials_request_digest(&oidc_token, &fa_pk).expect("Failed to create digest"); + + let user_credentials_frp_signature = + sign_digest(&user_credentials_request_digest, &fa_sk).expect("Failed to sign digest"); + + let user_credentials_request = UserCredentialsRequest { + oidc_token: oidc_token.clone(), + frp_public_key: fa_pk, + frp_signature: user_credentials_frp_signature, + }; + + let body_json = + serde_json::to_string(&user_credentials_request).expect("json serialization failed"); + + let body = Body::from(body_json.to_owned()); let request_builder = user - .get_request_builder(&GooseMethod::Post, "mpc_public_key")? - .body(Body::from("{}")) + .get_request_builder(&GooseMethod::Post, "user_credentials")? + .body(body) .header(CONTENT_TYPE, "application/json") .timeout(Duration::from_secs(10)); @@ -29,8 +169,159 @@ async fn mpc_public_key(user: &mut GooseUser) -> TransactionResult { let goose_responce = user.request(goose_request).await?; - let validate = &Validate::builder().status(200).build(); - validate_and_load_static_assets(user, goose_responce, validate).await?; + let response = goose_responce.response.expect("Expected response ... ."); + + let user_credentials_response = response + .json::() + .await + .expect("Failed to parse user credentials response"); + + if let UserCredentialsResponse::Ok { recovery_pk } = user_credentials_response { + tracing::info!("UserCredentialsResponce has Ok, setting session data"); + let session = UserSession { + jwt_token: oidc_token, + near_account_id, + fa_sk, + la_sk, + recovery_pk: Some(recovery_pk), + }; + user.set_session_data(session); + } else { + panic!( + "UserCredentialsResponce has Error: {:?}", + user_credentials_response + ); + } Ok(()) } + +async fn mpc_public_key(user: &mut GooseUser) -> TransactionResult { + tracing::info!("mpc_public_key"); + let body_json = serde_json::to_string(&MpcPkRequest {}).expect("json serialization failed"); + build_send_and_check_request(user, "mpc_public_key", &body_json).await +} + +async fn claim_oidc(user: &mut GooseUser) -> TransactionResult { + tracing::info!("claim_oidc"); + let sesion = user + .get_session_data::() + .expect("Session Data must be set"); + let oidc_token_hash = sesion.jwt_token.digest_hash(); + let frp_secret_key = sesion.fa_sk.clone(); + let frp_public_key = frp_secret_key.public_key(); + + let request_digest = claim_oidc_request_digest(&oidc_token_hash, &frp_public_key) + .expect("Failed to create digest"); + let frp_signature = + sign_digest(&request_digest, &frp_secret_key).expect("Failed to sign digest"); + + let claim_oidc_request = ClaimOidcRequest { + oidc_token_hash: oidc_token_hash.to_owned(), + frp_public_key, + frp_signature, + }; + + let body_json = serde_json::to_string(&claim_oidc_request).expect("json serialization failed"); + + build_send_and_check_request(user, "claim_oidc", &body_json).await +} + +async fn new_account(user: &mut GooseUser) -> TransactionResult { + let sesion = user + .get_session_data::() + .expect("Session Data must be set"); + let oidc_token = sesion.jwt_token.clone(); + let fa_secret_key = sesion.fa_sk.clone(); + let fa_public_key = fa_secret_key.public_key(); + let user_account_id = sesion.near_account_id.clone(); + + let create_account_options = CreateAccountOptions { + full_access_keys: Some(vec![fa_public_key.clone()]), + limited_access_keys: None, + contract_bytes: None, + }; + + let user_credentials_request_digest = + user_credentials_request_digest(&oidc_token, &fa_public_key) + .expect("Failed to create digest"); + + let user_credentials_frp_signature = + sign_digest(&user_credentials_request_digest, &fa_secret_key) + .expect("Failed to sign digest"); + + let new_account_request = NewAccountRequest { + near_account_id: user_account_id, + create_account_options, + oidc_token: sesion.jwt_token.clone(), + user_credentials_frp_signature, + frp_public_key: fa_public_key, + }; + + let body_json = serde_json::to_string(&new_account_request).expect("json serialization failed"); + build_send_and_check_request(user, "new_account", &body_json).await +} + +async fn sign(user: &mut GooseUser) -> TransactionResult { + tracing::info!("sign"); + let session = user + .get_session_data::() + .expect("Session Data must be set"); + let oidc_token = session.jwt_token.clone(); + let fa_secret_key = session.fa_sk.clone(); + let fa_public_key = fa_secret_key.public_key(); + let account_id = session.near_account_id.clone(); + let recovery_pk = session + .recovery_pk + .clone() + .expect("Recovery PK must be set before calling /sign"); + + let new_secret_key = SecretKey::from_random(near_crypto::KeyType::ED25519); + let new_public_key = new_secret_key.public_key(); + + let nonce = 0; // Set real nonce in case transaction is entend to be executed + let block_height = 0; // Set real block height in case transaction is entend to be executed + + let add_key_delegate_action = DelegateAction { + sender_id: account_id.clone(), + receiver_id: account_id.clone(), + actions: vec![Action::AddKey(AddKeyAction { + public_key: new_public_key.clone(), + access_key: AccessKey { + nonce: 0, + permission: AccessKeyPermission::FullAccess, + }, + }) + .try_into() + .unwrap()], + nonce, + max_block_height: block_height + 100, + public_key: recovery_pk, + }; + + let sign_request_digest = + sign_request_digest(&add_key_delegate_action, &oidc_token, &fa_public_key) + .expect("Failed to create digest"); + let sign_request_frp_signature = + sign_digest(&sign_request_digest, &fa_secret_key).expect("Failed to sign digest"); + + let user_credentials_request_digest = + user_credentials_request_digest(&oidc_token, &fa_public_key) + .expect("Failed to create digest"); + let user_credentials_frp_signature = + sign_digest(&user_credentials_request_digest, &fa_secret_key) + .expect("Failed to sign digest"); + + let sign_request = SignRequest { + delegate_action: add_key_delegate_action + .try_to_vec() + .expect("Failed to serialize delegate action"), + oidc_token, + frp_signature: sign_request_frp_signature, + user_credentials_frp_signature, + frp_public_key: fa_public_key, + }; + + let body_json = serde_json::to_string(&sign_request).expect("json serialization failed"); + build_send_and_check_request(user, "sign", &body_json).await +} diff --git a/load-tests/src/primitives.rs b/load-tests/src/primitives.rs new file mode 100644 index 000000000..638863a3b --- /dev/null +++ b/load-tests/src/primitives.rs @@ -0,0 +1,20 @@ +use mpc_recovery::sign_node::oidc::OidcToken; +use near_crypto::{PublicKey, SecretKey}; +use near_primitives::types::AccountId; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct IdTokenClaims { + pub iss: String, + pub sub: String, + pub aud: String, + pub exp: usize, +} + +pub struct UserSession { + pub jwt_token: OidcToken, + pub near_account_id: AccountId, + pub fa_sk: SecretKey, + pub la_sk: SecretKey, + pub recovery_pk: Option, +} diff --git a/load-tests/src/utils.rs b/load-tests/src/utils.rs new file mode 100644 index 000000000..917059913 --- /dev/null +++ b/load-tests/src/utils.rs @@ -0,0 +1,62 @@ +use chrono::Utc; +use goose::prelude::{GooseMethod, GooseRequest, GooseUser, TransactionResult}; +use goose_eggs::{validate_and_load_static_assets, Validate}; +use jsonwebtoken::{encode, Algorithm, EncodingKey, Header}; +use near_primitives::utils::generate_random_string; +use reqwest::{header::CONTENT_TYPE, Body}; +use std::time::Duration; + +use crate::primitives::IdTokenClaims; + +// TODO: try using existing function +pub fn create_jwt_token( + secret_rsa_pem_key: &str, + aud: &str, + iss: &str, + sub: Option<&str>, +) -> String { + let rnd_sub = generate_random_string(10); + let sub = sub.unwrap_or_else(|| &rnd_sub); + + let my_claims = IdTokenClaims { + iss: iss.to_owned(), + sub: sub.to_owned(), + aud: aud.to_owned(), + exp: (Utc::now() + chrono::Duration::hours(1)).timestamp() as usize, + }; + + let private_key_der = secret_rsa_pem_key.as_bytes().to_vec(); + + let token = encode( + &Header::new(Algorithm::RS256), + &my_claims, + &EncodingKey::from_rsa_pem(&private_key_der).unwrap(), + ) + .expect("Failed to encode jwt token"); + + token.to_string() +} + +pub async fn build_send_and_check_request( + user: &mut GooseUser, + path: &str, + body_json: &str, +) -> TransactionResult { + let body = Body::from(body_json.to_owned()); + let request_builder = user + .get_request_builder(&GooseMethod::Post, path)? + .body(body) + .header(CONTENT_TYPE, "application/json") + .timeout(Duration::from_secs(10)); + + let goose_request = GooseRequest::builder() + .set_request_builder(request_builder) + .build(); + + let goose_responce = user.request(goose_request).await?; + + let validate = &Validate::builder().status(200).build(); + validate_and_load_static_assets(user, goose_responce, validate).await?; + + Ok(()) +} diff --git a/load-tests/test_plans/short.txt b/load-tests/test_plans/short.txt index 3563b0f88..a2c87bb25 100644 --- a/load-tests/test_plans/short.txt +++ b/load-tests/test_plans/short.txt @@ -1 +1 @@ -10,2s;20,5s;0,0s \ No newline at end of file +0,0s;100,20s;0,0s \ No newline at end of file