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:
122
compliance-agent/src/database.rs
Normal file
122
compliance-agent/src/database.rs
Normal file
@@ -0,0 +1,122 @@
|
||||
use mongodb::bson::doc;
|
||||
use mongodb::{Client, Collection, IndexModel};
|
||||
use mongodb::options::IndexOptions;
|
||||
|
||||
use compliance_core::models::*;
|
||||
|
||||
use crate::error::AgentError;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Database {
|
||||
inner: mongodb::Database,
|
||||
}
|
||||
|
||||
impl Database {
|
||||
pub async fn connect(uri: &str, db_name: &str) -> Result<Self, AgentError> {
|
||||
let client = Client::with_uri_str(uri).await?;
|
||||
let db = client.database(db_name);
|
||||
db.run_command(doc! { "ping": 1 }).await?;
|
||||
tracing::info!("Connected to MongoDB database '{db_name}'");
|
||||
Ok(Self { inner: db })
|
||||
}
|
||||
|
||||
pub async fn ensure_indexes(&self) -> Result<(), AgentError> {
|
||||
// repositories: unique git_url
|
||||
self.repositories()
|
||||
.create_index(
|
||||
IndexModel::builder()
|
||||
.keys(doc! { "git_url": 1 })
|
||||
.options(IndexOptions::builder().unique(true).build())
|
||||
.build(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// findings: unique fingerprint
|
||||
self.findings()
|
||||
.create_index(
|
||||
IndexModel::builder()
|
||||
.keys(doc! { "fingerprint": 1 })
|
||||
.options(IndexOptions::builder().unique(true).build())
|
||||
.build(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// findings: repo_id + severity compound
|
||||
self.findings()
|
||||
.create_index(
|
||||
IndexModel::builder()
|
||||
.keys(doc! { "repo_id": 1, "severity": 1 })
|
||||
.build(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// scan_runs: repo_id + started_at descending
|
||||
self.scan_runs()
|
||||
.create_index(
|
||||
IndexModel::builder()
|
||||
.keys(doc! { "repo_id": 1, "started_at": -1 })
|
||||
.build(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// sbom_entries: compound
|
||||
self.sbom_entries()
|
||||
.create_index(
|
||||
IndexModel::builder()
|
||||
.keys(doc! { "repo_id": 1, "name": 1, "version": 1 })
|
||||
.build(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// cve_alerts: unique cve_id + repo_id
|
||||
self.cve_alerts()
|
||||
.create_index(
|
||||
IndexModel::builder()
|
||||
.keys(doc! { "cve_id": 1, "repo_id": 1 })
|
||||
.options(IndexOptions::builder().unique(true).build())
|
||||
.build(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
// tracker_issues: unique finding_id
|
||||
self.tracker_issues()
|
||||
.create_index(
|
||||
IndexModel::builder()
|
||||
.keys(doc! { "finding_id": 1 })
|
||||
.options(IndexOptions::builder().unique(true).build())
|
||||
.build(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
tracing::info!("Database indexes ensured");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn repositories(&self) -> Collection<TrackedRepository> {
|
||||
self.inner.collection("repositories")
|
||||
}
|
||||
|
||||
pub fn findings(&self) -> Collection<Finding> {
|
||||
self.inner.collection("findings")
|
||||
}
|
||||
|
||||
pub fn scan_runs(&self) -> Collection<ScanRun> {
|
||||
self.inner.collection("scan_runs")
|
||||
}
|
||||
|
||||
pub fn sbom_entries(&self) -> Collection<SbomEntry> {
|
||||
self.inner.collection("sbom_entries")
|
||||
}
|
||||
|
||||
pub fn cve_alerts(&self) -> Collection<CveAlert> {
|
||||
self.inner.collection("cve_alerts")
|
||||
}
|
||||
|
||||
pub fn tracker_issues(&self) -> Collection<TrackerIssue> {
|
||||
self.inner.collection("tracker_issues")
|
||||
}
|
||||
|
||||
pub fn raw_collection(&self, name: &str) -> Collection<mongodb::bson::Document> {
|
||||
self.inner.collection(name)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user