Skip to content

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.

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.

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.

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).

Terminal window
# 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 UTF8
Write-Host "Wrote $file"

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, typically api://<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 with roots.platform=mac|win.
  • SentryEnvironment — the environment tag Sentry groups events by. Defaults to release (or debug on Debug builds). Set to e.g. staging if 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.

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.

  1. Devices > Scripts and remediations > Platform scripts > + Add > Windows 10 and later.
  2. Name: Roots windows - write config.json.
  3. Script: upload the filled-in Set-RootsConfig.ps1.
  4. 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.
  5. 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.

  • 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 status shows Succeeded for at least one device.)

Only when the above is green, proceed to Step 3.

3. Enroll apps.