CI / Check (push) Has been skipped
CI / Detect Changes (push) Successful in 4s
CI / Deploy Agent (push) Successful in 3m44s
CI / Deploy Dashboard (push) Successful in 2m37s
CI / Deploy Docs (push) Has been skipped
CI / Deploy MCP (push) Successful in 1m49s
118 lines
5.0 KiB
Rust
118 lines
5.0 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>,
|
|
}
|
|
|
|
/// 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>,
|
|
}
|