diff --git a/Cargo.toml b/Cargo.toml index 5c97c0b..43ea90c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -108,8 +108,9 @@ intaglio = { version = "1.6", optional = true } [features] strict = [] #traceability = ["tracing-subscriber", "tokio/rt-multi-thread", "intaglio"] -irrefutable_audit = [] compressed_store = [] +merkle_audit = [] +az_audit = [] [[bin]] name = "graymamba" diff --git a/README.md b/README.md index 386846e..14aa860 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ ### Features (determines what is built into the binary) - Mandatory Backing Store, choose one of [ `rocksdb` | `redis` ]: Enables RocksDB or Redis as backing store for data shares (one of the two options must be chosen) -- Optional `irrefutable_audit`: Enables irrefutable audit logs for files and directories. (if not specified then no audit logs are created) +- Mandatory irrefutable_audit, choose one of [ `merkle_audit` | `az_audit` ]: Enables irrefutable audit logs for files and directories. Merkle audit writes to a merkle tree in a RocksDB, AZ_Audit writes to ALeph Zero custom blockchain. - Optional `compressed_store`: Enables compressed shares (if not specified then works uncompresed with reduced performance but greater traceability RocksDB is built-in to the filesystem if chosen. If Redis is the store of choice, then it will need to be installed and running on the machine. @@ -30,23 +30,23 @@ RocksDB is built-in to the filesystem if chosen. If Redis is the store of choice - `To run or test the filesystem`: 🚀 - cargo build --bin graymamba --features="irrefutable_audit,compressed_store,rocksdb" --release - cargo run --bin graymamba --features="irrefutable_audit,compressed_store,rocksdb" --release - cargo test --features irrefutable_audit -- --nocapture + cargo build --bin graymamba --features="merkle_audit,compressed_store,rocksdb" --release + cargo run --bin graymamba --features="merkle_audit,compressed_store,rocksdb" --release + cargo test --features merkle_audit -- --nocapture - `To build and run the audit_reader, qrocks, and data-room` (see below for more details on these binaries): 🚀 - cargo run --bin audit_reader --features="irrefutable_audit" --release - cargo run --bin qrocks --features="irrefutable_audit" --release - cargo run --bin data-room --features="irrefutable_audit" --release + cargo run --bin audit_reader --release (this is only for use with the merkle audit option currently) + cargo run --bin qrocks --release + cargo run --bin data-room --release - `To run the Linter` : 🚀 - cargo clippy --features="irrefutable_audit,compressed_store" + cargo clippy --features="merkle_audit,compressed_store" - `To run bench marking` : 🚀 - cargo bench --features="irrefutable_audit,compressed_store" + cargo bench --features="merkle_audit,compressed_store" ## Explanation of the project's binaries and their purpose diff --git a/src/audit_adapters/mod.rs b/src/audit_adapters/mod.rs index f2fdb12..c71a17a 100644 --- a/src/audit_adapters/mod.rs +++ b/src/audit_adapters/mod.rs @@ -4,5 +4,4 @@ pub mod merkle_tree; //pub mod substrate_based_audit; pub mod poseidon_hash; pub mod snark_proof; -#[cfg(feature = "irrefutable_audit")] pub mod irrefutable_audit; \ No newline at end of file diff --git a/src/bin/audit_reader/main.rs b/src/bin/audit_reader/main.rs index 0b40844..6270542 100644 --- a/src/bin/audit_reader/main.rs +++ b/src/bin/audit_reader/main.rs @@ -25,7 +25,6 @@ use std::collections::HashMap; use config::{Config, File as ConfigFile}; -#[cfg(feature = "irrefutable_audit")] use graymamba::audit_adapters::merkle_tree::MerkleNode; use graymamba::audit_adapters::irrefutable_audit::AuditEvent; diff --git a/src/bin/graymamba/build.rs b/src/bin/graymamba/build.rs new file mode 100644 index 0000000..b87107e --- /dev/null +++ b/src/bin/graymamba/build.rs @@ -0,0 +1,11 @@ +fn main() { + // Check if exactly one audit feature is enabled + let merkle_enabled = std::env::var("CARGO_FEATURE_MERKLE_AUDIT").is_ok(); + let az_enabled = std::env::var("CARGO_FEATURE_AZ_AUDIT").is_ok(); + + match (merkle_enabled, az_enabled) { + (false, false) => panic!("Either 'merkle_audit' or 'az_audit' feature must be enabled"), + (true, true) => panic!("Only one audit feature can be enabled at a time"), + _ => {} // Exactly one feature is enabled, which is what we want + } +} \ No newline at end of file diff --git a/src/bin/graymamba/main.rs b/src/bin/graymamba/main.rs index 309ccda..bae7efc 100644 --- a/src/bin/graymamba/main.rs +++ b/src/bin/graymamba/main.rs @@ -2,12 +2,12 @@ use std::sync::Arc; use graymamba::kernel::protocol::tcp::{NFSTcp, NFSTcpListener}; use graymamba::sharesfs::SharesFS; -#[cfg(feature = "irrefutable_audit")] +use graymamba::audit_adapters::irrefutable_audit::IrrefutableAudit; +#[cfg(feature = "merkle_audit")] use graymamba::audit_adapters::merkle_audit::MerkleBasedAuditSystem; -//use graymamba::audit_adapters::audit_system::AuditSystem; //simple template example -//use graymamba::audit_adapters::substrate_audit::SubstrateAuditSystem; //code rescued with aleph-zero prototype but not compiled and tested -#[cfg(feature = "irrefutable_audit")] -use graymamba::audit_adapters::irrefutable_audit::IrrefutableAudit; + +#[cfg(feature = "az_audit")] +use graymamba::audit_adapters::substrate_audit::SubstrateAuditSystem; use config::{Config, File as ConfigFile}; @@ -61,9 +61,6 @@ async fn main() { // Print enabled features println!("Enabled features:"); - if cfg!(feature = "irrefutable_audit") { - println!(" - irrefutable_audit"); - } SharesFS::set_namespace_id_and_community(settings.get_str("storage.namespace_id").unwrap().as_str(), settings.get_str("storage.community").unwrap().as_str()).await; @@ -78,22 +75,39 @@ async fn main() { ).expect("Failed to create a data store")); - #[cfg(feature = "irrefutable_audit")] - let audit_system = match MerkleBasedAuditSystem::new().await { - Ok(audit) => { - println!("✅ Irrefutable audit initialisation successful"); - Some(Arc::new(audit) as Arc) - }, - - Err(e) => { - eprintln!("❌ Fatal Error: {}", e); - std::process::exit(1); + let audit_system: Arc = { + #[cfg(feature = "merkle_audit")] + { + match MerkleBasedAuditSystem::new().await { + Ok(audit) => { + println!("✅ Merkle-based audit initialization successful"); + Arc::new(audit) + }, + Err(e) => { + eprintln!("❌ Fatal Error: {}", e); + std::process::exit(1); + } + } } + + #[cfg(feature = "az_audit")] + { + match SubstrateAuditSystem::new().await { + Ok(audit) => { + println!("✅ Aleph Zero audit initialization successful"); + Arc::new(audit) + }, + Err(e) => { + eprintln!("❌ Fatal Error: {}", e); + std::process::exit(1); + } + } + } + + #[cfg(not(any(feature = "merkle_audit", feature = "az_audit")))] + compile_error!("Either 'merkle_audit' or 'az_audit' feature must be enabled"); }; - #[cfg(not(feature = "irrefutable_audit"))] - let audit_system = None; - let shares_fs = SharesFS::new(data_store, audit_system.clone()); let shares_fs_clone = shares_fs.clone(); tokio::spawn(async move { @@ -122,10 +136,7 @@ async fn main() { } // Perform cleanup - #[cfg(feature = "irrefutable_audit")] - if let Some(audit) = audit_system { - std::io::stdout().flush().unwrap(); - audit.shutdown().unwrap(); - } + std::io::stdout().flush().unwrap(); + audit_system.shutdown().unwrap(); } diff --git a/src/kernel/vfs/api.rs b/src/kernel/vfs/api.rs index 6d4dfd6..4ed6aae 100644 --- a/src/kernel/vfs/api.rs +++ b/src/kernel/vfs/api.rs @@ -8,7 +8,7 @@ use std::time::SystemTime; use crate::backingstore::data_store::DataStore; use graymamba::sharesfs::SharesFS; -use tracing::debug; + #[derive(Default, Debug)] pub struct DirEntry { pub fileid: fileid3, diff --git a/src/lib.rs b/src/lib.rs index 7e7ea68..5e712f7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,5 +14,5 @@ pub mod secret_sharing; pub mod backingstore; pub mod nfsclient; -#[cfg(feature = "irrefutable_audit")] + pub mod audit_adapters; \ No newline at end of file diff --git a/src/sharesfs/mod.rs b/src/sharesfs/mod.rs index 0d8db73..243bf5e 100644 --- a/src/sharesfs/mod.rs +++ b/src/sharesfs/mod.rs @@ -49,15 +49,13 @@ use base64::{Engine as _, engine::general_purpose::STANDARD}; use crate::secret_sharing::SecretSharingService; -#[cfg(feature = "irrefutable_audit")] use crate::audit_adapters::irrefutable_audit::{AuditEvent, IrrefutableAudit}; -#[cfg(feature = "irrefutable_audit")] use crate::audit_adapters::irrefutable_audit::event_types::{REASSEMBLED}; #[derive(Clone)] pub struct SharesFS { pub data_store: Arc, - pub irrefutable_audit: Option>, // Add NFSModule wrapped in Arc + pub irrefutable_audit: Arc, // Add NFSModule wrapped in Arc pub active_writes: Arc>>, pub commit_semaphore: Arc, pub secret_sharing: Arc, @@ -109,7 +107,7 @@ impl SharesFS { Ok(()) } - pub fn new(data_store: Arc, irrefutable_audit: Option>) -> SharesFS { + pub fn new(data_store: Arc, irrefutable_audit: Arc) -> SharesFS { let active_writes = Arc::new(Mutex::new(HashMap::new())); let commit_semaphore = Arc::new(Semaphore::new(10)); let secret_sharing = Arc::new(SecretSharingService::new().expect("Failed to initialize SecretSharingService")); @@ -567,16 +565,15 @@ impl NFSFileSystem for SharesFS { user = parts[1]; } - if let Some(irrefutable_audit) = &self.irrefutable_audit { - let event = AuditEvent { - creation_time: creation_time.clone(), - event_type: REASSEMBLED.to_string(), - file_path: path.clone(), - event_key: user.to_string(), - }; - if let Err(e) = irrefutable_audit.trigger_event(event).await { - warn!("Failed to trigger audit event: {}", e); - } + debug!("Triggering disassembled event"); + let event = AuditEvent { + creation_time: creation_time.clone(), + event_type: REASSEMBLED.to_string(), + file_path: path.clone(), + event_key: user.to_string(), + }; + if let Err(e) = self.irrefutable_audit.trigger_event(event).await { + warn!("Failed to trigger audit event: {}", e); } Ok((data_slice.to_vec(), eof)) diff --git a/src/sharesfs/writing.rs b/src/sharesfs/writing.rs index 1e5371e..be1bbe8 100644 --- a/src/sharesfs/writing.rs +++ b/src/sharesfs/writing.rs @@ -3,10 +3,10 @@ use tokio::time::Instant; use tracing::{debug, warn}; use crate::kernel::api::nfs::{fattr3, fileid3, nfsstat3}; -#[cfg(feature = "irrefutable_audit")] + use crate::audit_adapters::irrefutable_audit::AuditEvent; -#[cfg(feature = "irrefutable_audit")] use crate::audit_adapters::irrefutable_audit::event_types::DISASSEMBLED; + use crate::graymamba::file_metadata::FileMetadata; use super::{SharesFS, ActiveWrite}; @@ -78,17 +78,15 @@ impl SharesFS { user = parts[1]; } - if let Some(irrefutable_audit) = &self.irrefutable_audit { - debug!("Triggering disassembled event"); - let event = AuditEvent { - creation_time: creation_time.clone(), - event_type: DISASSEMBLED.to_string(), - file_path: path.clone(), - event_key: user.to_string(), - }; - if let Err(e) = irrefutable_audit.trigger_event(event).await { - warn!("Failed to trigger audit event: {}", e); - } + debug!("Triggering disassembled event"); + let event = AuditEvent { + creation_time: creation_time.clone(), + event_type: DISASSEMBLED.to_string(), + file_path: path.clone(), + event_key: user.to_string(), + }; + if let Err(e) = self.irrefutable_audit.trigger_event(event).await { + warn!("Failed to trigger audit event: {}", e); } let metadata = self.get_metadata_from_id(id).await?;