158 lines
6.7 KiB
Rust
158 lines
6.7 KiB
Rust
use secrecy::SecretString;
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct AgentConfig {
|
|
pub mongodb_uri: String,
|
|
pub mongodb_database: String,
|
|
pub litellm_url: String,
|
|
pub litellm_api_key: SecretString,
|
|
pub litellm_model: String,
|
|
pub litellm_embed_model: String,
|
|
pub github_token: Option<SecretString>,
|
|
pub github_webhook_secret: Option<SecretString>,
|
|
pub gitlab_url: Option<String>,
|
|
pub gitlab_token: Option<SecretString>,
|
|
pub gitlab_webhook_secret: Option<SecretString>,
|
|
pub jira_url: Option<String>,
|
|
pub jira_email: Option<String>,
|
|
pub jira_api_token: Option<SecretString>,
|
|
pub jira_project_key: Option<String>,
|
|
pub searxng_url: Option<String>,
|
|
pub nvd_api_key: Option<SecretString>,
|
|
pub agent_port: u16,
|
|
pub scan_schedule: String,
|
|
pub cve_monitor_schedule: String,
|
|
pub git_clone_base_path: String,
|
|
/// Base directory for content-addressed artifact blobs and per-run working
|
|
/// dirs (`<base>/blobs/<sha[0:2]>/<sha>`, `<base>/work/<target>/<artifact>/`).
|
|
pub artifact_store_base_path: String,
|
|
pub ssh_key_path: String,
|
|
pub keycloak_url: Option<String>,
|
|
pub keycloak_realm: Option<String>,
|
|
pub keycloak_admin_username: Option<String>,
|
|
pub keycloak_admin_password: Option<SecretString>,
|
|
// Pentest defaults
|
|
pub pentest_verification_email: Option<String>,
|
|
pub pentest_imap_host: Option<String>,
|
|
pub pentest_imap_port: Option<u16>,
|
|
/// Use implicit TLS (IMAPS, port 993) instead of plain IMAP.
|
|
pub pentest_imap_tls: bool,
|
|
pub pentest_imap_username: Option<String>,
|
|
pub pentest_imap_password: Option<SecretString>,
|
|
/// Static bearer for the cross-tenant admin endpoints under
|
|
/// `/api/v1/admin/*`. When `None`, those endpoints are not
|
|
/// mounted at all (defense-in-depth: ops endpoints never reach
|
|
/// any auth path if no operator has explicitly opted in).
|
|
pub admin_api_token: Option<SecretString>,
|
|
/// Live tenant-registry URL the scheduler consults for the list
|
|
/// of tenants to iterate. When `None` or unreachable, scheduler
|
|
/// falls back to `SCHEDULER_TENANT_IDS` env (M7.2-C).
|
|
pub tenant_registry_url: Option<String>,
|
|
/// Ephemeral soft-PLC provisioning for dynamic PLC testing (#183). Off by
|
|
/// default: it needs Docker access in the agent's runtime, which is a
|
|
/// deployment opt-in.
|
|
pub plc_runtime: PlcRuntimeConfig,
|
|
/// Static bearer for the Werkbank runner endpoints
|
|
/// (`/api/v1/werkbank/jobs/*`). Machine auth for runners leasing/completing
|
|
/// jobs — NOT a Keycloak JWT, since a runner acts across tenants. When
|
|
/// `None`, those endpoints are not mounted at all.
|
|
pub werkbank_runner_token: Option<SecretString>,
|
|
/// Source for the OSCAL control catalog pulled from breakpilot-compliance
|
|
/// (drives the [`crate::traits::ControlsProvider`]). Disabled when
|
|
/// `base_url` is `None`.
|
|
pub breakpilot: BreakpilotConfig,
|
|
}
|
|
|
|
/// Where to pull the OSCAL control catalog from breakpilot-compliance, and where
|
|
/// to snapshot it for deterministic / offline reuse.
|
|
#[derive(Debug, Clone)]
|
|
pub struct BreakpilotConfig {
|
|
/// Backend base URL (e.g. `http://backend-compliance:8002`). `None` disables
|
|
/// the OSCAL controls provider.
|
|
pub base_url: Option<String>,
|
|
/// Optional bearer token for the catalog endpoint.
|
|
pub token: Option<SecretString>,
|
|
/// Directory for catalog snapshots.
|
|
pub snapshot_dir: String,
|
|
/// Enable the master-controls **semantic** mapping pass (embed regions,
|
|
/// Enable the master-controls **semantic** mapping pass (embed regions,
|
|
/// retrieve nearest controls, grounded-judge). On by default — validated live
|
|
/// against the deployed master-controls catalog. Still a no-op unless
|
|
/// `base_url` is set and the catalog is reachable.
|
|
pub semantic_mapping: bool,
|
|
/// Enable the **grounded surface** pass for absence-based controls (retrieve
|
|
/// the code surface a control governs, judge whether it holds). On by default
|
|
/// — validated live; it covers the 8 absence-based CRA controls that no
|
|
/// syntactic rule can.
|
|
pub grounded_control_checks: bool,
|
|
}
|
|
|
|
impl Default for BreakpilotConfig {
|
|
fn default() -> Self {
|
|
Self {
|
|
base_url: None,
|
|
token: None,
|
|
snapshot_dir: "/data/compliance-scanner/oscal".to_string(),
|
|
semantic_mapping: true,
|
|
grounded_control_checks: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Configuration for the ephemeral soft-PLC "provision-and-test" path (#183).
|
|
///
|
|
/// When a PLC/SPS target ships control logic but no reachable live device, the
|
|
/// agent can instantiate that logic itself: spin up a throwaway soft-PLC
|
|
/// (OpenPLC) container in-cluster, load the program, start the runtime, probe it
|
|
/// over industrial protocols, then tear it down. This struct carries the knobs
|
|
/// for that container's lifecycle and the OpenPLC web-UI credentials used to
|
|
/// upload the program.
|
|
#[derive(Clone, Debug)]
|
|
pub struct PlcRuntimeConfig {
|
|
/// Master switch. Provision-and-test does nothing unless this is set — it
|
|
/// shells out to `docker`, which requires the agent container to have Docker
|
|
/// access (socket mount), an explicit deployment decision.
|
|
pub enabled: bool,
|
|
/// Container image for the ephemeral soft-PLC (OpenPLC).
|
|
pub image: String,
|
|
/// Docker network the instance joins. Must be the agent's own network so it
|
|
/// is reachable in-cluster by container name and never published to the host.
|
|
pub network: String,
|
|
/// Memory cap passed to `docker run --memory` (e.g. `512m`).
|
|
pub memory: String,
|
|
/// CPU cap passed to `docker run --cpus` (e.g. `0.5`).
|
|
pub cpus: String,
|
|
/// Hard ceiling on a provisioned instance's lifetime. Teardown is guaranteed
|
|
/// no later than this even if a load/probe step hangs.
|
|
pub max_lifetime_secs: u64,
|
|
/// OpenPLC web-UI username for the program upload (image default `openplc`).
|
|
pub openplc_user: String,
|
|
/// OpenPLC web-UI password (image default `openplc`).
|
|
pub openplc_password: SecretString,
|
|
}
|
|
|
|
impl Default for PlcRuntimeConfig {
|
|
fn default() -> Self {
|
|
Self {
|
|
enabled: false,
|
|
image: "registry.meghsakha.com/openplc:latest".to_string(),
|
|
network: "certifai".to_string(),
|
|
memory: "512m".to_string(),
|
|
cpus: "0.5".to_string(),
|
|
max_lifetime_secs: 180,
|
|
openplc_user: "openplc".to_string(),
|
|
openplc_password: SecretString::from("openplc".to_string()),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
pub struct DashboardConfig {
|
|
pub mongodb_uri: String,
|
|
pub mongodb_database: String,
|
|
pub agent_api_url: String,
|
|
pub dashboard_port: u16,
|
|
pub mcp_endpoint_url: Option<String>,
|
|
}
|