refactor: modularize codebase and add 404 unit tests (#13)
CI / Format (push) Successful in 4s
CI / Clippy (push) Successful in 4m19s
CI / Security Audit (push) Successful in 1m44s
CI / Tests (push) Successful in 5m15s
CI / Detect Changes (push) Successful in 5s
CI / Deploy Agent (push) Successful in 2s
CI / Deploy Dashboard (push) Successful in 2s
CI / Deploy Docs (push) Has been skipped
CI / Deploy MCP (push) Successful in 2s
CI / Format (push) Successful in 4s
CI / Clippy (push) Successful in 4m19s
CI / Security Audit (push) Successful in 1m44s
CI / Tests (push) Successful in 5m15s
CI / Detect Changes (push) Successful in 5s
CI / Deploy Agent (push) Successful in 2s
CI / Deploy Dashboard (push) Successful in 2s
CI / Deploy Docs (push) Has been skipped
CI / Deploy MCP (push) Successful in 2s
This commit was merged in pull request #13.
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
mod archive;
|
||||
mod html;
|
||||
mod pdf;
|
||||
|
||||
use compliance_core::models::dast::DastFinding;
|
||||
use compliance_core::models::pentest::{AttackChainNode, PentestSession};
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
/// Report archive with metadata
|
||||
pub struct ReportArchive {
|
||||
/// The password-protected ZIP bytes
|
||||
pub archive: Vec<u8>,
|
||||
/// SHA-256 hex digest of the archive
|
||||
pub sha256: String,
|
||||
}
|
||||
|
||||
/// Report context gathered from the database
|
||||
pub struct ReportContext {
|
||||
pub session: PentestSession,
|
||||
pub target_name: String,
|
||||
pub target_url: String,
|
||||
pub findings: Vec<DastFinding>,
|
||||
pub attack_chain: Vec<AttackChainNode>,
|
||||
pub requester_name: String,
|
||||
pub requester_email: String,
|
||||
}
|
||||
|
||||
/// Generate a password-protected ZIP archive containing the pentest report.
|
||||
///
|
||||
/// The archive contains:
|
||||
/// - `report.pdf` — Professional pentest report (PDF)
|
||||
/// - `report.html` — HTML source (fallback)
|
||||
/// - `findings.json` — Raw findings data
|
||||
/// - `attack-chain.json` — Attack chain timeline
|
||||
///
|
||||
/// Files are encrypted with AES-256 inside the ZIP (standard WinZip AES format,
|
||||
/// supported by 7-Zip, WinRAR, macOS Archive Utility, etc.).
|
||||
pub async fn generate_encrypted_report(
|
||||
ctx: &ReportContext,
|
||||
password: &str,
|
||||
) -> Result<ReportArchive, String> {
|
||||
let html = html::build_html_report(ctx);
|
||||
|
||||
// Convert HTML to PDF via headless Chrome
|
||||
let pdf_bytes = pdf::html_to_pdf(&html).await?;
|
||||
|
||||
let zip_bytes = archive::build_zip(ctx, password, &html, &pdf_bytes)
|
||||
.map_err(|e| format!("Failed to create archive: {e}"))?;
|
||||
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(&zip_bytes);
|
||||
let sha256 = hex::encode(hasher.finalize());
|
||||
|
||||
Ok(ReportArchive {
|
||||
archive: zip_bytes,
|
||||
sha256,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user