Closing USB Exception Tickets With Self-Expiring Device Control
Replace manual USB exception approvals with time-boxed Entra ID groups, Defender device control, and an auto-expiry runbook that closes the loop itself.

This playbook covers
Table of Contents
Table of contents
Removable media requests are one of the most predictable tickets in any Security & Compliance queue. A contractor needs to copy a CAD file to a USB drive. A field engineer needs to load firmware onto a stick. A finance analyst needs to hand over an encrypted drive to an auditor. Every one of these requests currently forces a human to make a risk decision, edit a policy, and then somehow remember to undo it.
The Old Way: the user emails the helpdesk. L1 cannot approve a security exception, so it escalates to L2 or the security team. Someone opens a Group Policy
The New Way: the exception is time-boxed at the moment it is granted. A self-service form triggers an approval, the approval adds the requester to a security group with an expiry timestamp attached, a device control policy reads that group in near real time, and a scheduled automation removes the membership the second the clock runs out. No technician has to remember anything, and the audit trail writes itself. This article shows exactly how to build that pipeline using Microsoft Entra ID
#Prerequisites and Permissions
Confirm the following before you touch a production device control profile:
- Entra ID role: Privileged Role Administrator or Security Administrator to create groups and define custom security attributes. Attribute definition requires the Attribute Definition Administrator role specifically; do not assign Global Administrator for this task.
- Defender for Endpoint / Intune role: Endpoint Security Manager (or a custom role with
microsoft.intune/deviceConfigurations/createandupdatepermissions) to publish and assign the device control profile. - Automation permissions: an Automation Account with a system-assigned managed identity granted
GroupMember.ReadWrite.AllandCustomSecAttributeAssignment.ReadWrite.AllGraph application permissions, consented by a Global Administrator, scoped only to the two groups this workflow touches via Administrative Units where possible. - Log Analytics: a workspace with a custom table (or the Defender XDR advanced hunting connector) to receive grant and revoke events for audit evidence.
- Test scope: a pilot Entra ID group of no more than 25 users on Windows 11 devices, tagged
pilot-usb-exception, before this touches the production device control baseline. - Blast radius: changes only affect removable storage read/write permission for members of the exception group. It does not alter Conditional Access, does not touch BitLocker, and does not affect users outside the pilot tag during the test window.
#Implementation Steps
#Step 1 — Create the two control groups
Action: create SG-USB-Exception-Requested and SG-USB-Exception-Approved as security groups via Graph.
1POST https://graph.microsoft.com/v1.0/groups
2{
3 "displayName": "SG-USB-Exception-Approved",
4 "mailEnabled": false,
5 "mailNickname": "sg-usb-exception-approved",
6 "securityEnabled": true,
7 "description": "Time-boxed removable storage exception - do not add members manually"
8}Expected result: HTTP 204 on both calls. Evidence: Entra ID audit log shows Add member to group initiated by the Automation service principal, not a human account.
#Step 5 — Publish the Device Control policy in Intune / Defender for Endpoint
Action: create a Removable Storage Access Control profile that denies write access by default and grants read/write to the exception group. This is delivered as an Intune Settings Catalog device control profile referencing the group ID from Step 1.
1{
2 "name": "Removable-Storage-Default-Deny",
3 "platform": "windows10",
4 "technologies": "mdm",
5 "settings": [
6 {
7 "settingInstance": {
8 "settingDefinitionId": "device_vendor_msft_policy_config_defender_removablediskdenywriteaccess",
9 "choiceSettingValue": { "value": "1" }
10 }
11 }
12 ],
13 "assignments": [
14 { "target": { "groupId": "{allDevicesExcludingExceptionGroupId}" } }
15 ]
16}The exception profile mirrors this with value: 0 (deny disabled) assigned to SG-USB-Exception-Approved, and Intune’s conflict resolution ensures the exception profile wins by assignment priority. Expected result: policy shows as Succeeded on the pilot devices within 15 minutes of the next check-in. Evidence: device configuration profile status report exported from Intune, and a matching DeviceEvents row in Defender advanced hunting with ActionType == "RemovableStoragePolicyTriggered".
#Step 6 — Deploy the auto-expiry runbook
Action: publish a PowerShell 7.2 runbook in Azure Automation, scheduled every 15 minutes, using the managed identity to remove expired members and log the eviction.
1Connect-MgGraph -Identity
2Select-MgProfile -Name "v1.0"
3
4$groupId = "<approved-group-object-id>"
5$now = [datetime]::UtcNow
6$members = Get-MgGroupMember -GroupId $groupId -All
7
8foreach ($member in $members) {
9 $user = Get-MgUser -UserId $member.Id -Property "customSecurityAttributes"
10 $expiryRaw = $user.CustomSecurityAttributes.AdditionalProperties.SecurityOps.usbExceptionExpiryUtc
11 if (-not $expiryRaw) { continue }
12
13 $expiry = [datetime]::Parse($expiryRaw).ToUniversalTime()
14 if ($expiry -lt $now) {
15 Remove-MgGroupMemberByRef -GroupId $groupId -DirectoryObjectId $member.Id
16
17 $logBody = @{
18 userId = $member.Id
19 groupId = $groupId
20 expiredAt = $expiryRaw
21 evictedAt = $now.ToString("o")
22 action = "AutoRevoked"
23 } | ConvertTo-Json
24
25 Invoke-RestMethod -Method Post -Uri $env:LOG_ANALYTICS_INGESTION_URI -Body $logBody -ContentType "application/json"
26 Write-Output "Revoked USB exception for $($member.Id) at $now"
27 }
28}Expected result: expired users are removed within one 15-minute cycle of their expiry timestamp. Expected output example: Revoked USB exception for 3f1a2b4c-... at 01/15/2025 18:04:11. Evidence: runbook job history (Succeeded status) and the corresponding Log Analytics ingestion row.
#Step 7 — Wire up monitoring
Action: build a saved KQL query against the custom log table and Defender advanced hunting to correlate grants, device events, and revocations.
1query: |
2 USBExceptionEvents_CL
3 | where TimeGenerated > ago(7d)
4 | summarize Grants = countif(Action_s == "Granted"), Revokes = countif(Action_s == "AutoRevoked") by bin(TimeGenerated, 1d)
5 | order by TimeGenerated descExpected result: a daily count of grants versus automatic revocations, used both for the health check in Step 8 and for the deflection metrics in the final section.

#Step 8 — Pilot for five business days
Action: run the full loop against the pilot group only. Watch for orphaned members (users still in the group past their expiry) and for policy application failures.
Expected result: zero orphaned members after 15 minutes past expiry, and 100% policy application success on pilot devices. Evidence: a daily export of group membership compared against the expiry attribute, retained as pilot sign-off evidence.
#Step 9 — Expand to production
Action: extend the device control assignment from the pilot device group to the full managed device population, and open the self-service form to all employees rather than the pilot cohort.
Expected result: ticket volume for the category USB Exception Request drops toward zero within one reporting cycle. Evidence: ITSM category trend report, covered in the deflection section below.
#Verification and Expected Evidence
- Query
Get-MgGroupMember -GroupId $groupIdimmediately after an approval and confirm the requester appears within 60 seconds of the Power Automate run completing. - Query Defender advanced hunting for
DeviceEvents | where ActionType == "RemovableStorageAccessRequested"on the requester’s device and confirm the action showsAllowedonly during the granted window. - Confirm the runbook job history in Azure Automation shows a Succeeded status every 15 minutes with zero unhandled exceptions over a rolling 24-hour period.
- Confirm the custom security attribute value clears or the group membership is removed within one scheduling cycle after the stamped expiry timestamp passes.
- Pull the Entra ID audit log filtered to the Automation service principal and confirm every add and remove action is attributable to the automation, not a manual technician edit.
#Rollback
If the device control profile misbehaves — for example, USB write access is granted organisation-wide instead of to the exception group — immediately unassign the exception profile in Intune and confirm the default-deny profile re-applies on next check-in (typically within 8 hours, or force with Sync-MgDeviceManagementManagedDevice for urgent cases). Disable the Power Automate flow trigger to stop new approvals from entering the pipeline. Do not delete the two Entra ID groups; instead, manually clear membership via Remove-MgGroupMemberByRef for every current member, and pause (not delete) the Automation runbook schedule so historical logs remain intact for the incident review. Rollback triggers include: policy applying the wrong deny value to more than one device, the runbook removing a user who has not reached expiry, or the managed identity’s Graph token being flagged for unusual application permission usage.
#Failure and Escalation Conditions
- If the auto-expiry runbook fails three consecutive scheduled runs (monitored via an Azure Monitor alert rule on the Automation job status), page the on-call L3 security engineer immediately — this means exceptions are not expiring and standing access risk is accumulating silently.
- If the group membership count exceeds the expected pilot or production ceiling by more than 10% without a matching volume of approved flow runs, treat this as a possible manual bypass and escalate to the security incident process; audit who added the member.
- If the Intune device configuration report shows more than 5% of in-scope devices in an Error or Conflict state for over four hours, escalate to the Endpoint Security team, since this indicates a policy precedence problem that could either block legitimate business use or silently fail closed on the deny-by-default baseline.
- If a Defender for Endpoint alert fires for suspicious file activity from a device during an active USB exception window, this is a live security event, not a helpdesk ticket — escalate directly to the SOC regardless of time of day.
#Measuring Ticket Deflection
Baseline the manual process for 30 days before switching this on: capture average handle time per USB exception ticket (commonly 25–40 minutes once you include the GPO or endpoint console edit and the follow-up removal task that is frequently skipped), and total monthly ticket count for the category. After rollout, track the same category using the KQL query from Step 7 alongside the ITSM export.
1Deflection % = ((Baseline monthly tickets - Post-automation monthly tickets) / Baseline monthly tickets) x 100Most organisations running this pattern see the ticket category collapse to near zero within the first full reporting month, because the request never reaches a human queue — it resolves inside the approval card. The remaining technician time shifts from manual policy editing to reviewing the weekly grant-versus-revoke report, which is also the artefact your compliance team will ask for at the next audit cycle instead of a spreadsheet nobody trusts.
Evidence trail
Sources and verification
Primary documentation and external technical references used in this article.
- 01Microsoft Defender for Endpoint removable storage access control documentationlearn.microsoft.com
- 02Microsoft Graph groups resource referencelearn.microsoft.com
- 03Microsoft Entra custom security attributes overviewlearn.microsoft.com
- 04Azure Automation runbook execution and monitoring guidelearn.microsoft.com
Comments
Add a thoughtful note on Closing USB Exception Tickets With Self-Expiring Device Control. Comments are checked for spam and held for moderation before appearing.
Related articles
macOS
Replacing Manual Compliance Work with a Verifiable FileVault Workflow
Replace ad hoc FileVault checks with a validated, auditable macOS encryption workflow featuring rollback, verification steps and measurable compliance outcomes.
Security & Compliance
Engineer Out Standing Local Admin Requests With JIT Elevation
Standing local admin rights fail audits; this JIT elevation automation grants time-bound access and auto-revokes it, closing the ticket permanently.
Enterprise IT Management
Continuous Control Monitoring for SOC 2 Audits
How AWS Config, Okta logs and GitHub audit events feed a continuous control monitoring pipeline that replaces manual SOC 2 evidence pulls.
Security & Operations
Designing a Verifiable Security Workflow with Microsoft Defender
A bounded, five-stage Defender security operations workflow scoped to a test device group, with read-only checks, one reversible response, and a rehearsed rollback path.
Learn More About KBY
About KBY
Learn about our mission, editorial standards, and commitment to trusted engineering knowledge.
Why Trust KBY
Explore the processes and policies that ensure our publications are accurate, useful, and responsible.
Newsletter
Get our latest editorial publications, research and practical insights sent directly to your inbox.
Was this useful?
Operate smarter, with fewer recurring tickets.
Receive new operational playbooks, incident-prevention guidance, automation scripts and recovery runbooks.