Skip to content

4. Smoke test

Owner: IT

Pick one user with a device in the pilot device group, install the agent on their device, and confirm it reaches the backend cleanly before scoping to the wider fleet.

The user should have a device already enrolled in Intune and sitting in the pilot device group from Steps 2 and 3. Note the device serial number; you’ll use it when verifying captures arrived at the backend.

The test user must be signed into a session backed by an Entra-joined or Hybrid-joined device, since the agent acquires its Entra token through WAM against the device’s Primary Refresh Token. The tenant must also have granted admin consent for the Arbium app reg (Step 1).

The policy and MSI will install on the next MDM check-in (~15 minutes). To skip the wait, open Company Portal on the device and choose “Sync this device” — or from Intune: Devices > <device> > Sync.

Terminal window
# Process check
Get-Process -Name "Roots"
# Version
(Get-Item "C:\Program Files\Roots\Roots.exe").VersionInfo.FileVersion
# Config delivered
Test-Path 'C:\ProgramData\Roots\config.json'
Get-Content 'C:\ProgramData\Roots\config.json' | ConvertFrom-Json

Verify the JSON output matches what you set in Step 2 (correct endpoint, tenant, client ID, scope).

The Windows agent sends telemetry to Sentry (when SentryDsn is configured). In the Sentry Logs UI, filter by the device’s release (e.g. release:roots-win@0.1.15.0) and look for:

  • status.type: ready — the agent loaded its config and is running.
  • status.type: upload with status.inserted / status.assigned — captures are being uploaded to ChainDB.

If you see no Roots process, the per-user logon-triggered scheduled task probably hasn’t fired yet. The MSI registers an Active Setup stub that runs in each user’s context on their next interactive sign-in — if the test user was already signed in when Intune delivered the package, the stub will not have run yet. Sign them out and back in (or, for a hands-on smoke test only, run & 'C:\Program Files\Roots\register-task.ps1' once as that user) to create the task and start the agent.

These queries run against the deployed ChainDB Postgres. Cloud Ops can run them and confirm; IT does not need direct database access.

-- The user identity was provisioned on first capture
SELECT user_id, email, last_seen_at
FROM public.auth_identities
WHERE email = '<test user UPN>';
-- Captures are landing for that user
SELECT id, app_name, window_key, to_timestamp(created_at / 1000.0) AS created_at
FROM public.captures
WHERE user_id = (
SELECT user_id FROM public.auth_identities WHERE email = '<test user UPN>'
)
ORDER BY created_at DESC
LIMIT 10;

Healthy state:

  • A row in public.auth_identities for the test UPN, last_seen_at updated within the last few minutes.
  • Rows arriving in public.captures every minute or two, created_at close to now (the column is a Unix-millis bigint).

Confirm Sentry isn’t flagging errors from the device’s host.

  • Test-Path 'C:\ProgramData\Roots\config.json' returns False — the platform script from Step 2 hasn’t run yet. Force a sync; if it still doesn’t appear, check Devices > Scripts and remediations > Platform scripts > Roots windows - write config.json > Device status for errors.

  • MsalUiRequiredException / WAM cannot acquire a Roots token silently — the device or user is not Entra-joined / Hybrid-joined, so WAM has no Primary Refresh Token to mint against. Confirm with dsregcmd /status on the device that AzureAdJoined : YES and AzureAdPrt : YES.

  • MsalServiceException: WAM_provider_error_... / IncorrectConfiguration — one of three Entra app-reg knobs is missing. The MSAL message text points only at “invalid redirect URI” but the same error fires for all three. Verify each in the Entra admin center (App registrations > <your app> > Authentication):

    1. Redirect URI ms-appx-web://microsoft.aad.brokerplugin/<client-id> exists under the Mobile and desktop applications card (not “Web”).
    2. Advanced settings → Allow public client flows is Yes.
    3. API permissions → Grant admin consent for has been clicked (status column green checks, not yellow warnings). See Step 1 for the canonical setup.
  • Upload rejected by ChainDB: ... (server-side rejection) — the agent acquired a token but the backend’s OIDC verifier rejected it. Almost always one of: the backend OIDC_ISSUER_URL / OIDC_AUDIENCE doesn’t match the values from Step 1, or requestedAccessTokenVersion is not 2 in the Entra app manifest (which would make Entra mint v1 tokens with the wrong issuer + audience format). Re-check the values you sent to Cloud Ops.

  • type=ready shows in Sentry but no follow-up type=upload — the device may not be able to reach the capture or privacy-rules endpoint, or capture may be paused by the customer control. The agent holds captures until it has current or cached privacy rules. Confirm egress to https://arbium.<customer-domain>/functions/v1/health, then ask Cloud Ops to check the customer capture switch and the /functions/v1/blocklist endpoint.

  • No row in public.auth_identities — same root cause as above, or the Entra tokens are minting against a different tenant than the one Cloud Ops seeded.

Skip this section if Cloud Ops did not enable the fleet console in this deployment.

The smoke test for the admin UI is just: sign in, confirm the dashboard loads, confirm a non-admin lands on /forbidden. There is no per-device setup — admins use a browser.

  1. Pick two test users in the customer tenant. One who is a member of a SCIM-provisioned Admins security group from Step 1, and one who is not. Both must exist in the tenant where the Arbium Admin app registration lives, and provisioning must have synced the admin user and Admins group before the admin should be allowed.
  2. Open the admin URL Cloud Ops sent you (e.g. https://arbium.<customer-domain>/admin) in a private browser window. The page should redirect to Microsoft sign-in.
  3. Sign in as the admin. After consent, you land on the dashboard, which shows enrolled users (from Microsoft Graph), enrolled devices (from Intune Graph), and live capture counts (from the Arbium backend).
  4. Sign in as the non-admin (different private window). You should land on /forbidden, not the dashboard.

If anything is off, match the symptom and report the specifics to Cloud Ops — they have the matching server-side diagnoses in their Step 4:

  • AADSTS50011 “reply URL does not match” on the Microsoft sign-in page — the Redirect URI you registered does not byte-match https://arbium.<customer-domain>/admin/api/auth/callback. Re-check Step 1’s admin-UI section 1 and confirm with Cloud Ops what ingress.host resolved to.
  • AADSTS65001 consent_required — admin consent was not granted on the admin Entra app’s API permissions. Go back to Step 1’s admin-UI section 4 and click Grant admin consent for <tenant>.
  • invalid_client — the client secret expired or the wrong client ID landed in the Helm values. Mint a new secret (Step 1’s admin-UI section 3), forward the value to Cloud Ops.
  • Sign-in succeeds, every admin lands on /forbidden — either SCIM provisioning has not synced the user/group yet, the user is not actually in a provisioned Admins security group, or Cloud Ops loaded the wrong Object ID into scim.scimAdminGroupIds. Confirm provisioning status and group membership in Entra, then ask Cloud Ops to read back SCIM_ADMIN_GROUP_IDS from the running pod.
  • Sign-in succeeds, dashboard shows Failed to load users/devices — same root cause as consent_required. The two *.All delegated scopes need admin consent. Re-check Step 1’s admin-UI section 4.

The pipeline is proven end-to-end for one user: policy and MSI installed, agent acquired an Entra token, captures landing in the backend, UPN attribution correct. If the Admin UI was enabled, an admin can sign in and a non-admin is correctly blocked.

Expand the device group scope in Intune from the pilot group to the broader rollout group. Same policy, same MSI, same config — they just apply to more devices. Watch the public.captures table for a few days to confirm the wider rollout stays healthy.