Initial commit: Compliance Scanner Agent
Autonomous security and compliance scanning agent for git repositories. Features: SAST (Semgrep), SBOM (Syft), CVE monitoring (OSV.dev/NVD), GDPR/OAuth pattern detection, LLM triage, issue creation (GitHub/GitLab/Jira), PR reviews, and Dioxus fullstack dashboard. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
105
compliance-agent/src/scheduler.rs
Normal file
105
compliance-agent/src/scheduler.rs
Normal file
@@ -0,0 +1,105 @@
|
||||
use mongodb::bson::doc;
|
||||
use tokio_cron_scheduler::{Job, JobScheduler};
|
||||
|
||||
use compliance_core::models::ScanTrigger;
|
||||
|
||||
use crate::agent::ComplianceAgent;
|
||||
use crate::error::AgentError;
|
||||
|
||||
pub async fn start_scheduler(agent: &ComplianceAgent) -> Result<(), AgentError> {
|
||||
let sched = JobScheduler::new()
|
||||
.await
|
||||
.map_err(|e| AgentError::Scheduler(format!("Failed to create scheduler: {e}")))?;
|
||||
|
||||
// Periodic scan job
|
||||
let scan_agent = agent.clone();
|
||||
let scan_schedule = agent.config.scan_schedule.clone();
|
||||
let scan_job = Job::new_async(scan_schedule.as_str(), move |_uuid, _lock| {
|
||||
let agent = scan_agent.clone();
|
||||
Box::pin(async move {
|
||||
tracing::info!("Scheduled scan triggered");
|
||||
scan_all_repos(&agent).await;
|
||||
})
|
||||
})
|
||||
.map_err(|e| AgentError::Scheduler(format!("Failed to create scan job: {e}")))?;
|
||||
sched.add(scan_job).await
|
||||
.map_err(|e| AgentError::Scheduler(format!("Failed to add scan job: {e}")))?;
|
||||
|
||||
// CVE monitor job (daily)
|
||||
let cve_agent = agent.clone();
|
||||
let cve_schedule = agent.config.cve_monitor_schedule.clone();
|
||||
let cve_job = Job::new_async(cve_schedule.as_str(), move |_uuid, _lock| {
|
||||
let agent = cve_agent.clone();
|
||||
Box::pin(async move {
|
||||
tracing::info!("CVE monitor triggered");
|
||||
monitor_cves(&agent).await;
|
||||
})
|
||||
})
|
||||
.map_err(|e| AgentError::Scheduler(format!("Failed to create CVE monitor job: {e}")))?;
|
||||
sched.add(cve_job).await
|
||||
.map_err(|e| AgentError::Scheduler(format!("Failed to add CVE monitor job: {e}")))?;
|
||||
|
||||
sched.start().await
|
||||
.map_err(|e| AgentError::Scheduler(format!("Failed to start scheduler: {e}")))?;
|
||||
|
||||
tracing::info!(
|
||||
"Scheduler started: scans='{}', CVE monitor='{}'",
|
||||
agent.config.scan_schedule,
|
||||
agent.config.cve_monitor_schedule,
|
||||
);
|
||||
|
||||
// Keep scheduler alive
|
||||
loop {
|
||||
tokio::time::sleep(tokio::time::Duration::from_secs(3600)).await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn scan_all_repos(agent: &ComplianceAgent) {
|
||||
use futures_util::StreamExt;
|
||||
|
||||
let cursor = match agent.db.repositories().find(doc! {}).await {
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
tracing::error!("Failed to list repos for scheduled scan: {e}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let repos: Vec<_> = cursor
|
||||
.filter_map(|r| async { r.ok() })
|
||||
.collect()
|
||||
.await;
|
||||
|
||||
for repo in repos {
|
||||
let repo_id = repo.id.map(|id| id.to_hex()).unwrap_or_default();
|
||||
if let Err(e) = agent.run_scan(&repo_id, ScanTrigger::Scheduled).await {
|
||||
tracing::error!("Scheduled scan failed for {}: {e}", repo.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn monitor_cves(agent: &ComplianceAgent) {
|
||||
use futures_util::StreamExt;
|
||||
|
||||
// Re-scan all SBOM entries for new CVEs
|
||||
let cursor = match agent.db.sbom_entries().find(doc! {}).await {
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
tracing::error!("Failed to list SBOM entries for CVE monitoring: {e}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let entries: Vec<_> = cursor
|
||||
.filter_map(|r| async { r.ok() })
|
||||
.collect()
|
||||
.await;
|
||||
|
||||
if entries.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
tracing::info!("CVE monitor: checking {} dependencies", entries.len());
|
||||
// The actual CVE checking is handled by the CveScanner in the pipeline
|
||||
// This is a simplified version that just logs the activity
|
||||
}
|
||||
Reference in New Issue
Block a user