Microsoft Sentinel
Ship Arbiter authentication rejects and security events into Microsoft Sentinel for SOC monitoring, retention and correlation with your other security telemetry. End-to-end setup, no agent on either side.
How it fits together
Arbiter ships events into Sentinel via the Azure Monitor Logs Ingestion API. The chain looks like this:
Two unfamiliar Azure terms in there. Both are configuration objects, not running services:
- DCE (Data Collection Endpoint): the public HTTPS URL Arbiter posts JSON to. One per region is plenty; shared across streams.
- DCR (Data Collection Rule): the schema definition that says which columns the stream has and which Custom Table to write into. One DCR per stream.
Available streams
Each Arbiter SIEM target ships exactly one stream. To ship more than one, create one target per stream. Multiple targets share the same DCE; each points at its own Custom Table.
| Stream | Purpose | Default cadence | Default rate cap | Custom Table |
|---|---|---|---|---|
| Security events | Rule-based detections (SOC alerting and triage) | Real-time (10 s) | 1,000 / h | ArbiterSecurityEvents_CL |
| Auth log rejects | Failed authentication attempts (forensics, compliance) | Every minute | 10,000 / h | ArbiterAuthLog_CL |
| Auth log (all) | Permits and rejects, full RADIUS verdict feed | Every minute | 30,000 / h | ArbiterAuthLogAll_CL |
| Accounting events | Acct-Start / Stop / Interim with session lifetime, bytes | Every minute | 20,000 / h | ArbiterAccounting_CL |
| Audit log | Operator actions (policy edits, RBAC, settings touches) | Hourly | 1,000 / h | ArbiterAuditLog_CL |
| Endpoints snapshot | Full device inventory (asset-management overlay) | Daily | None (bounded by table size) | ArbiterEndpoints_CL |
Append-only. A tick only fires if there is something new since the last successful tick (per-stream cursor on the Arbiter side). The endpoints snapshot is the exception by design: it emits the current inventory once per cadence window.
Cadence and rate cap are per-target and editable.Defaults are sized for an SME tenant (50 to 2,000 endpoints). For larger estates or stricter alerting SLAs, change the cadence from the SIEM target editor. The rate cap is a hard ceiling: when hit, forwarding pauses for the rest of the rolling hour and a warning surfaces on the target row.
Security events
Rule-based detections fired by Arbiter: suspicious traffic on a guest VLAN, unknown MAC bursts, expired certificate attempts. Negligible ingest cost for SME tenants. The one stream that runs at full real-time cadence by default because detector hits should land in your SOC fast.
Auth log rejects
Every rejected authentication attempt: failed 802.1X, unknown MAC, policy-denied, expired cert. Includes the matched policy and auth policy so denial reasons are correlatable.
Auth log (all)
Permits and rejects together. Useful when you want a complete authentication audit in Sentinel rather than just the failure feed. Order of magnitude higher volume than rejects only.
Accounting events
RADIUS Acct-Start / Stop / Interim with session duration and byte counters. Useful for session-lifetime forensics, user attribution to network flows and licence usage reporting.
Audit log
Operator-action audit trail: who edited which policy, who rotated which secret, when settings changed. Low volume, highest compliance value. Pairs naturally with Sentinel Workbooks for an evidence-ready change history.
Endpoints snapshot
Daily full inventory of every endpoint the tenant has seen. Each tick emits the entire current endpoints table as a series of point-in-time rows so you can diff for new or disappearing devices in Sentinel.
Before you start
Prerequisites
- An Azure subscription where you can create a resource group, a Log Analytics workspace and an Entra ID app registration.
- Microsoft Sentinel enabled on that workspace (optional: without it the data still lands and is queryable, Sentinel just adds the SOC features on top).
- An Arbiter tenant where you are signed in as an admin.
- Permission to grant the Monitoring Metrics Publisherrole on the DCE and DCR. Contributor or Owner on the resource group is enough.
Create a resource group and Log Analytics workspace
Why: the workspace is where Sentinel queries the data from. Everything else in this guide lives inside the same resource group.
- Resource group: e.g.
rg-sentinel-lab, regionNorth Europe. - Log Analytics workspace: e.g.
law-arbiter-sentinel, same region as the resource group. - Pricing tier: start on Pay-as-you-go. Move to a Sentinel Commitment Tier later if your ingest grows.
Microsoft Sentinel features (Workbooks, Hunting, Analytics Rules) are optional. Enable Sentinel on the workspace from its blade if you want them. Without it, data still lands and is queryable from the workspace via plain KQL.
Create a Data Collection Endpoint (DCE)
Why: the DCE is the public URL Arbiter POSTs to. One DCE is enough; you will reuse it across both streams.
Portal search bar → Data Collection Endpoints→ + Create:
- Endpoint name:
dce-arbiter-sentinel - Subscription and resource group: same as the workspace
- Region: same as the workspace
Review and create. About 30 seconds. Once provisioned, open the DCE and copy the Logs Ingestion URL from the Overview tab:
https://dce-arbiter-sentinel-XXXX.northeurope-1.ingest.monitor.azure.comStrip any trailing slash. Save this URL for Step 7.
Create the Custom Table and its DCR
Why: the Custom Table is the destination Sentinel queries from. The DCR sits in front of it and enforces the schema. The wizard creates both in one flow.
One Custom Table per stream. The walkthrough below covers auth log rejects; the security events flow is identical except for the table name and the sample file.
a. Grab the sample JSON
The wizard infers the table's column types from a sample file. Save the block below as arbiter_authlog_rejects_sample.json:
Auth log rejects stream. Wizard uses this to build the column schema.
[
{
"TimeGenerated": "2026-05-21T14:30:12.000123Z",
"event_id": 90342,
"tenant_id": 201,
"mac_address": "aabbccddeeff",
"user_name": null,
"nas_ip": "10.0.0.5",
"nas_name": "core-sw-01",
"nas_port": "GigabitEthernet0/1",
"vlan_id": 30,
"ssid": null,
"ap_mac": null,
"auth_method": "mab",
"eap_type": null,
"reason": "unknown MAC: no matching endpoint",
"policy_name": "Default Deny",
"auth_policy_name": "Wired MAB",
"access_profile_name": "Quarantine",
"monitor_mode": false,
"monitor_coerced": false,
"client_cert_cn": null,
"client_cert_serial": null,
"client_cert_issuer": null,
"client_cert_issuer_org": null,
"source": "arbiter.auth_log_rejects"
}
]For the security events stream, use this sample instead:
[
{
"TimeGenerated": "2026-05-21T14:30:00.123456Z",
"event_id": 1042,
"tenant_id": 201,
"rule_name": "ssh-on-guest-vlan",
"severity": "high",
"mac_address": "aabbccddeeff",
"nas_ip": "10.0.0.5",
"nas_port_id": "GigabitEthernet0/1",
"summary": "SSH (TCP/22) seen from a guest-VLAN endpoint",
"details": {
"flow_src": "192.168.30.42",
"flow_dst_port": 22,
"flow_proto": "tcp"
},
"source": "arbiter.security_events"
}
]b. Run the table-creation wizard
In the workspace blade, left nav → Tables→ + Create → New custom log (DCR-based). Fill in:
- Table name:
ArbiterAuthLog(Azure appends_CL; do not type it yourself). - Data collection rule: Create new, same resource group, name
dcr-arbiter-authlog. - Data collection endpoint: pick
dce-arbiter-sentinelfrom Step 2.
Click Next. On the schema page, Browse for files and upload the sample JSON. The preview should show TimeGenerated as datetime and the rest as string / int / dynamic as appropriate.
source query. Arbiter ships TimeGenerated directly so no KQL rename is needed.Click Next → Create. Allow 1 to 2 minutes for the table to provision.
c. Copy the DCR identifiers
Once created, open dcr-arbiter-authlog and grab two values for Step 7:
- DCR immutable ID. Top toolbar → JSON View. Search for
"immutableId"; the value looks likedcr-64c60e809eca44d1af23031db751157c. - Stream name. Left nav → Data sources. The row is named
Custom-ArbiterAuthLog_CL.
Register an Entra ID application
Arbiter authenticates as a confidential client application using OAuth 2.0 client credentials. Create one app registration; both streams can share it.
- Search bar: Microsoft Entra ID → left nav App registrations → + New registration.
- Name:
Arbiter Sentinel Ingest(label only; pick whatever helps you). - Supported account types: Accounts in this organisational directory only (Single tenant).
- Redirect URI: leave blank.
- Register.
On the Overview tab, copy two values you will paste into Arbiter later:
- Application (client) ID: a GUID.
- Directory (tenant) ID: a different GUID (this is your Entra tenant identifier).
Create a client secret
In the same app registration:
- Left nav: Certificates & secrets.
- Client secrets tab → + New client secret.
- Description:
arbiter-core(label only). - Expires: 24 months recommended. Azure emails the registration owner ahead of expiry. Shorter lifetimes are fine for tighter rotation policies; longer is unsupported.
- Add.
The secret value appears once in the Value column, formatted like Aa1Bb2~Cc3Dd4.... Copy it immediately. If you navigate away without copying, the value is unrecoverable: delete the secret and create a new one.
Grant Monitoring Metrics Publisher
Why: the Logs Ingestion API checks RBAC at two scopes. A missing role assignment is the most common reason a Sentinel target shows HTTP 403.
- DCE needs the role for the connection.
- DCR needs the role for the stream write. This is the strict check.
Do the steps below twice: once on dce-arbiter-sentinel, once on dcr-arbiter-authlog.
- Open the resource.
- Left nav → Access control (IAM).
- + Add → Add role assignment.
- Role: Monitoring Metrics Publisher→ Next.
- Members: User, group, or service principal→ + Select members.
- Search for
Arbiter Sentinel Ingest. Pick the result with the service-principal icon (small blue square, not a user avatar). Click Select. - Review + assign.
Configure the SIEM target in Arbiter
Why: the SIEM target row is what tells the Arbiter forwarder where to ship events.
In the Arbiter admin portal, open the tenant you want shipping to Sentinel. Switch to the SIEM tab → + Add target.
| Field | Value |
|---|---|
| Name | Sentinel - auth rejects (free text) |
| Destination | Microsoft Sentinel |
| Stream | Auth log rejects |
| DCE URL | from Step 2 |
| DCR immutable ID | from Step 3c |
| Stream name | Custom-ArbiterAuthLog_CL |
| Azure tenant ID | from Step 4 |
| Client ID | from Step 4 |
| Client secret | from Step 5 |
Save the target, then click the Test paper-plane icon next to the row. The status flips to OK (green tick) within about 30 seconds on success.
If it stays red, hover the Error icon. The tooltip shows the exact HTTP response from Azure:
- 401: AAD credentials wrong (client ID, client secret or tenant ID).
- 403: role assignment missing or not yet propagated. See Troubleshooting below.
- 400: stream name typo or schema mismatch.
Test it's working
Why: verify the pipeline end-to-end in two stages before you trust it for production alerting.
a. Canary check (Test button)
In Arbiter, on the SIEM tab, click the paper-plane icon next to the target row. The forwarder posts a single synthetic event matching the stream's schema; the status flips to OK within about 30 seconds if everything is wired correctly.
Confirm it landed in Sentinel: open the workspace → Logs → paste:
ArbiterAuthLog_CL
| where TimeGenerated > ago(5m)
| project TimeGenerated, mac_address, reasonYou should see one row with mac_address = 000000000000 and a reason starting with "Arbiter SIEM test event…".
b. Real data check
Real rejects from the tenant start flowing on the next 10-second cursor tick. Filter the canary out so you only see live data:
ArbiterAuthLog_CL
| where TimeGenerated > ago(15m)
| where mac_address != "000000000000"
| project TimeGenerated, mac_address, nas_name, auth_method, reason, auth_policy_name
| order by TimeGenerated descIf your tenant has any failing auths (blocked MABs, expired certs, default-deny matches), rows appear here within a minute or two of the auth happening. If nothing's appearing, check the Auth log tab in the Arbiter portal first to confirm rejects are actually being produced.
Expected latency
| Stage | Time |
|---|---|
Endpoint fails auth, row written to auth_log | t + 0 s |
| Arbiter forwarder picks the row up on next tick | t + 0 to 10 s |
| POST accepted by the Azure DCE | t + 10 to 15 s |
| Row queryable from KQL | t + 30 to 90 s |
Build dashboards and alerts (optional)
Why: Sentinel's value over a passive log store is that you can render the data into Workbooks and trigger Analytics Rules. Starter queries below.
// Failed-auth rate by hour, useful for a Workbook tile
ArbiterAuthLog_CL
| where TimeGenerated > ago(7d)
| summarize rejects = count() by bin(TimeGenerated, 1h)
| render timechart
// Top reject reasons over the last 24 hours
ArbiterAuthLog_CL
| where TimeGenerated > ago(24h)
| summarize count() by reason
| order by count_ desc
| take 10
// Endpoints producing the most rejects (potential misconfig or attack)
ArbiterAuthLog_CL
| where TimeGenerated > ago(24h)
| summarize attempts = count(), reasons = make_set(reason) by mac_address
| order by attempts desc
| take 20To turn one of these into an alert, go to Sentinel → Analytics→ + Create→ Scheduled query rule. Paste the query, set a threshold (e.g. "trigger when more than 20 rejects from the same MAC in 5 minutes") and an action (email, Teams, ServiceNow ticket, etc.).
Troubleshooting
HTTP 403 from the DCE
By far the most common failure. The AAD token issued cleanly (no 401) but the DCR refused the principal. Two causes:
Cause 1: propagation lag
Resource-scoped role assignments take 5 to 15 minutes to take effect. Wait 10 minutes and click Test again. The forwarder also retries every 10 seconds in the background, so the status flips to OK on its own once Azure catches up.
Cause 2: wrong principal assigned
Azure lists an Entra app twice in the member picker: the Application object and the Service Principal. The role must be on the Service Principal.
- Check the IAM → Role assignments tab. Your row's Type column should read Service principal, not App.
- If wrong, remove that row and add a new one. Fastest way to disambiguate: paste the Service Principal Object ID (visible from the Enterprise Applications view of the app) into the member search box.
HTTP 401 from AAD
Wrong client ID, wrong client secret or wrong Azure tenant ID. Edit the SIEM target row in Arbiter and re-paste the values from the Entra app's Overview tab. Missing or expired client secrets are the usual culprit.
HTTP 400 from the DCE
The request reached the DCR but failed validation. Almost always one of:
- Stream name typo. Case sensitive, must start with
Custom-. - Schema mismatch: a field Arbiter sends isn't in the table. Recreate the table using the latest sample JSON from Step 3.
Status flips between OK and Error
Intermittent connectivity from Arbiter Core to ingest.monitor.azure.com, or a transient AAD token issue. No data is lost: the forwarder retries every 10 seconds and the cursor only advances on success, so rows are held until the next successful tick.
Cost and volume
Sentinel charges per GB of data ingested. Order of magnitude at the time of writing: around €2.30 per GB on the Pay-as-you-go tier; Commitment Tiers reduce this if you ingest steadily above 100 GB per day.
For typical SME deployments the cost split is heavily skewed:
- Security events are sparse. A few dozen events per tenant per day at most: negligible cost.
- Auth log rejects scale with how noisy your network is. The stream filters to
result = 'reject'on the Arbiter side, so the typical volume is 5 to 15% of total auth events. Each row is under a kilobyte. A 500-endpoint SME tenant typically ships well under 100 MB per month. - Auth log (all) and accounting events are higher volume. Each row is around 500 bytes; at the default rate cap of 30,000 events/h that's roughly 360 MB per day per tenant worst case.
- Audit log is sparse (operator actions only): negligible cost.
- Endpoints snapshot is one full inventory per day. A 2,000-endpoint tenant ships around 1 MB per day on this stream.
The per-target hourly rate cap (visible on every SIEM target row in the Arbiter portal) is the safety net. When hit, forwarding pauses for the rest of the rolling hour and the row turns red with a warning so the operator notices instead of getting a surprise Sentinel bill. Defaults are sized at roughly 3x the realistic SME peak; raise them per target if your subscription is sized for more.
Need help?
Stuck on a 403 or want us to look at your Sentinel target config? Email support@arbiter.ie with a screenshot of the SIEM tab and the error tooltip. We usually reply same business day.