From 3726108561a226edf86b805be7f7b41a3c12ccdc Mon Sep 17 00:00:00 2001 From: Shubham Singh Date: Thu, 5 Sep 2024 02:18:31 +0530 Subject: [PATCH 1/4] feat(logs): completed certificates --- core/Cargo.lock | 11 +++ core/Cargo.toml | 3 +- core/src/commands/generate.rs | 31 +++++++- core/src/commands/utils.rs | 7 +- core/src/errors.rs | 29 +++++-- core/src/main.rs | 6 +- core/src/trust_stores/errors.rs | 35 +++++++-- core/src/trust_stores/firefox.rs | 6 +- core/src/trust_stores/linux.rs | 7 +- core/src/trust_stores/nss.rs | 13 ++-- core/src/utils.rs | 21 ++++-- core/src/x509/errors.rs | 125 +++++++++++++++++++++++++------ 12 files changed, 230 insertions(+), 64 deletions(-) diff --git a/core/Cargo.lock b/core/Cargo.lock index f6bbdb6..66291a8 100644 --- a/core/Cargo.lock +++ b/core/Cargo.lock @@ -118,6 +118,16 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +[[package]] +name = "colored" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" +dependencies = [ + "lazy_static", + "windows-sys 0.48.0", +] + [[package]] name = "dirs" version = "5.0.1" @@ -344,6 +354,7 @@ name = "vanish" version = "0.1.2" dependencies = [ "clap", + "colored", "dirs", "lazy_static", "openssl", diff --git a/core/Cargo.toml b/core/Cargo.toml index a8a9623..3c96ed5 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -16,4 +16,5 @@ readme = "README.md" openssl = "0.10" clap = { version = "4.4.8", features = ["derive"] } dirs = "5.0" -lazy_static = "1.4" \ No newline at end of file +lazy_static = "1.4" +colored = "2.0" \ No newline at end of file diff --git a/core/src/commands/generate.rs b/core/src/commands/generate.rs index 2d95356..60eb337 100644 --- a/core/src/commands/generate.rs +++ b/core/src/commands/generate.rs @@ -9,11 +9,15 @@ use crate::{ Certificate, }, }; +use colored::*; use openssl::{ pkey::{PKey, Private}, x509::{X509Req, X509}, }; -use std::error; +use std::{ + error::{self, Error}, + path::PathBuf, +}; pub fn generate( domains: Vec, @@ -29,13 +33,31 @@ pub fn generate( install: bool, ) -> Result<(), Box> { if request { + println!(); + println!("Generated Certificate Requests for :"); for domain in &domains { let distinguished_name: DistinguishedName = create_distinguished_name(&commonname, &country, &state); let (ca_req_certificate, private_key) = CAReq::new(distinguished_name)?.generate_certificate()?; - save_csr_certificate(domain.to_string(), &output, ca_req_certificate, private_key)?; + let is_saved: Result> = + save_csr_certificate(domain.to_string(), &output, ca_req_certificate, private_key); + match is_saved { + Ok(path) => { + println!(" - \"{}\" ✅", domain); + println!(); + println!( + "{}: Your request certs and their corresponding keys are saved at: {:?}", + "Note".green(), + path + ); + } + Err(_err) => { + println!(" - \"{}\" ❌", domain); + } + } } + println!(); return Ok(()); } @@ -77,9 +99,11 @@ pub fn generate( } } if install {} + println!(); return Ok(()); } else { - eprintln!("Corresponding KeyFile Not Found"); + eprintln!("{}: Corresponding KeyFile Not Found", "Error".red()); + println!(); std::process::exit(1); } } @@ -166,5 +190,6 @@ pub fn generate( generate_install(created_cert)?; } } + println!(); Ok(()) } diff --git a/core/src/commands/utils.rs b/core/src/commands/utils.rs index 3af1d49..61bba3e 100644 --- a/core/src/commands/utils.rs +++ b/core/src/commands/utils.rs @@ -36,7 +36,7 @@ pub fn generate_install(cert: X509) -> Result<(), Box> { ); } if success { - println!("Certificate installed successfully."); + println!("Certificate installed successfully 👍"); } else { eprintln!("Failed to install the certificate."); } @@ -133,7 +133,7 @@ pub fn save_csr_certificate( output: &Option, ca_req_certificate: X509Req, private_key: PKey, -) -> Result<(), Box> { +) -> Result> { if let Some(output) = &output { let output_path: &Path = Path::new(output); if !output_path.exists() { @@ -158,6 +158,7 @@ pub fn save_csr_certificate( } else { eprintln!("Error: Error creating file for key : {}", name); } + return Ok(output_path); } else { let output_path: PathBuf = std::env::current_dir()?; let file_name: PathBuf = output_path.join(format!("csr-{}.pem", name)); @@ -174,8 +175,8 @@ pub fn save_csr_certificate( } else { eprintln!("Error: Error creating file for key : {}", name); } + Ok(output_path) } - Ok(()) } pub fn create_distinguished_name( diff --git a/core/src/errors.rs b/core/src/errors.rs index ed44b19..c6784b5 100644 --- a/core/src/errors.rs +++ b/core/src/errors.rs @@ -1,7 +1,7 @@ +use colored::*; use core::fmt; use openssl::error::ErrorStack; use std::error::Error; - pub type CertKeyResult = Result; pub type SerialNumberResult = Result; @@ -14,9 +14,16 @@ pub enum CertKeyPairError { impl fmt::Display for CertKeyPairError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Self::PKeyCreationError(err) => write!(f, "Error Creating Key File : {}", err), + Self::PKeyCreationError(err) => { + write!(f, "{}: Creating Key File : {}", "Error".red(), err) + } Self::RSAGenerationError(err) => { - write!(f, "Error Generating Certificate File : {}", err) + write!( + f, + "{}: Generating Certificate File : {}", + "Error".red(), + err + ) } } } @@ -35,13 +42,23 @@ impl fmt::Display for SerialNumberError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::BigNumberInitializationError(err) => { - write!(f, "Error Initializing Big Number : {}", err) + write!(f, "{}: Initializing Big Number : {}", "Error".red(), err) } Self::RandomBigNumberGenerationError(err) => { - write!(f, "Error creating a Random Big Number : {}", err) + write!( + f, + "{}: creating a Random Big Number : {}", + "Error".red(), + err + ) } Self::ConvertBigNumberToASN1Error(err) => { - write!(f, "Error Converting Big Number to ASN1Integer: {}", err) + write!( + f, + "{}: Converting Big Number to ASN1Integer: {}", + "Error".red(), + err + ) } } } diff --git a/core/src/main.rs b/core/src/main.rs index 051386f..9c56f4b 100644 --- a/core/src/main.rs +++ b/core/src/main.rs @@ -94,20 +94,20 @@ fn main() { ); std::process::exit(1); } - + if !domains.is_empty() && csr.is_some() { eprintln!("Error: `-d` (domains) and `--csr` cannot be used together."); std::process::exit(1); } if request && csr.is_some() { - eprint!("Error: `--req-only` and `csr` are incompatible. You can't generate requests from a request certificate."); + eprintln!("Error: `--req-only` and `csr` are incompatible. You can't generate requests from a request certificate."); std::process::exit(1); } if request && install { //CORRECT THIS - eprint!("Error: `--req-only` and `install` are incompatible. You can't generate requests from a request certificate."); + eprintln!("Error: `--req-only` and `install` are incompatible. You can't generate requests from a request certificate."); std::process::exit(1); } diff --git a/core/src/trust_stores/errors.rs b/core/src/trust_stores/errors.rs index 85d97fd..de9ea26 100644 --- a/core/src/trust_stores/errors.rs +++ b/core/src/trust_stores/errors.rs @@ -1,3 +1,4 @@ +use colored::*; use openssl::error::ErrorStack; use std::{env::VarError, error::Error, fmt, io}; @@ -12,13 +13,28 @@ impl fmt::Display for TrustStoreError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::PEMEncodingError(err) => { - write!(f, "Trust Store PEM Encoding Failed: {}", err) + write!( + f, + "{}: Trust Store PEM Encoding Failed: {}", + "Error".red(), + err + ) } Self::PEMFileCreationError(err) => { - write!(f, "Trust Store PEM File creation Failed: {}", err) + write!( + f, + "{}: Trust Store PEM File creation Failed: {}", + "Error".red(), + err + ) } Self::WriteToFileError(err) => { - write!(f, "Trust Store Writing to PEM file: {}", err) + write!( + f, + "{}: Trust Store Writing to PEM file: {}", + "Error".red(), + err + ) } } } @@ -38,12 +54,19 @@ impl fmt::Display for FirefoxTrustStoreError { Self::ENVVariableNotFound(err, variable) => { write!( f, - "Error getting Environment varibale {} : {}", - variable, err + "{}: getting Environment varibale {} : {}", + "Error".red(), + variable, + err ) } Self::IOError(err) => { - write!(f, "Error reading the default firefox directoryL {}", err) + write!( + f, + "{}: reading the default firefox directoryL {}", + "Error".red(), + err + ) } } } diff --git a/core/src/trust_stores/firefox.rs b/core/src/trust_stores/firefox.rs index 7552ef6..2c87895 100644 --- a/core/src/trust_stores/firefox.rs +++ b/core/src/trust_stores/firefox.rs @@ -1,5 +1,5 @@ use super::errors::FirefoxTrustStoreError; -use std::process::exit; +use std::process::{exit, Stdio}; use std::{ env, fs, io, path::{Path, PathBuf}, @@ -82,12 +82,9 @@ impl FirefoxTrustStore { pub fn find_cert_directories(&self) -> Result, FirefoxTrustStoreError> { let mut cert_dirs: Vec = Vec::new(); - println!("Firefox Profiles: {:?}", &self.firefox_profile); for profile_dir in &self.firefox_profile { let path: &Path = Path::new(profile_dir); - println!("{:?} exists: {:?}", &path, &path.exists()); if path.exists() && path.is_dir() { - println!("Path is a dir: {:?}", &path); for entry in fs::read_dir(path) .map_err(|err: io::Error| FirefoxTrustStoreError::IOError(err))? { @@ -127,6 +124,7 @@ impl FirefoxTrustStore { .arg(&self.ca_unique_name) .arg("-i") .arg(&self.vanish_ca_path) + .stdout(Stdio::null()) .status(); match cmd_result { diff --git a/core/src/trust_stores/linux.rs b/core/src/trust_stores/linux.rs index 0204e41..6f0577e 100644 --- a/core/src/trust_stores/linux.rs +++ b/core/src/trust_stores/linux.rs @@ -1,3 +1,4 @@ +use colored::*; use openssl::error::ErrorStack; use openssl::x509::X509; use std::fs; @@ -35,7 +36,7 @@ impl CAValue { match store { Some(store) => { let path: String = store.get_path(); - println!("Adding file to trust store: {}", path); + println!("{}: Adding file to trust store: {}", "Note".green(), path); let pem_path: PathBuf = Path::new(&path).join("vanish-root.crt"); if let Err(err) = fs::create_dir_all(&path) { @@ -45,7 +46,7 @@ impl CAValue { match CAValue::save_cert(&self.certificate, pem_path.to_str().unwrap()) { Ok(_) => println!("Certificate saved at: {}", pem_path.display()), - Err(err) => eprintln!("Failed to save certificate: {}", err), + Err(err) => eprintln!("{}", err), } } None => { @@ -85,4 +86,4 @@ impl PossibleStores { PossibleStores::Other => "/usr/share/pki/trust/anchors/".to_string(), } } -} \ No newline at end of file +} diff --git a/core/src/trust_stores/nss.rs b/core/src/trust_stores/nss.rs index 4ee0008..95c7bbc 100644 --- a/core/src/trust_stores/nss.rs +++ b/core/src/trust_stores/nss.rs @@ -1,8 +1,9 @@ use crate::trust_stores::nss_profile::NSSProfile; +use colored::*; use std::{ fs, io, path::Path, - process::{Command, ExitStatus}, + process::{Command, ExitStatus, Stdio}, }; pub struct NSSValue { @@ -28,7 +29,6 @@ impl NSSValue { let mut success: bool = true; if self.for_each_nss_profile(|profile: &str| { - println!("{:?}", self.profile.certutil_path); let cmd: Result = Command::new(self.profile.certutil_path.as_ref().unwrap()) .arg("-V") @@ -38,6 +38,7 @@ impl NSSValue { .arg("L") .arg("-n") .arg(&self.ca_unique_name) + .stdout(Stdio::null()) .status(); if cmd.is_err() || !cmd.unwrap().success() { @@ -64,6 +65,7 @@ impl NSSValue { .arg(&self.ca_unique_name) .arg("-i") .arg(&self.caroot) + .stdout(Stdio::null()) .status(); if let Err(err) = cmd { @@ -71,7 +73,7 @@ impl NSSValue { } }) == 0 { - eprintln!("ERROR: no NSS security databases found"); + eprintln!("{}: No NSS security databases found", "Error".red()); return false; } @@ -94,6 +96,7 @@ impl NSSValue { .arg(profile) .arg("-n") .arg(&self.ca_unique_name) + .stdout(Stdio::null()) .status(); if let Err(err) = cmd { @@ -107,9 +110,7 @@ impl NSSValue { F: FnMut(&str), { let mut found: usize = 0; - let profiles = &self.profile.nss_dbs; - - println!("{:?}", profiles); + let profiles: &Vec = &self.profile.nss_dbs; for profile in profiles { let stat: Result = Path::new(profile).metadata(); diff --git a/core/src/utils.rs b/core/src/utils.rs index f519e68..46ffd3c 100644 --- a/core/src/utils.rs +++ b/core/src/utils.rs @@ -2,6 +2,7 @@ use crate::{ errors::{CertKeyPairError, CertKeyResult, SerialNumberError, SerialNumberResult}, x509::{self, ca_cert::CACert}, }; +use colored::*; use openssl::{ asn1::Asn1Integer, bn::BigNum, @@ -36,7 +37,11 @@ pub fn get_certificates_from_data_dir() -> Option<(X509, PKey)> { if let Some(ref data_dir) = *x509::DATA_DIR { if !data_dir.exists() { if let Err(err) = fs::create_dir_all(data_dir) { - eprintln!("Failed to create data directory: {}", err); + eprintln!( + "{}: Failed to create data directory: {}", + "Error".red(), + err + ); return None; } } @@ -46,7 +51,10 @@ pub fn get_certificates_from_data_dir() -> Option<(X509, PKey)> { let ca_cert_file_str: &str = match ca_certfile.to_str() { Some(s) => s, None => { - eprintln!("Failed to convert ca_certfile path to string"); + eprintln!( + "{}: Failed to convert ca_certfile path to string", + "Error".red() + ); return None; } }; @@ -54,7 +62,10 @@ pub fn get_certificates_from_data_dir() -> Option<(X509, PKey)> { let ca_key_file_str: &str = match ca_keyfile.to_str() { Some(s) => s, None => { - eprintln!("Failed to convert ca_keyfile path to string"); + eprintln!( + "{}: Failed to convert ca_keyfile path to string", + "Error".red() + ); return None; } }; @@ -62,12 +73,12 @@ pub fn get_certificates_from_data_dir() -> Option<(X509, PKey)> { match CACert::load_ca_cert(ca_cert_file_str, ca_key_file_str) { Ok((cert, pkey)) => Some((cert, pkey)), Err(_err) => { - eprintln!("Warning: Generating new certificates"); + eprintln!("{}: Generating new certificates", "Warning".yellow()); None } } } else { - eprintln!("Unable to get Data Directory"); + eprintln!("{}: Unable to get Data Directory", "Error".red()); None } } diff --git a/core/src/x509/errors.rs b/core/src/x509/errors.rs index 49b9456..48a0c8a 100644 --- a/core/src/x509/errors.rs +++ b/core/src/x509/errors.rs @@ -1,4 +1,5 @@ use crate::errors::{CertKeyPairError, SerialNumberError}; +use colored::*; use core::fmt; use openssl::error::ErrorStack; use std::{error::Error, io}; @@ -35,94 +36,170 @@ impl fmt::Display for X509Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::CertificateStackPushError(err) => { - write!(f, "Failed to push item to stack: {}", err) + write!( + f, + "{}: Failed to push item to stack: {}", + "Error".red(), + err + ) } Self::CertificateStackInitializationError(err) => { - write!(f, "Failed to initialize extension stack: {}", err) + write!( + f, + "{}: Failed to initialize extension stack: {}", + "Error".red(), + err + ) } Self::InitCARequestCertKeyPairError(err) => { write!( f, - "Failed to initialize Certificate Signing Request : {}", + "{}: Failed to initialize Certificate Signing Request : {}", + "Error".red(), err ) } Self::X509NameBuilderInitializeError(err) => { - write!(f, "Failed to initialize Name Builder: {}", err) + write!( + f, + "{}: Failed to initialize Name Builder: {}", + "Error".red(), + err + ) } Self::X509NameBuilderEntryError(err, entry, value) => { write!( f, - "Error adding entry {} in name builder with value {} : {}", - entry, value, err + "{}: Adding entry {} in name builder with value {} : {}", + "Error".red(), + entry, + value, + err ) } Self::X509CertificateBuilderInitializeError(err) => { - write!(f, "Failed to initialize Certificate Builder: {}", err) + write!( + f, + "{}: Failed to initialize Certificate Builder: {}", + "Error".red(), + err + ) } Self::X509CertificateBuilerEntryError(err, entry) => { write!( f, - "Error adding entry {} in Certificate builder : {}", - entry, err + "{}: adding entry {} in Certificate builder : {}", + "Error".red(), + entry, + err ) } Self::X509CSRToPEMError(err) => { - write!(f, "Error Converting Certificate to PEM : {}", err) + write!( + f, + "{}: Converting Certificate to PEM : {}", + "Error".red(), + err + ) } Self::X509PEMFileCreationError(err) => { - write!(f, "Error creating PEM file at specified location: {}", err) + write!( + f, + "{}: creating PEM file at specified location: {}", + "Error".red(), + err + ) } Self::X509WriteToFileError(err) => { - write!(f, "Error writing to specified PEM file: {}", err) + write!( + f, + "{}: writing to specified PEM file: {}", + "Error".red(), + err + ) } Self::InitSerialNumberGenerationError(err) => { - write!(f, "Error Generating Random Serial Number -> {}", err) + write!( + f, + "{}: Generating Random Serial Number -> {}", + "Error".red(), + err + ) } Self::GenerateNotBeforeError(err) => { - write!(f, "Error Generating Not Before Time: {}", err) + write!(f, "{}: Generating Not Before Time: {}", "Error".red(), err) } Self::GenerateNotAfterError(err) => { - write!(f, "Error Generating Not After Time: {}", err) + write!(f, "{}: Generating Not After Time: {}", "Error".red(), err) } Self::BasicConstraintsInitializeError(err) => { write!( f, - "Error Initializing Basic Constrainsts for Certificate: {}", + "{}: Initializing Basic Constrainsts for Certificate: {}", + "Error".red(), err ) } Self::ErrorGettingPublicKeyFromCSR(err) => { - write!(f, "Error getting Public Key From CSR: {}", err) + write!(f, "{}: getting Public Key From CSR: {}", "Error".red(), err) } Self::KeyUsageBuildError(err) => { - write!(f, "Error building Key Usage for Certificate: {}", err) + write!( + f, + "{}: building Key Usage for Certificate: {}", + "Error".red(), + err + ) } Self::ExtendedKeyUsageBuildError(err) => { write!( f, - "Error building Extended Key Usage for Certificate: {}", + "{}: building Extended Key Usage for Certificate: {}", + "Error".red(), err ) } Self::ErrorReadingCertFile(err, path) => { - writeln!(f, "Error Reading Cert File at Path {} : {}", path, err) + writeln!( + f, + "{}: Reading Cert File at Path {} : {}", + "Error".red(), + path, + err + ) } Self::ErrorConvertingFileToData(err, path) => { - writeln!(f, "Error Converting file {} to desired data: {}", path, err) + writeln!( + f, + "{}: Converting file {} to desired data: {}", + "Error".red(), + path, + err + ) } Self::PKCS8EncodingError(err) => { - writeln!(f, "Failed to encode generated key to PKCS8 Format: {}", err) + writeln!( + f, + "{}: Failed to encode generated key to PKCS8 Format: {}", + "Error".red(), + err + ) } Self::PEMEncodingError(err) => { writeln!( f, - "Failed to encode generated certificate to PEM Format: {}", + "{}: Failed to encode generated certificate to PEM Format: {}", + "Error".red(), err ) } Self::SANCouldNotBuildError(err) => { - write!(f, "Error building Subject Alternative Name : {}", err) + write!( + f, + "{}: building Subject Alternative Name : {}", + "Error".red(), + err + ) } } } From bb1b1e8578ca0edbc4d609149f3b625af71eb538 Mon Sep 17 00:00:00 2001 From: Shubham Singh Date: Thu, 5 Sep 2024 04:24:27 +0530 Subject: [PATCH 2/4] feat(logs): added better logs --- core/src/commands/generate.rs | 97 ++++++++++++++++++++++++++++++----- core/src/commands/utils.rs | 47 +++++++++++++++-- core/src/utils.rs | 2 +- core/src/x509/ca_cert.rs | 45 +++++++++++----- core/src/x509/ca_req.rs | 40 +++++++++++---- 5 files changed, 190 insertions(+), 41 deletions(-) diff --git a/core/src/commands/generate.rs b/core/src/commands/generate.rs index 60eb337..130dfcb 100644 --- a/core/src/commands/generate.rs +++ b/core/src/commands/generate.rs @@ -32,8 +32,8 @@ pub fn generate( request: bool, install: bool, ) -> Result<(), Box> { + println!(); if request { - println!(); println!("Generated Certificate Requests for :"); for domain in &domains { let distinguished_name: DistinguishedName = @@ -63,40 +63,98 @@ pub fn generate( if let Some(certfile) = certfile { if let Some(keyfile) = keyfile { - let (cert, pkey) = CACert::load_ca_cert(&certfile, &keyfile)?; + let (cert, pkey) = match CACert::load_ca_cert(&certfile, &keyfile) { + Ok(cert_pkey) => cert_pkey, + Err(err) => { + eprintln!("{}", err); + std::process::exit(1); + } + }; if let Some(csr) = &csr { let distinguished_name: DistinguishedName = create_distinguished_name(&commonname, &country, &state); - let csr_object: X509Req = CAReq::read_csr_from_file(csr)?; + let csr_object: X509Req = match CAReq::read_csr_from_file(csr) { + Ok(csr) => csr, + Err(err) => { + eprintln!("{}", err); + std::process::exit(1); + } + }; let leaf_cert_object: LeafCert = LeafCert::new(distinguished_name)?; - let (leaf_certificate, _private_key) = LeafCert::generate_certificate( + println!(); + let (leaf_certificate, _private_key) = match LeafCert::generate_certificate( leaf_cert_object, &cert, &pkey, Some(&csr_object), - )?; - save_pem_certificate("csr_cert.pem".to_string(), output, leaf_certificate)?; + ) { + Ok((a, b)) => { + println!("Generating Certificate for Signing Request Successful! 👍"); + (a, b) + } + Err(err) => { + println!("Generating Certificate for Signing Request Failed! 👎"); + eprintln!("{}", err); + std::process::exit(1); + } + }; + match save_pem_certificate("csr_cert.pem".to_string(), output, leaf_certificate) { + Ok(()) => {} + Err(err) => { + println!("{}", err); + std::process::exit(1); + } + }; } else { + println!(); + println!("Generated Certificate for : "); for domain in &domains { let distinguished_name: DistinguishedName = create_distinguished_name(&commonname, &country, &state); let leaf_cert_object: LeafCert = LeafCert::new(distinguished_name)?; - let (leaf_certificate, private_key) = - LeafCert::generate_certificate(leaf_cert_object, &cert, &pkey, None)?; + let (leaf_certificate, private_key) = match LeafCert::generate_certificate( + leaf_cert_object, + &cert, + &pkey, + None, + ) { + Ok((a, b)) => { + println!(" - \"{}\" ✅", domain); + (a, b) + } + Err(err) => { + println!(" - \"{}\" ❌", domain); + eprintln!("{}", err); + std::process::exit(1); + } + }; if let Some(private_key) = private_key { - save_pem_key_pair( + match save_pem_key_pair( &output, leaf_certificate, domain.to_string(), private_key, - )?; + ) { + Ok(()) => {} + Err(err) => { + println!("{}", err); + } + }; } else { eprintln!( - "Oops! We lost your private key for domain {}. Please try again!", - domain + "{}{}{}", + "Oops! We lost your private key for domain ".yellow(), + domain.yellow(), + ". Please try again!".yellow() ) } } + println!(); + println!( + "{}: All Successful Certificates and their corresponding keys are saved at : {}", + "Note".green(), + output.unwrap() + ); } if install {} println!(); @@ -115,12 +173,23 @@ pub fn generate( create_distinguished_name(&commonname, &country, &state); let csr_object: X509Req = CAReq::read_csr_from_file(csr)?; let leaf_cert_object: LeafCert = LeafCert::new(distinguished_name)?; - let (leaf_certificate, _private_key) = LeafCert::generate_certificate( + println!(); + let (leaf_certificate, _private_key) = match LeafCert::generate_certificate( leaf_cert_object, &d_cert, &d_pkey, Some(&csr_object), - )?; + ) { + Ok((a, b)) => { + println!("Generating Certificate for Signing Request Successful! 👍"); + (a, b) + } + Err(err) => { + println!("Generating Certificate for Signing Request Failed! 👎"); + eprintln!("{}", err); + std::process::exit(1); + } + }; save_pem_certificate("csr_cert.pem".to_string(), output, leaf_certificate)?; } else { for domain in &domains { diff --git a/core/src/commands/utils.rs b/core/src/commands/utils.rs index 61bba3e..a385111 100644 --- a/core/src/commands/utils.rs +++ b/core/src/commands/utils.rs @@ -5,6 +5,7 @@ use crate::{ }, x509::{ca_req::CAReq, distinguished_name::DistinguishedName, leaf_cert::LeafCert}, }; +use colored::*; use openssl::{ pkey::{PKey, Private}, x509::{X509Req, X509}, @@ -61,18 +62,56 @@ pub fn save_pem_certificate( let file_name: PathBuf = output_path.join(name); let file_name_str: Option<&str> = file_name.to_str(); if let Some(file_name_str) = file_name_str { - LeafCert::save_cert(&leaf_certificate, file_name_str)?; + match LeafCert::save_cert(&leaf_certificate, file_name_str) { + Ok(()) => { + println!(); + println!( + "{}: Your local certificate from request is saved at: {:?}", + "Note".green(), + file_name + ); + println!( + "{}: You may use the Private Key of the Certificate Provided as the Private Key of your Local Certificate.", + "Note".green() + ); + } + Err(err) => { + eprintln!("{}", err); + } + }; } else { - eprintln!("Error: Error creating file for generated Certificate :"); + eprintln!( + "{}: Error creating file for Generated Certificate :", + "Error".red() + ); } } else { let output_path: PathBuf = std::env::current_dir()?; let file_name: PathBuf = output_path.join("csr_cert.pem"); let file_name_str: Option<&str> = file_name.to_str(); if let Some(file_name_str) = file_name_str { - LeafCert::save_cert(&leaf_certificate, file_name_str)?; + match LeafCert::save_cert(&leaf_certificate, file_name_str) { + Ok(()) => { + println!(); + println!( + "{}: Your local certificate from request is saved at: {:?}", + "Note".green(), + file_name + ); + println!( + "{}: You may use the Private Key of the Certificate Provided as the Private Key of your Local Certificate.", + "Note".green() + ); + } + Err(err) => { + eprintln!("{}", err); + } + }; } else { - eprintln!("Error: Error creating file for generated Certificate"); + eprintln!( + "{}: Error creating file for Generated Certificate", + "Error".red() + ); } } Ok(()) diff --git a/core/src/utils.rs b/core/src/utils.rs index 46ffd3c..85a056f 100644 --- a/core/src/utils.rs +++ b/core/src/utils.rs @@ -73,7 +73,7 @@ pub fn get_certificates_from_data_dir() -> Option<(X509, PKey)> { match CACert::load_ca_cert(ca_cert_file_str, ca_key_file_str) { Ok((cert, pkey)) => Some((cert, pkey)), Err(_err) => { - eprintln!("{}: Generating new certificates", "Warning".yellow()); + eprintln!("{}: Generating new certificates ", "Warning".yellow()); None } } diff --git a/core/src/x509/ca_cert.rs b/core/src/x509/ca_cert.rs index 2c4de7e..bb6a34c 100644 --- a/core/src/x509/ca_cert.rs +++ b/core/src/x509/ca_cert.rs @@ -112,19 +112,40 @@ impl Certificate for CACert { impl CACert { pub fn load_ca_cert(cert_path: &str, key_path: &str) -> X509Result<(X509, PKey)> { - let cert: X509 = X509::from_pem(&std::fs::read(cert_path).map_err(|err: io::Error| { - X509Error::ErrorReadingCertFile(err, cert_path.to_string()) - })?) - .map_err(|err: ErrorStack| { - X509Error::ErrorConvertingFileToData(err, cert_path.to_string()) - })?; - let key: PKey = - PKey::private_key_from_pem(&std::fs::read(key_path).map_err(|err: io::Error| { + let cert: X509 = + match X509::from_pem(&std::fs::read(cert_path).map_err(|err: io::Error| { X509Error::ErrorReadingCertFile(err, cert_path.to_string()) - })?) - .map_err(|err: ErrorStack| { - X509Error::ErrorConvertingFileToData(err, key_path.to_string()) - })?; + })?) { + Ok(certificate) => { + println!("Reading Certificate at {} ✅", cert_path); + certificate + } + Err(err) => { + println!("Reading Certificate at {} ❌", cert_path); + return Err(X509Error::ErrorConvertingFileToData( + err, + cert_path.to_string(), + )); + } + }; + + let key: PKey = + match PKey::private_key_from_pem(&std::fs::read(key_path).map_err( + |err: io::Error| X509Error::ErrorReadingCertFile(err, key_path.to_string()), + )?) { + Ok(key) => { + println!("Reading Key at {} ✅", key_path); + key + }, + Err(err) => { + println!("Reading Key at {} ❌", key_path); + return Err(X509Error::ErrorConvertingFileToData( + err, + key_path.to_string(), + )); + } + }; + Ok((cert, key)) } diff --git a/core/src/x509/ca_req.rs b/core/src/x509/ca_req.rs index 53f7100..ba1dbd5 100644 --- a/core/src/x509/ca_req.rs +++ b/core/src/x509/ca_req.rs @@ -88,17 +88,37 @@ impl CAReq { } pub fn read_csr_from_file(file_name: &str) -> X509Result { - let mut file: File = File::open(file_name).map_err(|err: io::Error| { - X509Error::ErrorReadingCertFile(err, file_name.to_string()) - })?; + println!(); + let mut file: File = match File::open(file_name) { + Ok(f) => f, + Err(err) => { + eprintln!("Reading Signing Request at {} ❌", file_name); + return Err(X509Error::ErrorReadingCertFile(err, file_name.to_string())); + } + }; + let mut buffer: Vec = Vec::new(); - file.read_to_end(&mut buffer).map_err(|err: io::Error| { - X509Error::ErrorReadingCertFile(err, file_name.to_string()) - })?; - let csr: X509Req = X509Req::from_pem(&buffer).map_err(|err: ErrorStack| { - X509Error::ErrorConvertingFileToData(err, file_name.to_string()) - })?; - Ok(csr) + match file.read_to_end(&mut buffer) { + Ok(_) => (), + Err(err) => { + eprintln!("Reading Signing Request at {} ❌", file_name); + return Err(X509Error::ErrorReadingCertFile(err, file_name.to_string())); + } + }; + + match X509Req::from_pem(&buffer) { + Ok(csr) => { + println!("Reading Signing Request at {} ✅", file_name); + Ok(csr) + } + Err(err) => { + eprintln!("Reading Signing Request at {} ❌", file_name); + Err(X509Error::ErrorConvertingFileToData( + err, + file_name.to_string(), + )) + } + } } pub fn save_key(key: &PKey, path: &str) -> X509Result<()> { From b92bcc6c883467e22698f01a71101f33c1c6e53f Mon Sep 17 00:00:00 2001 From: Shubham Singh Date: Thu, 5 Sep 2024 04:37:34 +0530 Subject: [PATCH 3/4] feat(logs): added logs for default certificate --- core/src/commands/generate.rs | 49 ++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/core/src/commands/generate.rs b/core/src/commands/generate.rs index 130dfcb..b2cbb75 100644 --- a/core/src/commands/generate.rs +++ b/core/src/commands/generate.rs @@ -192,12 +192,28 @@ pub fn generate( }; save_pem_certificate("csr_cert.pem".to_string(), output, leaf_certificate)?; } else { + println!(); + println!("Generated Certificate for : "); for domain in &domains { let distinguished_name: DistinguishedName = create_distinguished_name(&commonname, &country, &state); let leaf_cert_object: LeafCert = LeafCert::new(distinguished_name)?; - let (leaf_certificate, private_key) = - LeafCert::generate_certificate(leaf_cert_object, &d_cert, &d_pkey, None)?; + let (leaf_certificate, private_key) = match LeafCert::generate_certificate( + leaf_cert_object, + &d_cert, + &d_pkey, + None, + ) { + Ok((a, b)) => { + println!(" - \"{}\" ✅", domain); + (a, b) + } + Err(err) => { + println!(" - \"{}\" ❌", domain); + eprintln!("{}", err); + std::process::exit(1); + } + }; if let Some(private_key) = private_key { save_pem_key_pair(&output, leaf_certificate, domain.to_string(), private_key)?; } else { @@ -207,6 +223,12 @@ pub fn generate( ) } } + println!(); + println!( + "{}: All Successful Certificates and their corresponding keys are saved at : {}", + "Note".green(), + output.unwrap() + ); } if install { @@ -214,7 +236,10 @@ pub fn generate( } } else { if noca { - eprintln!("Error: No CA Certificates found and generation of a new one is disabled by `--no-ca`"); + eprintln!( + "{}: No CA Certificates found and generation of a new one is disabled by `--no-ca`", + "Error".red() + ); std::process::exit(1) } let distinguished_name: DistinguishedName = @@ -246,11 +271,23 @@ pub fn generate( None, )?; if let Some(private_key) = private_key { - save_pem_key_pair(&output, leaf_certificate, domain.to_string(), private_key)?; + match save_pem_key_pair( + &output, + leaf_certificate, + domain.to_string(), + private_key, + ) { + Ok(()) => {} + Err(err) => { + println!("{}", err); + } + }; } else { eprintln!( - "Oops! We lost your private key for domain {}. Please try again!", - domain + "{}{}{}", + "Oops! We lost your private key for domain ".yellow(), + domain.yellow(), + ". Please try again!".yellow() ) } } From 85ae1e8821324dc36a9dfe91b378c2294cbd8f27 Mon Sep 17 00:00:00 2001 From: Shubham Singh Date: Thu, 5 Sep 2024 14:27:13 +0530 Subject: [PATCH 4/4] feat(logs): improved logs for new token --- core/src/commands/generate.rs | 38 ++++++++++++++++++++++++++++---- core/src/utils.rs | 41 ++++++++++++++++++++++++++++++----- 2 files changed, 69 insertions(+), 10 deletions(-) diff --git a/core/src/commands/generate.rs b/core/src/commands/generate.rs index b2cbb75..6e7cf22 100644 --- a/core/src/commands/generate.rs +++ b/core/src/commands/generate.rs @@ -252,24 +252,47 @@ pub fn generate( create_distinguished_name(&commonname, &country, &state); let csr_object: X509Req = CAReq::read_csr_from_file(csr)?; let leaf_cert_object: LeafCert = LeafCert::new(distinguished_name)?; - let (leaf_certificate, _private_key) = LeafCert::generate_certificate( + println!(); + let (leaf_certificate, _private_key) = match LeafCert::generate_certificate( leaf_cert_object, &created_cert, &created_key, Some(&csr_object), - )?; + ) { + Ok((a, b)) => { + println!("Generating Certificate for Signing Request Successful! 👍"); + (a, b) + } + Err(err) => { + println!("Generating Certificate for Signing Request Failed! 👎"); + eprintln!("{}", err); + std::process::exit(1); + } + }; save_pem_certificate("csr_cert.pem".to_string(), output, leaf_certificate)?; } else { + println!(); + println!("Generated Certificate for : "); for domain in &domains { let distinguished_name: DistinguishedName = create_distinguished_name(&commonname, &country, &state); let leaf_cert_object: LeafCert = LeafCert::new(distinguished_name)?; - let (leaf_certificate, private_key) = LeafCert::generate_certificate( + let (leaf_certificate, private_key) = match LeafCert::generate_certificate( leaf_cert_object, &created_cert, &created_key, None, - )?; + ) { + Ok((a, b)) => { + println!(" - \"{}\" ✅", domain); + (a, b) + } + Err(err) => { + println!(" - \"{}\" ❌", domain); + eprintln!("{}", err); + std::process::exit(1); + } + }; if let Some(private_key) = private_key { match save_pem_key_pair( &output, @@ -291,6 +314,13 @@ pub fn generate( ) } } + + println!(); + println!( + "{}: All Successful Certificates and their corresponding keys are saved at : {}", + "Note".green(), + output.unwrap() + ); } if install { generate_install(created_cert)?; diff --git a/core/src/utils.rs b/core/src/utils.rs index 85a056f..7fc34d9 100644 --- a/core/src/utils.rs +++ b/core/src/utils.rs @@ -87,10 +87,15 @@ pub fn save_generated_cert_key_files( cert: &X509, key: &PKey, ) -> Result<(), Box> { + println!(); if let Some(ref data_dir) = *x509::DATA_DIR { if !data_dir.exists() { fs::create_dir_all(data_dir).map_err(|err| { - eprintln!("Failed to create data directory: {}", err); + eprintln!( + "{}: Failed to create data directory: {}", + "Error".red(), + err + ); err })?; } @@ -100,22 +105,46 @@ pub fn save_generated_cert_key_files( let ca_cert_file_str: &str = ca_certfile.to_str().ok_or_else(|| { let err: String = "Failed to convert ca_certfile path to string".to_string(); - eprintln!("{}", err); + eprintln!("{}: {}", "Error".red(), err); io::Error::new(io::ErrorKind::InvalidInput, err) })?; let ca_key_file_str: &str = ca_keyfile.to_str().ok_or_else(|| { let err: String = "Failed to convert ca_keyfile path to string".to_string(); - eprintln!("{}", err); + eprintln!("{}: {}", "Error".red(), err); io::Error::new(io::ErrorKind::InvalidInput, err) })?; - CACert::save_cert(cert, ca_cert_file_str)?; - CACert::save_key(key, ca_key_file_str)?; + match CACert::save_cert(cert, ca_cert_file_str) { + Ok(()) => { + println!( + "{}: CA Root Certificate saved at: {} 👍", + "Note".green(), + ca_cert_file_str + ); + } + Err(err) => { + eprintln!("{}", err); + std::process::exit(1); + } + }; + match CACert::save_key(key, ca_key_file_str) { + Ok(()) => { + println!( + "{}: CA Root Private Key saved at: {} 👍", + "Note".green(), + ca_cert_file_str + ); + } + Err(err) => { + eprintln!("{}", err); + std::process::exit(1); + } + }; Ok(()) } else { let err: String = "Unable to get Data Directory".to_string(); - eprintln!("{}", err); + eprintln!("{}: {}", "Error".red(), err); Err(Box::new(io::Error::new(io::ErrorKind::NotFound, err))) } }