2. Policy management
Owner: IT Prerequisite: Step 1 - Entra app registration is complete. You also need the captures-endpoint URL and publishable key from Cloud Ops Step 5 - Handoff. The values from both feed straight into the config script. Critical: complete this step before Step 3. If the MSI lands before the config script, the agent installs and starts with missing configuration, logs an error, and retries until the script writes
config.json. Recoverable, but cleaner the other way.
Pilot device group
Section titled “Pilot device group”Create or choose a security group in Entra ID, for example Arbium Windows Pilot Devices. Membership type Assigned (static). Everything in Steps 2 and 3 scopes to this group.
Members are device objects (not users) — devices get added after they enroll in Intune.
Deliver the agent config
Section titled “Deliver the agent config”Intune has no native CSP for “set arbitrary machine environment variable” on Windows, so Settings Catalog cannot deliver the agent’s config directly. Instead, use a PowerShell platform script that writes the filled-in config to %ProgramData%\Roots\config.json. The agent reads that file with reloadOnChange: true — re-editing the script in Intune and re-syncing the device live-rotates the config without an MSI reinstall.
The config script
Section titled “The config script”Copy the block below into a file named Set-RootsConfig.ps1. Replace every __Placeholder__ with the value from your handoff sheet (Step 1 for Entra values; Cloud Ops handoff for endpoint + key).
# Roots Windows agent config - written by an Intune PowerShell script policy.# Runs as SYSTEM at device-target. The agent reads with reloadOnChange: true,# so editing this script in Intune and re-syncing the device re-applies the# config live - no MSI reinstall, no agent restart.
$dir = "$env:ProgramData\Roots"$file = Join-Path $dir 'config.json'
if (-not (Test-Path $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null }
$config = [ordered]@{ CapturesEndpoint = '__CapturesEndpoint__' PublishableKey = '__PublishableKey__' EntraTenantId = '__EntraTenantId__' EntraClientId = '__EntraClientId__' EntraApiScope = '__EntraApiScope__' EntraCloudHost = 'login.microsoftonline.com' FlushThreshold = 50 FlushIntervalSeconds = 30
# Optional Sentry telemetry. Blank SentryDsn = disabled (SDK short- # circuits at init, no overhead). To enable, paste the DSN from your # Sentry project > Settings > Client Keys. SentryEnvironment is the # tag Sentry groups events by; "release" is the default. Same Sentry # project covers Mac + Win; platform routing is by the roots.platform tag. SentryDsn = '' SentryEnvironment = 'release'}
$config | ConvertTo-Json | Set-Content -Path $file -Encoding UTF8Write-Host "Wrote $file"Placeholder substitutions
Section titled “Placeholder substitutions”From the Cloud Ops handoff:
__CapturesEndpoint__— the full URL, e.g.https://arbium.<customer-domain>/functions/v1/captures-batch-direct.__PublishableKey__— the deployment’s public anon key.
From the Entra app registration (Step 1):
__EntraTenantId__— the Directory (tenant) ID.__EntraClientId__— the Application (client) ID.__EntraApiScope__— the Application ID URI, typicallyapi://<client-id>.
EntraCloudHost is optional and defaults to login.microsoftonline.com. Set it to login.microsoftonline.us only if your tenant is on a sovereign cloud (GCC High, DoD).
Optional — Sentry error telemetry:
SentryDsn— blank by default = Sentry disabled (the SDK short-circuits at init, no overhead). To enable, paste the DSN from your Sentry project’s Settings > Client Keys (DSN) page. One Sentry project covers both Mac and Windows; the SDK tags each event withroots.platform=mac|win.SentryEnvironment— the environment tag Sentry groups events by. Defaults torelease(ordebugon Debug builds). Set to e.g.stagingif you want to keep pilot devices off the prod issue stream.
After setting SentryDsn, validate delivery by deploying the agent and checking the Sentry Logs UI for status.type: ready entries from the device’s release (e.g. release:roots-win@0.1.15.0). See Step 4 - Smoke test for detailed verification steps.
Privacy rules
Section titled “Privacy rules”No additional config entry is required for privacy rules. The agent fetches the customer’s current blocked-app and blocked-site rules from the backend and enforces them on the device before a capture can leave it. It caches the last successful rules response and holds captures until it has either current rules or a cache to apply.
BlocklistEndpoint and BlocklistRefreshSeconds are optional advanced config
keys. Leave them unset for the standard endpoint and ten-minute refresh cycle.
Do not use these settings to bypass a customer privacy rule.
Upload to Intune
Section titled “Upload to Intune”Devices > Scripts and remediations > Platform scripts > + Add > Windows 10 and later.- Name:
Roots windows - write config.json. - Script: upload the filled-in
Set-RootsConfig.ps1. - Settings:
- Run this script using the logged-on credentials = No (script writes under
%ProgramData%and needs SYSTEM). - Enforce script signature check = No.
- Run script in 64-bit PowerShell Host = Yes.
- Run this script using the logged-on credentials = No (script writes under
- Assignments: scope to the pilot device group.
The agent watches config.json and re-binds its EntraOptions and AgentOptions on file change. Config rotation flow: edit the script content in Intune → Intune re-runs it on next sync → the file is rewritten on disk → the agent picks up new values on its next capture / token-acquire cycle. No restart required.
Once a new agent version ships and either the schema or values change, re-run this same flow against the existing platform-script policy — see Step 5 - Shipping updates.
Definition of done
Section titled “Definition of done”- Pilot device group exists.
- Platform-script policy is deployed to the pilot group, no errors.
- (Verifiable in Intune:
Devices > Scripts and remediations > Platform scripts > Roots windows - write config.json > Device statusshows Succeeded for at least one device.)
Only when the above is green, proceed to Step 3.