Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions sentinel/data-connectors/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# RetailShield — Data Connector Definition

This directory contains the ARM template that provisions the two custom Log Analytics tables used by RetailShield detection rules.

## Custom Tables

### RetailShield_POS_CL

Point-of-sale transaction events from retail terminals. Used by:

| Detection Rule | Event Types |
|---------------|-------------|
| `pos_void_refund.kql` | `pos_void_refund` |
| `gift_card_fraud.kql` | `gift_card_fraud` |
| `pos_anomaly.kql` | `pos_anomaly` (also uses `RetailShield_Logs_CL`) |

**Key columns:**

| Column | Type | Description |
|--------|------|-------------|
| `TerminalID` | string | POS terminal identifier |
| `StoreID` | string | Retail store identifier |
| `EmployeeID` | string | Cashier/operator who performed the transaction |
| `OperatorID` | string | Supervisor who authorised void/refund |
| `TransactionType` | string | Sale, Void, Refund, GiftCardIssue, GiftCardReload, GiftCardRedeem, NoSale |
| `TransactionAmount` | real | Value in GBP |
| `VoidCount` | int | Void transaction count in detection window |
| `RefundCount` | int | Refund transaction count in detection window |
| `TotalGiftCardValue` | real | Aggregate gift card transaction value |
| `RiskScore` | int | RetailShield risk score (0–100) |
| `PlaybookTrigger` | string | Recommended response playbook |

### RetailShield_Logs_CL

General RetailShield log events covering voice fraud detection and POS device anomalies. Used by:

| Detection Rule | Event Types |
|---------------|-------------|
| `ai_voice_fraud.kql` | `voice_fraud` |
| `pos_anomaly.kql` | `pos_anomaly` |

**Key columns:**

| Column | Type | Description |
|--------|------|-------------|
| `EventType` | string | voice_fraud, pos_anomaly, network_anomaly |
| `CallerID` | string | Caller identifier or phone number (voice fraud) |
| `CallCount` | int | Call volume within detection window |
| `VoiceAnomalyScore` | real | AI anomaly score 0.0–1.0 |
| `ProcessName` | string | Suspicious process name (POS anomaly) |
| `DeviceName` | string | Host device name |
| `RiskScore` | int | RetailShield risk score (0–100) |
| `PlaybookTrigger` | string | Recommended response playbook |

## Deployment

```bash
az deployment group create \
--resource-group <your-resource-group> \
--template-file sentinel/data-connectors/retailshield-connector.json \
--parameters workspaceName=<your-workspace-name>
```

This creates both custom tables in the workspace. Tables must exist before deploying analytics rules or ingesting data.

## Data Ingestion

Use the [Log Analytics Data Collector API](https://learn.microsoft.com/en-us/azure/azure-monitor/logs/data-collector-api) or the Azure Monitor Ingestion API (DCR-based) to send records to these tables from your POS middleware or SIEM feed:

```bash
# Example ingestion via REST (simplified)
POST https://<workspace-id>.ods.opinsights.azure.com/api/logs?api-version=2016-04-01
Content-Type: application/json
Log-Type: RetailShield_POS
x-ms-date: <RFC 7231 date>
Authorization: SharedKey <workspace-id>:<signature>

[{"TerminalID":"POS-001","StoreID":"ST-042","EmployeeID":"EMP-123",...}]
```

## Standard Tables Also Used

The following built-in Sentinel/Defender tables are referenced by RetailShield rules and require the corresponding data connectors to be enabled in your workspace:

| Table | Data Connector |
|-------|---------------|
| `SigninLogs` | Azure Active Directory |
| `AuditLogs` | Azure Active Directory |
| `DeviceNetworkEvents` | Microsoft Defender for Endpoint |
| `DeviceFileEvents` | Microsoft Defender for Endpoint |
| `DeviceProcessEvents` | Microsoft Defender for Endpoint |
| `DeviceEvents` | Microsoft Defender for Endpoint |
| `DeviceLogonEvents` | Microsoft Defender for Endpoint |
| `EmailAttachmentInfo` | Microsoft Defender for Office 365 |
| `EmailEvents` | Microsoft Defender for Office 365 |
| `AzureDiagnostics` | Azure Diagnostics |
231 changes: 231 additions & 0 deletions sentinel/data-connectors/retailshield-connector.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"workspaceName": {
"type": "string",
"metadata": {
"description": "Name of the Log Analytics workspace where Microsoft Sentinel is deployed."
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Azure region for all resources."
}
}
},
"variables": {
"connectorId": "RetailShield",
"connectorVersion": "1.0.0"
},
"resources": [
{
"type": "Microsoft.OperationalInsights/workspaces/tables",
"apiVersion": "2022-10-01",
"name": "[concat(parameters('workspaceName'), '/RetailShield_POS_CL')]",
"location": "[parameters('location')]",
"properties": {
"schema": {
"name": "RetailShield_POS_CL",
"columns": [
{
"name": "TimeGenerated",
"type": "datetime",
"description": "Timestamp when the POS event was ingested into the workspace."
},
{
"name": "TerminalID",
"type": "string",
"description": "Unique identifier of the POS terminal that generated the event."
},
{
"name": "StoreID",
"type": "string",
"description": "Retail store identifier."
},
{
"name": "EmployeeID",
"type": "string",
"description": "Operator or cashier identifier performing the transaction."
},
{
"name": "OperatorID",
"type": "string",
"description": "Supervisor or override operator identifier (used for void/refund authorisation)."
},
{
"name": "TransactionType",
"type": "string",
"description": "Type of POS transaction: Sale, Void, Refund, GiftCardIssue, GiftCardReload, GiftCardRedeem, NoSale."
},
{
"name": "TransactionAmount",
"type": "real",
"description": "Transaction value in GBP."
},
{
"name": "TransactionCount",
"type": "int",
"description": "Number of transactions within the aggregation window."
},
{
"name": "PaymentMethod",
"type": "string",
"description": "Payment method: Cash, Card, GiftCard, ContactlessMobile."
},
{
"name": "CardLast4",
"type": "string",
"description": "Last 4 digits of payment card (if applicable, for correlation only)."
},
{
"name": "GiftCardID",
"type": "string",
"description": "Gift card identifier (for gift card transaction types)."
},
{
"name": "TotalGiftCardValue",
"type": "real",
"description": "Aggregated value of gift card transactions within the detection window."
},
{
"name": "VoidCount",
"type": "int",
"description": "Number of void transactions by the operator in the lookback window."
},
{
"name": "RefundCount",
"type": "int",
"description": "Number of refund transactions by the operator in the lookback window."
},
{
"name": "EventType",
"type": "string",
"description": "RetailShield event classification: pos_void_refund, gift_card_fraud, pos_no_sale."
},
{
"name": "RiskScore",
"type": "int",
"description": "RetailShield risk score 0-100; higher values indicate greater anomaly confidence."
},
{
"name": "SignalName",
"type": "string",
"description": "RetailShield detection signal that triggered this record."
},
{
"name": "PlaybookTrigger",
"type": "string",
"description": "Recommended playbook to invoke: notify_soc, suspend_terminal, block_ip."
},
{
"name": "SourceSystem",
"type": "string",
"description": "Source system tag — always 'RetailShield-POS' for this table."
}
]
}
}
},
{
"type": "Microsoft.OperationalInsights/workspaces/tables",
"apiVersion": "2022-10-01",
"name": "[concat(parameters('workspaceName'), '/RetailShield_Logs_CL')]",
"location": "[parameters('location')]",
"properties": {
"schema": {
"name": "RetailShield_Logs_CL",
"columns": [
{
"name": "TimeGenerated",
"type": "datetime",
"description": "Timestamp when the log event was ingested into the workspace."
},
{
"name": "EventType",
"type": "string",
"description": "RetailShield event classification: voice_fraud, pos_anomaly, network_anomaly."
},
{
"name": "DeviceName",
"type": "string",
"description": "Hostname of the device generating the log event."
},
{
"name": "TerminalID",
"type": "string",
"description": "POS terminal identifier (for POS-related log events)."
},
{
"name": "StoreID",
"type": "string",
"description": "Retail store identifier."
},
{
"name": "CallerID",
"type": "string",
"description": "Caller identifier or phone number (for voice fraud events)."
},
{
"name": "CallCount",
"type": "int",
"description": "Number of calls from the CallerID within the detection window."
},
{
"name": "CallDurationSeconds",
"type": "int",
"description": "Total or average call duration in seconds."
},
{
"name": "VoiceAnomalyScore",
"type": "real",
"description": "AI-derived anomaly score for voice pattern analysis (0.0–1.0)."
},
{
"name": "ProcessName",
"type": "string",
"description": "Process name involved in POS anomaly events."
},
{
"name": "ProcessCommandLine",
"type": "string",
"description": "Process command line for POS anomaly events."
},
{
"name": "NetworkDestination",
"type": "string",
"description": "Destination IP or hostname for network anomaly events."
},
{
"name": "BytesSent",
"type": "long",
"description": "Bytes sent to network destination."
},
{
"name": "RiskScore",
"type": "int",
"description": "RetailShield risk score 0-100."
},
{
"name": "SignalName",
"type": "string",
"description": "RetailShield detection signal that triggered this record."
},
{
"name": "PlaybookTrigger",
"type": "string",
"description": "Recommended playbook to invoke."
},
{
"name": "SourceSystem",
"type": "string",
"description": "Source system tag — always 'RetailShield-Logs' for this table."
}
]
}
}
}
]
}
1,263 changes: 1,262 additions & 1 deletion tests/detection-rules/test_kql_rules.py

Large diffs are not rendered by default.

Loading