diff --git a/.cargo/audit.toml b/.cargo/audit.toml new file mode 100644 index 0000000..470cb17 --- /dev/null +++ b/.cargo/audit.toml @@ -0,0 +1,9 @@ +[advisories] +ignore = [ + # ignore this one since serde_cbor is unmaintained and is a + # core part of IC libraries + "RUSTSEC-2021-0127", + # ignore this one for now since rsa is only used internally via + # sqlx and should not be exposed to an external caller + "RUSTSEC-2023-0071", +] diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml new file mode 100644 index 0000000..26cf40c --- /dev/null +++ b/.github/workflows/security.yml @@ -0,0 +1,29 @@ +name: security + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +on: + push: + branches: ["main", "staging"] + paths: + - "**/Cargo.toml" + - "**/Cargo.lock" + - ".cargo/audit.toml" + workflow_dispatch: + +jobs: + audit: + runs-on: ubuntu-latest + steps: + - run: sudo apt install pkg-config + - uses: actions/checkout@v1 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + - uses: actions-rs/audit-check@v1.2.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/Cargo.toml b/Cargo.toml index e941a79..0feba94 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,12 +23,11 @@ async-std = "1.12.0" async-trait = "0.1" # Note: Need to leave ring at 0.16 for compatibility with ic-agent bincode = "1.3" -candid = { git = "https://github.com/dscvr-one/candid.git", rev = "0.9.3-3", features = [ - "parser", - "deepsize", -] } +candid = { git = "https://github.com/dscvr-one/candid.git", rev = "dscvr-2024-04-11-2" } +candid_parser = { git = "https://github.com/dscvr-one/candid.git", rev = "dscvr-2024-04-11-2" } convert_case = "0.6" -deepsize = { git = "https://github.com/dscvr-one/deepsize.git", rev = "0.2.0-candid-0.9.3-2", features = [ +deepsize = { git = "https://github.com/dscvr-one/deepsize.git", tag = "dscvr-2024-04-11-2", features = [ + "candid", "serde_bytes", "derive", "std", @@ -37,11 +36,11 @@ derive_more = "0.99" enum-iterator = "1.2.0" flate2 = "1.0" futures = "0.3.25" -ic-agent = { version = "0.25.0", features = ["pem"] } -ic-cdk = "0.10" +ic-agent = { version = "0.34.0", features = ["pem"] } +ic-cdk = "0.13" lazy_static = "1.4" num-traits = "0.2.15" -ring = "0.16" +ring = "0.17" rmp-serde = "1.1" rustc-hash = { version = "1.1" } serde = "1.0" @@ -57,4 +56,5 @@ tracing-stackdriver = "0.8" tracing-subscriber = { version = "0.3", features = ["env-filter"] } [patch.crates-io] -candid = { git = "https://github.com/dscvr-one/candid.git", rev = "0.9.3-3" } +candid = { git = "https://github.com/dscvr-one/candid.git", rev = "dscvr-2024-04-11-2" } +candid_parser = { git = "https://github.com/dscvr-one/candid.git", rev = "dscvr-2024-04-11-2" } diff --git a/crates/dscvr-candid-generator/Cargo.toml b/crates/dscvr-candid-generator/Cargo.toml index 04ad19c..a42e79a 100644 --- a/crates/dscvr-candid-generator/Cargo.toml +++ b/crates/dscvr-candid-generator/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [dependencies] candid.workspace = true +candid_parser.workspace = true convert_case.workspace = true prettyplease = "0.2" quote = "1.0" diff --git a/crates/dscvr-candid-generator/src/lib.rs b/crates/dscvr-candid-generator/src/lib.rs index 9caa462..2e098e7 100644 --- a/crates/dscvr-candid-generator/src/lib.rs +++ b/crates/dscvr-candid-generator/src/lib.rs @@ -3,3 +3,21 @@ pub mod rust_canister_agent; pub mod util; + +#[cfg(test)] +mod test { + use super::*; + use std::path::Path; + const DID: &str = "../../../canister-idls/society-rs/society-common.did"; + #[test] + #[ignore] + fn test_generate() { + let output_dir: std::path::PathBuf = Path::new("src").join("gen"); + std::fs::create_dir_all("src/gen").expect("create src/gen"); + let _ = rust_canister_agent::generate( + Path::new(DID), + &output_dir.join("dscvr_tx_log_agent.rs"), + ) + .expect("Something good to happen"); + } +} diff --git a/crates/dscvr-candid-generator/src/rust_canister_agent.rs b/crates/dscvr-candid-generator/src/rust_canister_agent.rs index 75e27e8..1ff3ac1 100644 --- a/crates/dscvr-candid-generator/src/rust_canister_agent.rs +++ b/crates/dscvr-candid-generator/src/rust_canister_agent.rs @@ -1,11 +1,6 @@ // Based on Dfinity's rust bindings generator: // https://github.com/dfinity/candid/blob/master/rust/candid/src/bindings/rust.rs -use candid::bindings::analysis::chase_actor; -use candid::bindings::analysis::infer_rec; -use candid::bindings::rust::TypePath; -use candid::parser::typing::CheckFileOptions; -use candid::parser::typing::CheckFileResult; use candid::types::Field; use candid::types::FuncMode; use candid::types::Function; @@ -13,9 +8,12 @@ use candid::types::Label; use candid::types::Type; use candid::types::TypeInner; use candid::TypeEnv; +use candid_parser::bindings::analysis::chase_actor; +use candid_parser::bindings::analysis::infer_rec; +use candid_parser::bindings::rust::TypePath; use convert_case::Case; use convert_case::Casing; -use instrumented_error::Result; +use instrumented_error::{IntoInstrumentedError, Result}; use quote::__private::TokenStream; use quote::format_ident; use quote::quote; @@ -448,21 +446,11 @@ fn generate_file(path: &Path, tokens: TokenStream) -> Result<()> { } #[tracing::instrument] -pub fn generate(did: &Path, output: &Path) -> Result> { - let CheckFileResult { - types, - actor, - imports, - } = candid::parser::typing::check_file_with_options( - did, - &CheckFileOptions { - pretty_errors: false, - combine_actors: true, - }, - )?; +pub fn generate(did: &Path, output: &Path) -> Result> { + let (types, actor, imports) = candid_parser::typing::check_file_with_imports(did)?; let (env, actor) = nominalize_all(&types, &actor); let def_list: Vec<_> = if let Some(actor) = &actor { - chase_actor(&env, actor).unwrap() + chase_actor(&env, actor).map_err(|err| format!("{err:?}").into_instrumented_error())? } else { env.0.iter().map(|pair| pair.0.as_ref()).collect() }; @@ -470,10 +458,12 @@ pub fn generate(did: &Path, output: &Path) -> Result> { let mut tokens = generate_types(&env, &def_list, &recs)?; if let Some(actor) = actor { - let serv = env.as_service(&actor).unwrap(); + let serv = env + .as_service(&actor) + .map_err(|err| format!("{err:?}").into_instrumented_error())?; serv.iter() .map(|(id, func)| { - let func = env.as_func(func).unwrap(); + let func = env.as_func(func).expect("valid function"); q_function(id, func) }) .for_each(|f| tokens.extend(f)); diff --git a/crates/dscvr-candid-generator/src/util.rs b/crates/dscvr-candid-generator/src/util.rs index 90ad054..6d30ee0 100644 --- a/crates/dscvr-candid-generator/src/util.rs +++ b/crates/dscvr-candid-generator/src/util.rs @@ -1,22 +1,16 @@ -use candid::parser::typing::{check_file_with_options, CheckFileOptions}; +use candid::pretty::candid::compile; +use candid_parser::check_file_with_imports; use instrumented_error::Result; -use std::collections::BTreeSet; use std::path::{Path, PathBuf}; /// Combines all imported candid files into a single file. #[tracing::instrument] -pub fn combine_candid_files(path: &Path, output_file: &str) -> Result> { +pub fn combine_candid_files(path: &Path, output_file: &str) -> Result> { let candid_path = Path::new(path); - let result = check_file_with_options( - candid_path, - &CheckFileOptions { - pretty_errors: false, - combine_actors: true, - }, - )?; + let result = check_file_with_imports(candid_path)?; // export the did to all defined networks - let contents = candid::bindings::candid::compile(&result.types, &result.actor); + let contents = compile(&result.0, &result.1); std::fs::write(output_file, contents)?; - Ok(result.imports) + Ok(result.2) } diff --git a/crates/dscvr-canister-agent/Cargo.toml b/crates/dscvr-canister-agent/Cargo.toml index 9037c65..601d24e 100644 --- a/crates/dscvr-canister-agent/Cargo.toml +++ b/crates/dscvr-canister-agent/Cargo.toml @@ -31,7 +31,7 @@ dscvr-canister-exports = { path = "../dscvr-canister-exports" } dscvr-interface = { path = "../dscvr-interface" } ic-canister-stable-storage = { path = "../ic-canister-stable-storage" } ic-identity-util = { path = "../ic-identity-util" } -ic-test-state-machine-client = "=3.0.0" +ic-test-state-machine-client = "=3.0.1" instrumented-error = { path = "../instrumented-error" } [build-dependencies] diff --git a/crates/dscvr-canister-agent/src/agent_impl/replica_impl.rs b/crates/dscvr-canister-agent/src/agent_impl/replica_impl.rs index a0c4148..469205c 100644 --- a/crates/dscvr-canister-agent/src/agent_impl/replica_impl.rs +++ b/crates/dscvr-canister-agent/src/agent_impl/replica_impl.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use std::time::Duration; use candid::Principal; -use ic_agent::agent::http_transport::ReqwestHttpReplicaV2Transport; +use ic_agent::agent::http_transport::reqwest_transport::ReqwestHttpReplicaV2Transport; use ic_agent::Agent; use ic_agent::Identity; use instrumented_error::IntoInstrumentedError; diff --git a/crates/dscvr-canister-agent/src/agent_impl/state_machine_impl.rs b/crates/dscvr-canister-agent/src/agent_impl/state_machine_impl.rs index 5bb1280..f3833c3 100644 --- a/crates/dscvr-canister-agent/src/agent_impl/state_machine_impl.rs +++ b/crates/dscvr-canister-agent/src/agent_impl/state_machine_impl.rs @@ -16,7 +16,7 @@ struct WrappedStateMachine { #[async_trait::async_trait] impl AgentImpl for WrappedStateMachine { async fn query(&self, canister_id: &Principal, method: &str, args: &[u8]) -> Result> { - let state_machine = self.machine.lock().unwrap(); + let state_machine = self.machine.lock().expect("lock failure"); match state_machine .query_call( canister_id.to_owned(), @@ -32,7 +32,7 @@ impl AgentImpl for WrappedStateMachine { } async fn update(&self, canister_id: &Principal, method: &str, args: &[u8]) -> Result> { - let state_machine = self.machine.lock().unwrap(); + let state_machine = self.machine.lock().expect("lock failure"); match state_machine .update_call( canister_id.to_owned(), @@ -75,12 +75,14 @@ pub fn new( ) -> Result<(Arc, Principal)> { // TODO: for multi-canister WrappedStateMachine needs to be a singleton let machine = Arc::new(Mutex::new(StateMachine::new( - &std::env::var("STATE_MACHINE_BINARY_PATH").expect("valid state machine binary path"), + &std::env::var("STATE_MACHINE_BINARY_PATH").map_err(|e| { + format!("missing valid state machine binary path: {e:?}").into_instrumented_error() + })?, false, ))); let canister_id = { - let machine = machine.lock().unwrap(); + let machine = machine.lock().expect("lock failure"); let canister_id = machine.create_canister(Some(caller)); machine.install_canister(canister_id, wasm, init_arguments, Some(caller)); canister_id diff --git a/crates/dscvr-canister-agent/src/lib.rs b/crates/dscvr-canister-agent/src/lib.rs index ce179d0..447ed1a 100644 --- a/crates/dscvr-canister-agent/src/lib.rs +++ b/crates/dscvr-canister-agent/src/lib.rs @@ -94,18 +94,6 @@ impl CanisterAgent { } } - pub async fn new_replica( - caller: Arc, - replica: &str, - canister_id: &str, - ) -> Result { - let agent = Self { - agent: agent_impl::replica_impl::new(caller, replica).await?, - canister_id: Principal::from_text(canister_id)?, - }; - Ok(agent) - } - pub async fn clone_with_identity(&self, identity: Arc) -> Result { Ok(Self { agent: self.agent.clone_with_identity(identity).await?, diff --git a/crates/dscvr-canister-agent/src/stable_storage_restore_backup.rs b/crates/dscvr-canister-agent/src/stable_storage_restore_backup.rs index 2acf6c6..b0cb678 100644 --- a/crates/dscvr-canister-agent/src/stable_storage_restore_backup.rs +++ b/crates/dscvr-canister-agent/src/stable_storage_restore_backup.rs @@ -213,8 +213,7 @@ impl CanisterAgent { &hash[0..5], time.format(format_description!( "[year]-[month]-[day]_[hour]-[minute]-[second]" - )) - .unwrap() + ))? )) } } diff --git a/crates/ic-ingress-validator-util/Cargo.toml b/crates/ic-ingress-validator-util/Cargo.toml index c9635cd..0a8aecc 100644 --- a/crates/ic-ingress-validator-util/Cargo.toml +++ b/crates/ic-ingress-validator-util/Cargo.toml @@ -7,8 +7,9 @@ edition = "2021" [dependencies] ic-agent.workspace = true -ic-crypto-utils-threshold-sig-der = { git = "https://github.com/dscvr-one/ic.git", rev = "cacda1", package = "ic-crypto-utils-threshold-sig-der" } -ic-validator-ingress-message = { git = "https://github.com/dscvr-one/ic.git", rev = "cacda1", package = "ic-validator-ingress-message" } +ic-crypto-utils-threshold-sig-der = { git = "https://github.com/dfinity/ic.git", rev = "release-2024-04-17_23-01-query-stats", package = "ic-crypto-utils-threshold-sig-der" } +ic-types = { git = "https://github.com/dfinity/ic.git", rev = "release-2024-04-17_23-01-query-stats", package = "ic-types" } +ic-validator-ingress-message = { git = "https://github.com/dfinity/ic.git", rev = "release-2024-04-17_23-01-query-stats", package = "ic-validator-ingress-message" } ic-identity-util = { path = "../ic-identity-util" } instrumented-error = { path = "../instrumented-error" } diff --git a/crates/ic-ingress-validator-util/src/lib.rs b/crates/ic-ingress-validator-util/src/lib.rs index e658097..f12474a 100644 --- a/crates/ic-ingress-validator-util/src/lib.rs +++ b/crates/ic-ingress-validator-util/src/lib.rs @@ -1,19 +1,24 @@ -use ic_agent::agent::http_transport::ReqwestHttpReplicaV2Transport; +use ic_agent::agent::http_transport::ReqwestTransport; use ic_agent::identity::AnonymousIdentity; use ic_agent::Agent; use ic_crypto_utils_threshold_sig_der::parse_threshold_sig_key_from_der; -use ic_validator_ingress_message::IngressMessageVerifier; +use ic_types::messages::UserQuery; +use ic_validator_ingress_message::{HttpRequestVerifier, IngressMessageVerifier}; use instrumented_error::Result; use std::sync::Arc; -pub async fn try_new_ingress_verifier(url: &str) -> Result { +pub type IcHttpRequestVerifier = Arc + Send + Sync>; + +pub async fn try_new_ingress_verifier(url: &str) -> Result { let agent: Agent = Agent::builder() - .with_transport(ReqwestHttpReplicaV2Transport::create(url)?) + .with_transport(ReqwestTransport::create(url)?) .with_arc_identity(Arc::new(AnonymousIdentity)) .build()?; agent.fetch_root_key().await?; let public_key = parse_threshold_sig_key_from_der(&agent.read_root_key())?; - Ok(IngressMessageVerifier::builder() - .with_root_of_trust(public_key) - .build()) + Ok(Arc::new( + IngressMessageVerifier::builder() + .with_root_of_trust(public_key) + .build(), + )) } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 6939a60..41d80b8 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "1.73.0" +channel = "1.77.2" components = ["rustfmt", "clippy"] targets = ["wasm32-unknown-unknown"]