Refactor description to clarify device removal process and reporting for stale Entra ID and Intune-managed devices
This commit is contained in:
@@ -4,80 +4,10 @@
|
||||
longer than a given number of days.
|
||||
|
||||
.DESCRIPTION
|
||||
Connects to Microsoft Graph and evaluates staleness in two passes:
|
||||
|
||||
1. Entra ID devices, cross-referenced with their matching Intune managed
|
||||
device (if any), matched via the device's Azure AD device ID. "Last
|
||||
activity" is the more recent of the Intune managed device's
|
||||
LastSyncDateTime (last MDM check-in) and the Entra ID device's
|
||||
ApproximateLastSignInDateTime (last sign-in with the device identity). A
|
||||
device is considered stale only when BOTH available signals are older than
|
||||
the -InactiveDays threshold, to minimize the risk of removing a device that
|
||||
is active under one signal but temporarily quiet under the other. When
|
||||
stale, the script removes the Intune managed device object (if any) and
|
||||
then the Entra ID device object itself.
|
||||
|
||||
2. Intune managed devices that have NO matching Entra ID device object at all
|
||||
(e.g. the Entra ID device was already deleted manually, or sync between
|
||||
Intune and Entra ID is broken). These are invisible to pass 1, since it is
|
||||
driven from the Entra ID device list. For these, staleness is judged purely
|
||||
by LastSyncDateTime, and only the Intune managed device object is removed
|
||||
(there is no Entra ID device object to remove).
|
||||
|
||||
Devices with no usable activity signal at all cannot be judged reliably and are
|
||||
reported as 'Unknown' rather than removed. Every row in the output has a 'Source'
|
||||
column ('EntraID' or 'Intune') so it's clear which pass found it and what was
|
||||
actually evaluated/removed. When a removal attempt fails, the 'ErrorDetail' column
|
||||
holds the underlying error message(s) so the cause is visible directly in the
|
||||
report, without needing to correlate back to the -Warning output. The 'TrustType'
|
||||
column (Entra ID rows only - 'AzureAd' cloud joined, 'ServerAd' hybrid joined,
|
||||
'Workplace' registered/BYOD) helps explain permission-related removal failures,
|
||||
since deleting a Workplace-registered device can require different rights than
|
||||
deleting a joined one. The 'AutopilotRegistered' column is purely informational -
|
||||
it flags devices that still have an active Windows Autopilot device identity, in
|
||||
case that turns out to be relevant to a removal failure, but it does not change
|
||||
whether removal is attempted. This lookup is best-effort: the Autopilot/Intune
|
||||
enrollment backend can return transient errors (e.g. HTTP 500) independently of
|
||||
the rest of the script; if it fails, the column shows 'Unknown' for every device
|
||||
instead of aborting the whole run.
|
||||
|
||||
The output only lists devices that were removed, attempted-but-failed, skipped
|
||||
(e.g. under -WhatIf), or flagged as 'Unknown' for manual review - healthy, still
|
||||
active devices are deliberately left out of the report to keep it focused on what
|
||||
needs attention. Use -Verbose to see how many active devices were excluded.
|
||||
|
||||
This script reads Windows Autopilot device identities only to populate the
|
||||
'AutopilotRegistered' column above - it never modifies or removes an Autopilot
|
||||
registration. The hardware hash entry is always left in place, so a device can
|
||||
always be re-provisioned via Autopilot later, even after its Entra ID / Intune
|
||||
objects have been cleaned up (when that succeeds).
|
||||
|
||||
Hybrid Azure AD joined devices (TrustType 'ServerAd') are never removed - their
|
||||
Entra ID device object is synced from on-premises Active Directory, and Entra ID
|
||||
rejects deleting it directly, so removal must happen by deleting/disabling the
|
||||
on-prem computer object and letting Entra Connect sync the deletion. A hybrid
|
||||
device is only mentioned (via -Verbose, not in the output) when it would
|
||||
otherwise have been flagged stale and removed - active hybrid devices are not
|
||||
called out at all, same as any other active device.
|
||||
|
||||
Because these deletions are effectively irreversible, run with -WhatIf first to
|
||||
preview exactly what would be removed - each candidate device is still reported
|
||||
individually. For a real run, instead of prompting once per device/operation, the
|
||||
script asks for a single upfront confirmation ("This will permanently remove ...
|
||||
Continue?") before touching anything; declining aborts the entire run with nothing
|
||||
removed. Pass -Confirm:$false to skip even that single prompt (e.g. for unattended/
|
||||
scheduled execution).
|
||||
|
||||
Requires an account with sufficient Entra ID / Intune role assignments (e.g. Cloud
|
||||
Device Administrator + Intune Administrator, or Global Administrator) and the
|
||||
following Microsoft Graph delegated scopes:
|
||||
Device.Read.All
|
||||
Directory.ReadWrite.All
|
||||
DeviceManagementManagedDevices.ReadWrite.All
|
||||
DeviceManagementServiceConfig.ReadWrite.All (read-only use: listing Autopilot
|
||||
device identities for the 'AutopilotRegistered' column; no Graph permission
|
||||
model exists for read-only access to this resource, so ReadWrite.All is the
|
||||
minimum available scope even though this script never writes to it)
|
||||
Connects to Microsoft Graph, finds stale Entra ID and Intune-managed devices,
|
||||
and removes the matching device records after checking their last sign-in and
|
||||
last sync activity. It also reports devices that cannot be deleted, devices with
|
||||
no reliable activity signal, and whether an Autopilot registration still exists.
|
||||
|
||||
.PARAMETER InactiveDays
|
||||
Number of days of inactivity after which a device is considered stale. Defaults to
|
||||
|
||||
Reference in New Issue
Block a user