Skip to content

Vaikora-AzureSecurityCenter v3.0.1 — align playbook + analytic rules with Vaikora /actions API schema#14366

Open
mazamizo21 wants to merge 1 commit into
Azure:masterfrom
Data443:feature/vaikora-asc-v3.0.1-agent-id-fix
Open

Vaikora-AzureSecurityCenter v3.0.1 — align playbook + analytic rules with Vaikora /actions API schema#14366
mazamizo21 wants to merge 1 commit into
Azure:masterfrom
Data443:feature/vaikora-asc-v3.0.1-agent-id-fix

Conversation

@mazamizo21
Copy link
Copy Markdown
Contributor

@mazamizo21 mazamizo21 commented May 28, 2026

Summary

End-to-end testing surfaced that the 3.0.0 solution was built against an assumed alert-shaped API response while the Vaikora `/api/v1/actions` endpoint actually returns action-shaped events. This caused failures across the playbook and all three analytic rules. This PR aligns the entire solution on the action-field schema and the `Vaikora_AgentSignals_CL` table.

Defects in 3.0.0

  1. `Poll_Vaikora_Actions` always sent `agent_id=` even when `VaikoraAgentId` was blank. Vaikora API returned HTTP 422 because Pydantic cannot parse `""` as a UUID. Every downstream action skipped.

  2. `Send_to_Log_Analytics` crashed with `InvalidTemplate` because `replace()` ran against null `title` / `description` fields that do not exist on the response.

  3. `Filter_High_Risk_Actions` referenced `threat_detected`, which is missing from the response.

  4. Three analytic rules queried `Vaikora_SecurityAlerts_CL` with columns (`AlertId_s`, `Title_s`, `Description_s`, `SourceIP_s`, `UserName_s`, etc.) that the playbook never wrote.

  5. Same solution shipped two divergent target tables: standalone playbook wrote to `Vaikora_SecurityAlerts`; mainTemplate inner playbook wrote to `Vaikora_AgentSignals`. Rules failed to match in both install paths.

Fix

Align everything on the action-field schema and `Vaikora_AgentSignals_CL`:

  • `Poll_Vaikora_Actions` URI rebuilt with `if(empty(parameters('VaikoraAgentId')))` so the `agent_id` segment is omitted when blank. Switched from `queries` object to URI concat so the conditional works.
  • `Send_to_Log_Analytics` body rewritten to action fields (`action_id`, `agent_id`, `action_type`, `resource_type`, `resource_id`, `status`, `severity`, `policy_id`, `policy_decision`, `is_anomaly`, `anomaly_score`, `anomaly_reason`, `log_hash`, `timestamp`) with `coalesce()` guards on nullable values. `Log-Type` set to `Vaikora_AgentSignals`.
  • `is_anomaly` wrapped with `toLower(string(coalesce(...)))` so it serializes as JSON `true`/`false` instead of Logic Apps' default `True`/`False`, which `json()` refuses to parse.
  • `Parse_Response` schema updated to declare the real `actions` array shape with nullable types on every property (the API returns explicit `null` for some optional fields).
  • `Filter_High_Risk_Actions` drops the `threat_detected` check (standalone playbook + mainTemplate inner playbook).
  • Three analytic rules rewritten to query `Vaikora_AgentSignals_CL` with action-field columns.
  • `entityMappings` reduced to `AgentId` (from `agent_id_s`) mapped to `Account.Name`. The response carries no IP/Host/Process fields.
  • `alertDetailsOverride` placeholders updated and kept at or below the 3-placeholder cap.
  • Solution description updated to reference `Vaikora_AgentSignals_CL`.

Files changed

  • `Solutions/Vaikora-AzureSecurityCenter/Playbooks/VaikoraToAzureSecurityCenter/azuredeploy.json`
  • `Solutions/Vaikora-AzureSecurityCenter/Package/mainTemplate.json` — `_solutionVersion` bumped to 3.0.1
  • `Solutions/Vaikora-AzureSecurityCenter/Package/3.0.1.zip` (3.0.0.zip retained per repo policy)
  • `Solutions/Vaikora-AzureSecurityCenter/Analytic Rules/Vaikora - High Severity Security Alerts.yaml`
  • `Solutions/Vaikora-AzureSecurityCenter/Analytic Rules/Vaikora - Anomaly Detection.yaml`
  • `Solutions/Vaikora-AzureSecurityCenter/Analytic Rules/Vaikora - Feed Outage Detection.yaml`
  • `Solutions/Vaikora-AzureSecurityCenter/Data/Solution_VaikoraSecurityCenter.json` — Version 3.0.1
  • `Solutions/Vaikora-AzureSecurityCenter/ReleaseNotes.md` — v3.0.1 entry
  • `Solutions/Vaikora-AzureSecurityCenter/SolutionMetadata.json` — lastPublishDate 2026-05-28

Test plan

  • arm-ttk local: 49/49 pass on `Package/3.0.1.zip`
  • Verified Vaikora API response shape against `api.vaikora.com/api/v1/actions` (live response: `{actions: [{action_type, agent_id, severity, policy_decision, is_anomaly, anomaly_score, anomaly_reason, log_hash, timestamp, …}], total, page, per_page}`)
  • Full E2E on a real Sentinel workspace: Poll_Vaikora_Actions → Parse_Response → Filter_High_Risk_Actions → For_Each_Security_Alert → Send_to_Log_Analytics all return `Succeeded`. The JSON body sent to LA contains every action field including `anomaly_reason` populated with real explanation text. LA Data Collector API returned HTTP 200.
  • CI `run-arm-ttk` green
  • Reviewer Content Hub install + standalone playbook test

cc @v-maheshbh @v-shukore

@mazamizo21 mazamizo21 requested review from a team as code owners May 28, 2026 16:33
@mazamizo21 mazamizo21 force-pushed the feature/vaikora-asc-v3.0.1-agent-id-fix branch from 4b696c3 to a1aec2f Compare May 28, 2026 17:01
@mazamizo21 mazamizo21 changed the title Vaikora-AzureSecurityCenter v3.0.1 — omit empty agent_id query param Vaikora-AzureSecurityCenter v3.0.1 — align playbook + analytic rules with Vaikora /actions API schema May 28, 2026
@mazamizo21 mazamizo21 force-pushed the feature/vaikora-asc-v3.0.1-agent-id-fix branch from a1aec2f to 5ae2531 Compare May 28, 2026 17:26
@v-maheshbh v-maheshbh added the Solution Solution specialty review needed label May 29, 2026
…ith Vaikora /actions API schema

The 3.0.0 release shipped against an assumed alert-shaped API response. End-to-end testing surfaced that the Vaikora /api/v1/actions endpoint returns action-shaped events. Concrete defects in 3.0.0:

- Poll_Vaikora_Actions always sent agent_id=, even when VaikoraAgentId was blank. Vaikora API returns HTTP 422 because Pydantic cannot parse '' as a UUID.
- Send_to_Log_Analytics crashed with InvalidTemplate because replace() ran against null title/description fields that do not exist on the response.
- Filter_High_Risk_Actions referenced threat_detected, which is missing from the response.
- The three analytic rules queried Vaikora_SecurityAlerts_CL with columns (AlertId_s, Title_s, Description_s, SourceIP_s, UserName_s, etc.) that the playbook never wrote.
- The standalone playbook wrote to Vaikora_SecurityAlerts; the mainTemplate inner playbook wrote to Vaikora_AgentSignals. Same solution shipped two divergent target tables.

This PR aligns everything on the action-field schema and the Vaikora_AgentSignals_CL table:

- Poll_Vaikora_Actions URI now omits agent_id when VaikoraAgentId is empty.
- Send_to_Log_Analytics body rewritten to action fields (action_id, agent_id, action_type, resource_type, resource_id, status, severity, policy_id, policy_decision, is_anomaly, anomaly_score, anomaly_reason, log_hash, timestamp) with coalesce guards on nullable values. Log-Type set to Vaikora_AgentSignals.
- is_anomaly wrapped with toLower(string(coalesce(...))) so it serializes as JSON true/false instead of Logic Apps' default True/False, which json() refuses to parse.
- Parse_Response schema accepts nullable fields so rows where anomaly_reason or other optional fields are null pass validation.
- Filter_High_Risk_Actions drops the threat_detected check; mainTemplate inner playbook mirrors the fix.
- All three analytic rules rewritten to query Vaikora_AgentSignals_CL with action-field columns.
- entityMappings reduced to agent_id -> Account.Name.
- alertDetailsOverride placeholders updated and kept at or below the 3-placeholder cap.
- Solution description updated to reference Vaikora_AgentSignals_CL.

Validated end-to-end against api.vaikora.com on a real Sentinel workspace: full chain (Poll_Vaikora_Actions -> Parse_Response -> Filter_High_Risk_Actions -> For_Each_Security_Alert -> Send_to_Log_Analytics) all succeed. LA Data Collector API returned HTTP 200 with the action JSON including populated anomaly_reason.

arm-ttk local: 49/49 pass on Package/3.0.1.zip. 3.0.0.zip retained per repo policy.
@mazamizo21 mazamizo21 force-pushed the feature/vaikora-asc-v3.0.1-agent-id-fix branch from 5ae2531 to ceaa077 Compare May 29, 2026 13:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Solution Solution specialty review needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants