Some checks failed
CI / Check (pull_request) Failing after 5m55s
CI / Detect Changes (pull_request) Has been skipped
CI / Deploy Agent (pull_request) Has been skipped
CI / Deploy Dashboard (pull_request) Has been skipped
CI / Deploy Docs (pull_request) Has been skipped
CI / Deploy MCP (pull_request) Has been skipped
Browser tool: - Session-persistent Chrome tab (same tab reused across all calls in a pentest) - Auto-screenshot on every navigate and click (stored in attack chain for report) - Fill uses CDP Input.insertText (fixes WebSocket corruption on special chars) - Switched from browserless/chromium to chromedp/headless-shell (stable WS) Context window optimization: - Strip screenshot_base64 from LLM conversation (kept in DB for report) - Truncate HTML to 2KB, page text to 1.5KB in LLM messages - Cap element/link arrays at 15 items - SAST triage: batch 30 findings per LLM call instead of all at once Report improvements: - Auto-embed screenshots in attack chain timeline (navigate + click nodes) - Cover page shows best app screenshot - Attack chain phases capped at 8 (no more 20x "Final") User cleanup: - TestUserRecord model tracks created test users per session - cleanup.rs: Keycloak (Admin REST API), Auth0 (Management API), Okta (Users API) - Auto-cleanup on session completion when cleanup_test_user is enabled - Env vars: KEYCLOAK_ADMIN_USERNAME, KEYCLOAK_ADMIN_PASSWORD System prompt: - Explicit browser usage instructions (navigate → get_content → click → fill) - SPA auth bypass guidance (check page content, not HTTP status) - Screenshot instructions for evidence collection Other: - Pin mongo:7 in docker-compose (mongo:latest/8 segfaults on kernel 6.19) - Add deploy/docker-compose.mailserver.yml for Postfix + Dovecot Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
61 lines
2.9 KiB
Rust
61 lines
2.9 KiB
Rust
use compliance_core::AgentConfig;
|
|
use secrecy::SecretString;
|
|
|
|
use crate::error::AgentError;
|
|
|
|
fn env_var(key: &str) -> Result<String, AgentError> {
|
|
std::env::var(key).map_err(|_| AgentError::Config(format!("Missing env var: {key}")))
|
|
}
|
|
|
|
fn env_var_opt(key: &str) -> Option<String> {
|
|
std::env::var(key).ok().filter(|v| !v.is_empty())
|
|
}
|
|
|
|
fn env_secret_opt(key: &str) -> Option<SecretString> {
|
|
env_var_opt(key).map(SecretString::from)
|
|
}
|
|
|
|
pub fn load_config() -> Result<AgentConfig, AgentError> {
|
|
Ok(AgentConfig {
|
|
mongodb_uri: env_var("MONGODB_URI")?,
|
|
mongodb_database: env_var_opt("MONGODB_DATABASE")
|
|
.unwrap_or_else(|| "compliance_scanner".to_string()),
|
|
litellm_url: env_var_opt("LITELLM_URL")
|
|
.unwrap_or_else(|| "http://localhost:4000".to_string()),
|
|
litellm_api_key: SecretString::from(env_var_opt("LITELLM_API_KEY").unwrap_or_default()),
|
|
litellm_model: env_var_opt("LITELLM_MODEL").unwrap_or_else(|| "gpt-4o".to_string()),
|
|
litellm_embed_model: env_var_opt("LITELLM_EMBED_MODEL")
|
|
.unwrap_or_else(|| "text-embedding-3-small".to_string()),
|
|
github_token: env_secret_opt("GITHUB_TOKEN"),
|
|
github_webhook_secret: env_secret_opt("GITHUB_WEBHOOK_SECRET"),
|
|
gitlab_url: env_var_opt("GITLAB_URL"),
|
|
gitlab_token: env_secret_opt("GITLAB_TOKEN"),
|
|
gitlab_webhook_secret: env_secret_opt("GITLAB_WEBHOOK_SECRET"),
|
|
jira_url: env_var_opt("JIRA_URL"),
|
|
jira_email: env_var_opt("JIRA_EMAIL"),
|
|
jira_api_token: env_secret_opt("JIRA_API_TOKEN"),
|
|
jira_project_key: env_var_opt("JIRA_PROJECT_KEY"),
|
|
searxng_url: env_var_opt("SEARXNG_URL"),
|
|
nvd_api_key: env_secret_opt("NVD_API_KEY"),
|
|
agent_port: env_var_opt("AGENT_PORT")
|
|
.and_then(|p| p.parse().ok())
|
|
.unwrap_or(3001),
|
|
scan_schedule: env_var_opt("SCAN_SCHEDULE").unwrap_or_else(|| "0 0 */6 * * *".to_string()),
|
|
cve_monitor_schedule: env_var_opt("CVE_MONITOR_SCHEDULE")
|
|
.unwrap_or_else(|| "0 0 0 * * *".to_string()),
|
|
git_clone_base_path: env_var_opt("GIT_CLONE_BASE_PATH")
|
|
.unwrap_or_else(|| "/tmp/compliance-scanner/repos".to_string()),
|
|
ssh_key_path: env_var_opt("SSH_KEY_PATH")
|
|
.unwrap_or_else(|| "/data/compliance-scanner/ssh/id_ed25519".to_string()),
|
|
keycloak_url: env_var_opt("KEYCLOAK_URL"),
|
|
keycloak_realm: env_var_opt("KEYCLOAK_REALM"),
|
|
keycloak_admin_username: env_var_opt("KEYCLOAK_ADMIN_USERNAME"),
|
|
keycloak_admin_password: env_secret_opt("KEYCLOAK_ADMIN_PASSWORD"),
|
|
pentest_verification_email: env_var_opt("PENTEST_VERIFICATION_EMAIL"),
|
|
pentest_imap_host: env_var_opt("PENTEST_IMAP_HOST"),
|
|
pentest_imap_port: env_var_opt("PENTEST_IMAP_PORT").and_then(|p| p.parse().ok()),
|
|
pentest_imap_username: env_var_opt("PENTEST_IMAP_USERNAME"),
|
|
pentest_imap_password: env_secret_opt("PENTEST_IMAP_PASSWORD"),
|
|
})
|
|
}
|