Skip to content

Security Monitoring Architecture

Rebased from the bedrock-soc codebase on 2026-06-10 (review issue #138). Counts, pipeline order, and job mapping below cite their source files; if this doc and bedrock-soc disagree, the code wins.

Overview

Cirius Group runs an agent-based security monitoring system deployed as Azure Container Apps Jobs. The consolidated orchestrator (job-orchestrator-cirius) runs 81 detection agents per cycle across PROD + DDE + AWS + HOME, drawn from 126 agent modules in the bedrock-soc repo, followed by a multi-stage triage pipeline. A 5-minute mini-orchestrator provides rapid response between cycles; a daily maintenance run covers posture. Findings post to the SOC platform; urgent incidents page Rory via Telegram. No human is required in the loop for detection — only for triage and response.

(The long-standing "17-agent system" label describes the original 2025 deployment and is retired.)


Branding — MSSP vs. Customer Entity

Two distinct identities run through everything the SOC produces. Keeping them straight is a hard rule, not a style preference — it is the difference between a service voice and a legal entity.

IdentityRoleWhere it appears
Bedrock CybersecurityThe MSSP — the managed-security service voiceOutbound sender / report-issuer branding: email "from" name, report headers, heartbeat and notification voice, anything that speaks as the provider
Cirius GroupThe customer / monitored entity being protectedSENTINEL report subjects, the audited-entity field, and all HIPAA legal text — anything that names who is under audit

Rules:

  • Reports and emails are issued by Bedrock Cybersecurity. When the SOC speaks in the provider's voice — the sender name, report-issuer line, heartbeat and alert notifications — that voice is Bedrock Cybersecurity, the MSSP.
  • Cirius Group stays as the customer entity. Do not rebrand Cirius Group out of SENTINEL report subjects, the audit-entity reference, or HIPAA legal text. There, Cirius Group is the entity being monitored, not the service provider — swapping it for Bedrock there would be wrong.
  • Incident links point to soc.bedrockcybersecurity.org (incidents moved off secopssoc).

Shipped in bedrock-soc (#237 / #238 / #239). If a report, email, or template mixes the two voices, the test is simple: who is speaking (Bedrock, the MSSP) vs. who is being audited (Cirius Group, the customer).


Stack

ComponentResourceLocation
Agent runtimeContainer Apps Jobs (consolidated *-cirius + specialized)rg-logging-logs, logging subscription
Container registryciriusagentsprod.azurecr.iologging subscription
SOC platformca-soc-prod — soc.bedrockcybersecurity.orgrg-logging-logs
SecOps dashboardca-secops-prod — secops.bedrockcybersecurity.org (read-only aggregator)rg-logging-logs
DatabasePostgreSQL — psql-soc-prod (SOC platform); UBA baselines in psql-secops-prodlogging subscription
Log sourcescirius-logging-law-central (PROD, ID 5d76d1f2), DDE LAW, OPS LAWsper tenant
AI inferenceAzure OpenAIcirius-openai-prod.openai.azure.com

Pipeline (per orchestrator cycle, in order)

Source: bedrock-soc/agents/orchestrator.py.

  1. Mini agents — 81 registry agents post NEW incidents in parallel waves of 5; then the UEBA baseliner and the SLA agent (refreshes SLA state, Telegram AT_RISK warnings).
  2. Analyst agent (rules engine, no LLM) — moves NEW → CLOSED (known-good / CM-ticket / maintenance-window match) or OPEN.
  3. Engineer agent — closes recurring noise with CM tickets; proposes PENDING known-good rules. Then the auto-correlator (links OPEN incidents sharing actor/resource) and the kill-chain correlator (multi-stage chains in a 120-min window → CRITICAL chain incident).
  4. History matcher — closes patterns resolved 5+ times as FP in 90 days (never touches CRITICAL). Then threat-intel enrichment of surviving OPEN incidents (AbuseIPDB / VirusTotal / HIBP / Shodan).
  5. Detection agent (LLM) — enriches remaining OPEN incidents; triage agent (LLM) auto-closes obviously-benign ones.
  6. SecurityAgent (LLM) — paging decision over first-time incidents, per-environment prompts; urgent → Telegram.
  7. Post-run: vuln findings mirrored to bedrock-findings, CMDB sync, email heartbeat report; Mondays add known-good counter reset + stale-rule pruning.

Container Apps Jobs (Consolidated — June 2026)

The per-environment split (formerly job-orchestrator-prod / job-secops-dde / job-secops-aws) shipped and was later consolidated into tenant-wide jobs. Source of truth: azure-infra/logging/secops_cirius.tf and the bedrock-soc repo.

JobScopeSchedule
job-orchestrator-ciriusMain incident pipeline — PROD + DDE + AWS + HOME (81 agents + full pipeline)Every 4 hours
job-mini-orchestrator-cirius9 read-only rapid checks (cortex, execution ×2, network ×2, identity, GuardDuty, CloudTrail root, IAM); triggers the main job on urgent signal, 60-min cooldownEvery 5 minutes
job-secops-maintenance-cirius22 posture agents — backup, VM status, certs, endpoint, MDR coverage, supply chain, credential inventoryDaily 07:00 UTC

Specialized jobs run alongside: job-uba-baseline-{prod,dde} (weekly Sun 02:00 UTC), job-findings-agents-prod, job-audit-evidence-prod (daily), job-sentinel-*, job-grc-agents-prod. Eleven external-surface agents (HIBP, CT logs, Shodan, typosquat, DNS/email security, GHAS…) run as scheduled GitHub Actions rather than Container Apps Jobs (bedrock-soc/README.md).

Note: orchestrator.py's docstring still says "every 6 hours"; the 4-hour figure follows bedrock-soc/CLAUDE.md and README (newer, post-consolidation). The actual cron lives in azure-infra Terraform.


Agent Inventory (by category)

126 agent modules; 81 run per main CIRIUS cycle. Chronic agents (61 names in agents/agent_config.py::CHRONIC_AGENTS) keep one long-lived incident per condition (no date in ioc_key); behavioral agents date-stamp so each day's signal is a distinct ticket.

CategoryCountNotable agentsData sources
Kill chain — PROD / DDE / AWS7 + 7 + 7execution, persistence, credential_dumping, lateral_movement, exfiltration, defense_evasion, encryption (+_dde, aws_* variants)Sentinel LAW SecurityEvent KQL; CloudTrail (7 accounts)
ATT&CK coverage net2kql_coverage, kql_coverage_dde — 655 KQL queries / 527 techniquesboth Sentinel LAWs
Universal translator agents3universal_sentinel(_dde), universal_aws — translator-mapped detections, replacing per-stage DDE agentsSentinelKQL / CloudTrail translators
Identity & auth6 PROD + 5 DDEidentity, entra, sp_signin, ad, dcsync, ad_identitySigninLogs, AuditLogs, DC SecurityEvent
Break-glass3break_glass{,_dde,_aws} — any activity pages, no exceptionsEntra logs, Palo syslog, AWS root CloudTrail
UBA9 PROD + 4 DDE + 2 AWSimpossible travel, MFA fatigue, dormant account, off-hours privileged, logon velocity, bulk data access, longitudinal driftSign-in logs vs p50/p95 baselines (psql-secops-prod)
Azure activity / M365 / DLP6azure_activity, office, purview_dlp (+_dde)AzureActivity, OfficeActivity, Purview
Network & log integrity2 + 6network(_dde); log_volume, fim, syslog (+_dde)Palo Alto CEF, OPS LAWs, FIM
EDR / vendor4cortex, cortex_version, edr_silence, canaryCortex XDR API, LAW heartbeat, canary health
AWS infra activity4aws_security, aws_cloudtrail, aws_palo, aws_wineventSecurity Hub/GuardDuty, CloudTrail, S3 archives
HOME workstations3device_alert, device_process, device_networkMDE device tables via Defender XDR connector
Supply chain1sbom_scannerSBOMs in cirius-audit-evidence-prod
Maintenance (daily)12 PROD + 4 DDE + 5 AWS + 1 HOMEbackup, vm_status, disk_space, cert_expiry, arctic_wolf_coverage, keeper, twingate, mdfc, credential_inventory…Azure/AWS APIs, vendor APIs
External surface (GH Actions)11hibp, cert_transparency, shodan_exposure, typosquat, dns_monitor, email_security, github_security…external APIs
LLM analyst packages7azure_auditor, cti_analyst, detection_engineer, identity_analyst, sentinelGraph/MDFC/Intune, KEV+OTX+VT, LAW backtests

Full per-agent registry: bedrock-soc/agents/orchestrator.py:1379-1605. Environment membership is decided by the registry dicts (PROD_AGENTS / DDE_AGENTS / AWS_AGENTS / HOME_AGENTS / MAINTENANCE_*) selected by the job's --environment arg — agents do not self-declare. Every finding is stamped with source_system via _env_to_source_system().

Break-Glass Accounts (Permanently Unsuppressible)

Any activity from the 18 break-glass accounts triggers CRITICAL immediately with no suppression possible — not by known-good rules, not by analyst override. Hard-blocked at the SOC API layer (bedrock-soc/app/routers/known_good.py).


Incident Lifecycle

NEW  ──► CLOSED   (Analyst Agent: known-good rule match)
NEW  ──► OPEN     (Analyst Agent: no known-good match)
OPEN ──► INVESTIGATING  (analyst picks up)
INVESTIGATING ──► RESOLVED

All state transitions are in the SOC platform at soc.bedrockcybersecurity.org. Telegram is read-only — no buttons, no approvals via Telegram.


Known-Good Rules

Rules are DB-driven; agents fetch on startup via GET /api/known-good. Hit counters increment fire-and-forget (POST /api/known-good/{id}/hit). Rory is the sole authority for creating or modifying rules. Break-glass accounts are permanently excluded from any rule scope.


Change Management Integration

Every merged PR auto-creates a CM ticket via POST /api/changes. The analyst agent calls GET /api/changes/recent before opening an incident — a matching CM within the window suppresses infrastructure-change alerts. This prevents agent noise during normal Terraform apply cycles.


Notification Rules

ConditionChannel
Every orchestrator run completesEmail (heartbeat)
SecurityAgent pages on CRITICAL/HIGH incidentTelegram
SLA AT_RISK warningsTelegram
Known-good rule match (CLOSED)No notification
Analyst moves to INVESTIGATINGSOC UI only

All outbound email and reports are issued in the Bedrock Cybersecurity (MSSP) voice; Cirius Group is named only as the monitored/audited entity. See Branding — MSSP vs. Customer Entity.


Last updated: June 2026 — full rebase from bedrock-soc (issue #138): consolidated jobs, real pipeline order, 126-module / 81-per-cycle agent inventory by category. API contract: SOC API Reference.

Internal use only — Cirius Group