From 352a744b502442b7db5d369b679ae16f96fa5494 Mon Sep 17 00:00:00 2001 From: Shubham Singh Date: Thu, 5 Sep 2024 17:42:37 +0530 Subject: [PATCH] feat(test): introduced tests --- core/.gitignore | 2 +- core/Cargo.lock | 137 + core/Cargo.toml | 9 +- core/src/commands/utils.rs | 5 +- core/src/main.rs | 2 + core/src/trust_stores/nss_profile.rs | 4 +- core/src/utils.rs | 31 +- core/src/utils_tests.rs | 81 + core/tarpaulin-report.html | 10424 +++++++++++++++++++++++++ 9 files changed, 10683 insertions(+), 12 deletions(-) create mode 100644 core/src/utils_tests.rs create mode 100644 core/tarpaulin-report.html diff --git a/core/.gitignore b/core/.gitignore index ea8c4bf..c41cc9e 100644 --- a/core/.gitignore +++ b/core/.gitignore @@ -1 +1 @@ -/target +/target \ No newline at end of file diff --git a/core/Cargo.lock b/core/Cargo.lock index 66291a8..f00fb54 100644 --- a/core/Cargo.lock +++ b/core/Cargo.lock @@ -51,12 +51,27 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + [[package]] name = "bitflags" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "cc" version = "1.1.15" @@ -128,6 +143,35 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "cpufeatures" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + [[package]] name = "dirs" version = "5.0.1" @@ -149,6 +193,22 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + [[package]] name = "foreign-types" version = "0.3.2" @@ -164,6 +224,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -209,6 +279,12 @@ dependencies = [ "libc", ] +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + [[package]] name = "once_cell" version = "1.19.0" @@ -294,6 +370,30 @@ dependencies = [ "thiserror", ] +[[package]] +name = "rustix" +version = "0.38.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "shlex" version = "1.3.0" @@ -317,6 +417,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tempfile" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + [[package]] name = "thiserror" version = "1.0.63" @@ -337,6 +450,12 @@ dependencies = [ "syn", ] +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + [[package]] name = "unicode-ident" version = "1.0.12" @@ -353,11 +472,14 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" name = "vanish" version = "0.1.2" dependencies = [ + "base64", "clap", "colored", "dirs", "lazy_static", "openssl", + "sha2", + "tempfile", ] [[package]] @@ -366,6 +488,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -390,6 +518,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-targets" version = "0.48.5" diff --git a/core/Cargo.toml b/core/Cargo.toml index 3c96ed5..f924eba 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -10,11 +10,14 @@ categories = ["development-tools", "command-line-utilities", "parsing", "os", "h keywords = ["https", "certificates", "localhost", "local-development", "root-ca"] readme = "README.md" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] openssl = "0.10" clap = { version = "4.4.8", features = ["derive"] } dirs = "5.0" +sha2 = "0.10" lazy_static = "1.4" -colored = "2.0" \ No newline at end of file +colored = "2.0" +base64 = "0.21" + +[dev-dependencies] +tempfile = "3.3" \ No newline at end of file diff --git a/core/src/commands/utils.rs b/core/src/commands/utils.rs index a385111..d5a535a 100644 --- a/core/src/commands/utils.rs +++ b/core/src/commands/utils.rs @@ -2,8 +2,7 @@ use crate::{ trust_stores::{ firefox::FirefoxTrustStore, nss::NSSValue, nss_profile::NSSProfile, utils::check_if_firefox_exists, CAValue, - }, - x509::{ca_req::CAReq, distinguished_name::DistinguishedName, leaf_cert::LeafCert}, + }, utils::get_unique_hash, x509::{ca_req::CAReq, distinguished_name::DistinguishedName, leaf_cert::LeafCert} }; use colored::*; use openssl::{ @@ -20,8 +19,8 @@ pub fn generate_install(cert: X509) -> Result<(), Box> { let ca_value_object: CAValue = CAValue { certificate: cert }; ca_value_object.install_certificate()?; let nss_profile_object: NSSProfile = NSSProfile::new(); - let ca_unique_name: String = "vanish-root-test-123456-shubham-brr".to_string(); let caroot: String = "/home/jerry/.local/share/vanish/ca_cert.pem".to_string(); + let ca_unique_name: String = get_unique_hash(&caroot)?; let mkcert: NSSValue = NSSValue::new(nss_profile_object, ca_unique_name.clone(), caroot.clone()); let success: bool = mkcert.install_nss(); diff --git a/core/src/main.rs b/core/src/main.rs index 9c56f4b..065dec6 100644 --- a/core/src/main.rs +++ b/core/src/main.rs @@ -6,6 +6,8 @@ mod x509; use clap::{Parser, Subcommand}; use commands::generate::generate; use std::env; +#[cfg(test)] +mod utils_tests; #[derive(Parser)] #[clap( diff --git a/core/src/trust_stores/nss_profile.rs b/core/src/trust_stores/nss_profile.rs index 0933c9a..620af81 100644 --- a/core/src/trust_stores/nss_profile.rs +++ b/core/src/trust_stores/nss_profile.rs @@ -2,7 +2,7 @@ use std::path::{Path, PathBuf}; use std::process::Command; pub struct NSSProfile { - pub has_nss: bool, + pub _has_nss: bool, pub has_certutil: bool, pub certutil_path: Option, pub nss_dbs: Vec, @@ -60,7 +60,7 @@ impl NSSProfile { } Self { - has_nss, + _has_nss: has_nss, has_certutil, certutil_path, nss_dbs, diff --git a/core/src/utils.rs b/core/src/utils.rs index 7fc34d9..dbf5309 100644 --- a/core/src/utils.rs +++ b/core/src/utils.rs @@ -2,6 +2,8 @@ use crate::{ errors::{CertKeyPairError, CertKeyResult, SerialNumberError, SerialNumberResult}, x509::{self, ca_cert::CACert}, }; +use base64::engine::general_purpose::URL_SAFE; +use base64::Engine; use colored::*; use openssl::{ asn1::Asn1Integer, @@ -9,9 +11,16 @@ use openssl::{ error::ErrorStack, pkey::{PKey, Private}, rsa::Rsa, + sha::Sha256, x509::X509, }; -use std::{error, fs, io, path::Path, process::Output}; +use std::{ + error, + fs::{self, File}, + io::{self, Read}, + path::Path, + process::Output, +}; use std::{path::PathBuf, process::Command}; pub fn generate_cert_key_pair() -> CertKeyResult<(Rsa, PKey)> { @@ -149,13 +158,29 @@ pub fn save_generated_cert_key_files( } } -pub fn _path_exists(path: &str) -> bool { +#[allow(dead_code)] +pub fn path_exists(path: &str) -> bool { Path::new(path).exists() } -pub fn _binary_exists(binary: &str) -> bool { +#[allow(dead_code)] +pub fn binary_exists(binary: &str) -> bool { Command::new(binary) .output() .map(|output: Output| output.status.success()) .unwrap_or(false) } + +#[allow(dead_code)] +pub fn get_unique_hash(csr_path: &str) -> Result { + let mut file: File = File::open(csr_path)?; + let mut csr_contents: Vec = Vec::new(); + file.read_to_end(&mut csr_contents)?; + let mut hasher: Sha256 = Sha256::new(); + hasher.update(&csr_contents); + let result: [u8; 32] = hasher.finish(); + let mut unique_name: String = URL_SAFE.encode(result); + unique_name = unique_name.trim_end_matches('=').to_string(); + + Ok(unique_name) +} diff --git a/core/src/utils_tests.rs b/core/src/utils_tests.rs new file mode 100644 index 0000000..402f25e --- /dev/null +++ b/core/src/utils_tests.rs @@ -0,0 +1,81 @@ +mod get_unique_hash { + use crate::utils::get_unique_hash; + use std::io::Write; + use tempfile::NamedTempFile; + + const CSR_DATA: &[u8; 954] = b"-----BEGIN CERTIFICATE REQUEST-----\n +MIICfTCCAWUCAQAwETEPMA0GA1UECgwGVmFuaXNoMIIBIjANBgkqhkiG9w0BAQEF\n +AAOCAQ8AMIIBCgKCAQEAu6yXUMzVfqCBGOJh50MziGFKShMWQt7iIYe2pAeFBoeo\n +uuwuVq4xSdqpgTFvkhekH8tpTX8n+Y8pY7rur6Nosi/G2A6AxvvwG/ahDuHYg9Il\n +XmTYrqKnK32n/8ALPT6W3J6wKq6Nm2y5yXhGX/fSVSrmNw78hl0osKLUa7dLmCs0\n +zBghTfwjSz+qkUXvwEKuGPqgXLh6hirjiNhbtbR1XgV3p/w/7u3qH7fJcDlrhQDW\n +QhJnxcdYGCMGGcIzEdGaNzTHNAlpU7lLR2FTEjk7OCYwDgzLFYy6QFdeK2swdkfn\n +OlipnXQfzFUEbTKDQUckLafodJBzLhqyKCulDPxqoQIDAQABoCcwJQYJKoZIhvcN\n +AQkOMRgwFjAUBgNVHREEDTALgglsb2NhbGhvc3QwDQYJKoZIhvcNAQELBQADggEB\n +ACwI/gFmKb5oAahbq2LlnkGtAwmbV67xgxTmXXUIvJs37cz4Rde/CdSDct5g7mYh\n +8EghzWLEfHmg9K9kMiV58HHYIkcQ421v+pPub3wDVU3yvq3/DpIqHDBs/Wz3nFrI\n +GZEfI1cwUTqTkK9Lk2z3waUkt8adk4pvof01tiEq9A06GjK5tJfUIGef4lkOfzKE\n +ld7i9gqfMk+9pmSjBYVG0YCfc0ye/oPhmSNtFc9dTlBb9bqcN3C0dgqdhM3E/4Gz\n +YBni+0GjtUKZT9NsekFh/O14P6j9MrtbHsMLWU6KXgHc+t75kD+XKy2U/IPd8nzt\n +ncq6d7m7pfbZs5a+gBnsPqA=\n +-----END CERTIFICATE REQUEST-----"; + + #[test] + fn returns_ok() { + let mut temp_file: NamedTempFile = NamedTempFile::new().unwrap(); + temp_file.write_all(CSR_DATA).unwrap(); + let csr_path: &str = temp_file.path().to_str().unwrap(); + + let hash_result: Result = get_unique_hash(csr_path); + assert!(hash_result.is_ok(), "Expected Ok result, got an error"); + } + + #[test] + fn hash_length() { + let mut temp_file: NamedTempFile = NamedTempFile::new().unwrap(); + temp_file.write_all(CSR_DATA).unwrap(); + let csr_path: &str = temp_file.path().to_str().unwrap(); + + let unique_hash: String = get_unique_hash(csr_path).unwrap(); + assert_eq!(unique_hash.len(), 43, "Expected hash length of 43"); + } + + #[test] + fn consistent() { + let mut temp_file: NamedTempFile = NamedTempFile::new().unwrap(); + temp_file.write_all(CSR_DATA).unwrap(); + let csr_path: &str = temp_file.path().to_str().unwrap(); + + let hash1: String = get_unique_hash(csr_path).unwrap(); + let hash2: String = get_unique_hash(csr_path).unwrap(); + assert_eq!(hash1, hash2, "Hashes for the same file should be equal"); + } +} + +mod serial_number { + use crate::utils::generate_certificate_serial_number; + + #[test] + fn returns_ok() { + let result: Result = + generate_certificate_serial_number(); + assert!(result.is_ok(), "Expected Ok result"); + } + + #[test] + fn is_valid() { + let result: Result = + generate_certificate_serial_number(); + let asn1_integer: openssl::asn1::Asn1Integer = result.unwrap(); + let serial_bytes: Vec = asn1_integer.to_bn().unwrap().to_vec(); + assert!(!serial_bytes.is_empty(), "ASN1 Integer should not be empty"); + + let is_negative: bool = asn1_integer.to_bn().unwrap().is_negative(); + assert!(!is_negative, "ASN1 Integer should not be negative"); + + assert!( + serial_bytes.len() <= 16, + "ASN1 Integer should fit within 128 bits (16 bytes)" + ); + } +} diff --git a/core/tarpaulin-report.html b/core/tarpaulin-report.html new file mode 100644 index 0000000..7e619a9 --- /dev/null +++ b/core/tarpaulin-report.html @@ -0,0 +1,10424 @@ + + + + + + + +
+ + + + + +