<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: AdminPackStudio</title>
    <description>The latest articles on DEV Community by AdminPackStudio (@adminpackstudio).</description>
    <link>https://dev.to/adminpackstudio</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4167635%2F08f935ad-f91f-42f5-9f97-43e9754d3e9f.png</url>
      <title>DEV Community: AdminPackStudio</title>
      <link>https://dev.to/adminpackstudio</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adminpackstudio"/>
    <language>en</language>
    <item>
      <title>Build a small M365 + Intune home lab to practise admin skills (without touching production or your wallet)</title>
      <dc:creator>AdminPackStudio</dc:creator>
      <pubDate>Wed, 07 Oct 2026 14:15:34 +0000</pubDate>
      <link>https://dev.to/adminpackstudio/build-a-small-m365-intune-home-lab-to-practise-admin-skills-without-touching-production-or-your-2ade</link>
      <guid>https://dev.to/adminpackstudio/build-a-small-m365-intune-home-lab-to-practise-admin-skills-without-touching-production-or-your-2ade</guid>
      <description>&lt;h1&gt;
  
  
  Build a small M365 + Intune home lab to practise admin skills
&lt;/h1&gt;

&lt;p&gt;You can read about Intune all week, but things only really make sense once you've enrolled a device yourself, watched a policy not apply, and worked out why. Practising on your employer's tenant is a bad idea, and so is practising on your daily laptop. You need a small lab you're allowed to break.&lt;/p&gt;

&lt;p&gt;This is the setup I'd suggest to anyone who wants hands-on M365 and Intune admin practice. It fits on one decent laptop or desktop, costs little or nothing beyond the hardware you already own, and stays well away from production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick version (TL;DR):&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Get a tenant you control.&lt;/strong&gt; That might be a developer sandbox (if you're eligible), a product trial, or a small paid subscription. &lt;strong&gt;Check current Microsoft terms first.&lt;/strong&gt; Don't assume anything is free.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run two or three VMs&lt;/strong&gt; on Hyper-V or VirtualBox: one or two Windows 11 clients and an optional Windows Server for AD practice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create fake users and groups&lt;/strong&gt; with an obvious naming scheme, plus one break-glass admin.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Practise the basics first:&lt;/strong&gt; users, groups, licences, enrolment, one compliance policy, one config profile, one app.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep lab and production apart:&lt;/strong&gt; separate browser profile, separate accounts, separate passwords, no real data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Put cost reminders on your calendar&lt;/strong&gt; for every trial end date.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. Getting a tenant: options, and why you should check eligibility first
&lt;/h2&gt;

&lt;p&gt;The biggest misconception in home lab threads is "just grab a free E5 developer tenant." That used to be easy. &lt;strong&gt;Today, the Microsoft 365 Developer Program sandbox is only available to members who meet specific qualification paths&lt;/strong&gt; (for example, certain Visual Studio subscriptions or partner programs), and the rules have changed several times. Read the current Developer Program FAQ and eligibility pages yourself before you plan around it.&lt;/p&gt;

&lt;p&gt;Your realistic options, roughly:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Good for&lt;/th&gt;
&lt;th&gt;Watch out for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Microsoft 365 Developer Program sandbox&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full E5-style feature set, if you qualify&lt;/td&gt;
&lt;td&gt;Eligibility is restricted and changes. Check current terms. Windows licences aren't included&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Product trials&lt;/strong&gt; (for example Microsoft 365 Business Premium, Intune, or Entra ID P1/P2 trials)&lt;/td&gt;
&lt;td&gt;Time-boxed practice on a specific feature set&lt;/td&gt;
&lt;td&gt;Limited length. Some trials ask for a payment method and can &lt;strong&gt;convert to paid&lt;/strong&gt; unless you cancel. Read the terms on the signup page&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Small paid subscription&lt;/strong&gt; (one or two user licences)&lt;/td&gt;
&lt;td&gt;A lab that lasts past 30 days&lt;/td&gt;
&lt;td&gt;It's a real monthly cost. Pick the cheapest SKU that includes what you want to practise (Intune + Entra ID P1 covers most of this article)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Your employer's test tenant&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Realistic config&lt;/td&gt;
&lt;td&gt;Only with &lt;strong&gt;written permission&lt;/strong&gt;, and only if it's genuinely a test tenant&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Whichever you pick:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sign up with a new identity&lt;/strong&gt; (a fresh &lt;code&gt;*.onmicrosoft.com&lt;/code&gt; admin), not your work account.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write the trial end date down&lt;/strong&gt; the day you start, and set a reminder a few days before it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't add your real custom domain&lt;/strong&gt; to the lab. The default &lt;code&gt;onmicrosoft.com&lt;/code&gt; domain is fine for practice.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Licensing matters for what you can practise. Dynamic groups and Conditional Access need &lt;strong&gt;Entra ID P1&lt;/strong&gt; (or a bundle that includes it), and devices only enrol into Intune when the &lt;strong&gt;user has an Intune licence&lt;/strong&gt;. If a feature is missing, check licensing before you assume you've misconfigured something.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2. Hypervisor and VM layout
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Hypervisor:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hyper-V&lt;/strong&gt; is built into Windows 10/11 &lt;strong&gt;Pro, Enterprise, and Education&lt;/strong&gt; (not Home). It supports Gen 2 VMs with Secure Boot and a virtual TPM, which Windows 11 expects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VirtualBox&lt;/strong&gt; works on Windows Home, macOS (Intel), and Linux. Recent versions support virtual TPM 2.0 and Secure Boot for Windows 11 guests. Check the docs for your version.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;RAM is usually the limit.&lt;/strong&gt; 16 GB on the host is a comfortable minimum for a client and a server running at the same time. With 8 GB, run one VM at a time.&lt;/p&gt;

&lt;p&gt;A layout that works:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;VM&lt;/th&gt;
&lt;th&gt;OS&lt;/th&gt;
&lt;th&gt;vCPU / RAM / disk&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lab-w11-01&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Windows 11 Enterprise or Pro&lt;/td&gt;
&lt;td&gt;2 / 4 GB / 64 GB+ (dynamic)&lt;/td&gt;
&lt;td&gt;Main Intune client: Entra join + enrol&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;lab-w11-02&lt;/code&gt; &lt;em&gt;(optional)&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;Windows 11&lt;/td&gt;
&lt;td&gt;2 / 4 GB / 64 GB+&lt;/td&gt;
&lt;td&gt;A second client so you can compare "pilot" vs "everyone" groups&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;lab-dc01&lt;/code&gt; &lt;em&gt;(optional)&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;Windows Server (evaluation)&lt;/td&gt;
&lt;td&gt;2 / 2–4 GB / 60 GB&lt;/td&gt;
&lt;td&gt;On-prem AD, DNS, GPO practice, and later hybrid identity if you want it&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use legal media.&lt;/strong&gt; The Microsoft Evaluation Center offers time-limited evaluation editions of Windows Server and Windows Enterprise. Evaluation periods end, so plan to rebuild (good practice anyway).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windows Home can't enrol into Intune as a managed corporate device.&lt;/strong&gt; Use Pro, Enterprise, or Education in your client VMs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network:&lt;/strong&gt; use NAT or a host-only/internal switch for VM-to-VM traffic, plus outbound internet so the clients can reach Microsoft 365. Don't port-forward RDP to the internet "for convenience".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Naming:&lt;/strong&gt; prefix everything with &lt;code&gt;lab-&lt;/code&gt; (VMs, users, groups, policies). When you're looking at a screenshot later, you'll know immediately it's the lab.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Checkpoints / snapshots: use them, but know the catch
&lt;/h3&gt;

&lt;p&gt;Take a checkpoint &lt;strong&gt;before&lt;/strong&gt; enrolling a client (&lt;code&gt;20261006-clean-w11-pre-enrol&lt;/code&gt;). Reverting a VM to a point &lt;em&gt;before&lt;/em&gt; it enrolled is clean.&lt;/p&gt;

&lt;p&gt;Reverting an &lt;strong&gt;already-enrolled&lt;/strong&gt; VM to an older checkpoint is messier. The cloud still remembers the newer state, so you'll often see duplicate or stale device records in the admin center. That isn't broken, it's just what happens. Clean up stale records in your &lt;strong&gt;lab&lt;/strong&gt; tenant and re-enrol. It's a good lesson in why device naming and record hygiene matter.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Test users and groups
&lt;/h2&gt;

&lt;p&gt;Create a small, fictional org. Five to ten users is enough:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Account&lt;/th&gt;
&lt;th&gt;Role in the lab&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lab-admin-breakglass@&amp;lt;tenant&amp;gt;.onmicrosoft.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Emergency Global Admin. Long random password in your password manager. &lt;strong&gt;Exclude it from any Conditional Access you test&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lab-admin-daily@…&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your day-to-day admin. Practise using a lower role (for example Intune Administrator) instead of Global Admin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lab-helpdesk1@…&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Practise scoped/limited admin roles&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;lab-user-pilot1&lt;/code&gt;, &lt;code&gt;lab-user-pilot2&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Pilot group members&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;lab-user-std1&lt;/code&gt; … &lt;code&gt;lab-user-std4&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;"Everyone else"&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Groups to start with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;lab-sg-pilot-users&lt;/code&gt; (assigned): your first ring for every new policy&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lab-sg-all-users&lt;/code&gt; (assigned, or dynamic if you have P1)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lab-sg-devices-pilot&lt;/code&gt; (device group): practise the user-vs-device assignment difference&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lab-sg-lic-intune&lt;/code&gt; (if your tenant supports group-based licensing): assign licences by group, not by hand&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Rule:&lt;/strong&gt; every user in the lab is fake. Don't import real names, real phone numbers, or a CSV from work.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. What to practise first (in this order)
&lt;/h2&gt;

&lt;p&gt;Resist the urge to start with the scariest feature. Build up:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Users, groups, licences.&lt;/strong&gt; Create users, assign licences through a group, and check a user actually received Intune. Most "my device won't enrol" problems in a lab are licensing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enrol one Windows 11 VM.&lt;/strong&gt; Entra-join it during OOBE or from Settings → Accounts → Access work or school. Find it in the Intune admin center. Note how long it takes to appear.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One compliance policy, assigned to the pilot group.&lt;/strong&gt; Keep it simple (for example require a minimum OS version). Watch the device go from "Not evaluated" to a real state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One configuration profile from the settings catalog.&lt;/strong&gt; Pick something visible, like a desktop or lock-screen setting or a Start menu tweak, so you can confirm it applied without a log viewer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One app.&lt;/strong&gt; Deploy a Microsoft Store app to the pilot group as &lt;strong&gt;Available&lt;/strong&gt;, then &lt;strong&gt;Required&lt;/strong&gt;. See the difference from the user's side.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read the logs.&lt;/strong&gt; Entra sign-in logs, audit logs, and the device's Intune status pages. Learning to read "why didn't this apply?" is the actual job.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Roles.&lt;/strong&gt; Sign in as &lt;code&gt;lab-helpdesk1&lt;/code&gt; and see what they can and can't do. Practise least privilege on purpose.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once those feel boring, move on to harder topics (Conditional Access in report-only, update rings, Win32 apps, Autopilot). There are plenty of write-ups on each of those, so I won't repeat them here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Journal everything.&lt;/strong&gt; A two-line note per session ("Goal / what broke / what fixed it") becomes your interview story bank later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## 2026-10-06&lt;/span&gt;
Goal: enrol lab-w11-01, apply first compliance policy
Broke: device enrolled but stayed "Not evaluated" for 40 min
Fix/lesson: policy was assigned to a user group, I was checking a device group. Read the assignment tab first.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5. Keeping lab and production completely separate
&lt;/h2&gt;

&lt;p&gt;This is the part people skip, and it's the one that actually causes incidents.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Separate browser profile&lt;/strong&gt; (or a separate browser) for the lab tenant. Never have lab and work admin portals open in the same profile. It's very easy to click "Assign" in the wrong tenant.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Different names and colours.&lt;/strong&gt; Give the lab browser profile a loud theme and name it &lt;code&gt;LAB&lt;/code&gt;. Check the tenant name in the top-right of the portal before every change.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separate accounts and passwords.&lt;/strong&gt; Don't reuse your work password or MFA method name. Lab admin passwords go in your password manager under a &lt;code&gt;LAB&lt;/code&gt; folder.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't enrol your daily driver&lt;/strong&gt; or your work laptop into the lab tenant. Lab policies belong on lab VMs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't connect the lab to production.&lt;/strong&gt; No syncing your work AD, no trust relationships, no guest-inviting your work account into the lab "just to test."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No real data.&lt;/strong&gt; No exported user lists, no real mailboxes, no screenshots of production pasted into lab notes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Employer tenant = written permission&lt;/strong&gt;, every time, even if it's called "test."&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  6. Cost awareness
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trials:&lt;/strong&gt; put the end date in your calendar the day you sign up. If the trial asked for a payment method, check whether it auto-converts and cancel in time if you don't want to pay.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Paid licences:&lt;/strong&gt; one or two licences is enough. Remove spare licences you added "just to try."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud VMs&lt;/strong&gt; (if you use Azure instead of local VMs): set a &lt;strong&gt;budget alert&lt;/strong&gt;, enable &lt;strong&gt;auto-shutdown&lt;/strong&gt;, and delete resource groups you're done with. Unattached disks and public IPs still cost money after you stop a VM.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local costs:&lt;/strong&gt; disk space for checkpoints adds up quickly. Keep three or four per VM and delete old ones monthly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evaluation media:&lt;/strong&gt; time-limited. Rebuilding is free; extending past the terms isn't something to rely on.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  7. A one-month plan
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Week 1:&lt;/strong&gt; hypervisor + network, first Windows 11 VM, tenant signup, fake users and groups, journal started.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Week 2:&lt;/strong&gt; enrolment, compliance policy, settings catalog profile, one app. Break each one on purpose and fix it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Week 3:&lt;/strong&gt; roles and least privilege, sign-in and audit logs, optional &lt;code&gt;lab-dc01&lt;/code&gt; with a few OUs and GPOs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Week 4:&lt;/strong&gt; tear down and rebuild one VM from scratch in an evening. Write up three incidents from your journal as interview stories.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  8. Want the lab plan in a ready-made pack?
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Home Lab Starter Pack for Aspiring Admins&lt;/strong&gt; from Admin Pack Studio ($19) is the planning and practice side of this post in a set of Markdown playbooks: a lab map with budget tiers and network isolation, a domain controller + member build order with an OU sketch, snapshot naming and a lab journal template, practice ticket drills (seven AD/Windows drills plus four cloud-optional ones for a practice tenant) with a simple self-scoring table, and a 30-day study path geared towards interviews. It also includes a small &lt;strong&gt;read-only&lt;/strong&gt; PowerShell script that records your host's RAM, free disk, and Hyper-V status to a CSV so you can size the lab. It doesn't include ISOs or licences, and it's mostly focused on the VM/AD side, with the cloud practice kept optional.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://cashflow4375.gumroad.com/l/ivqwrn" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/ivqwrn&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Moving on to the Intune side?&lt;/em&gt; The Intune &amp;amp; M365 Admin Starter Pack ($19 launch price, normally $29) has enrolment/compliance checklists and read-only snapshot scripts you can run against your lab tenant: &lt;a href="https://cashflow4375.gumroad.com/l/joonf" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/joonf&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Admin Pack Studio. Not affiliated with Microsoft. Microsoft 365, Intune, Entra ID, Hyper-V, and Windows are Microsoft products. Program eligibility, trial terms, licensing, and portal menus change, so check current Microsoft documentation before you sign up for anything. Use only tenants and devices you're authorised to manage. Examples use placeholder names.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>homelab</category>
      <category>intune</category>
      <category>microsoft365</category>
      <category>sysadmin</category>
    </item>
    <item>
      <title>Helpdesk Tier-1 triage cards: how to build a small ticket card library (with 4 copy-ready cards)</title>
      <dc:creator>AdminPackStudio</dc:creator>
      <pubDate>Wed, 07 Oct 2026 14:09:20 +0000</pubDate>
      <link>https://dev.to/adminpackstudio/helpdesk-tier-1-triage-cards-how-to-build-a-small-ticket-card-library-with-4-copy-ready-cards-1j3g</link>
      <guid>https://dev.to/adminpackstudio/helpdesk-tier-1-triage-cards-how-to-build-a-small-ticket-card-library-with-4-copy-ready-cards-1j3g</guid>
      <description>&lt;h1&gt;
  
  
  Helpdesk Tier-1 triage cards: how to build a small ticket card library
&lt;/h1&gt;

&lt;p&gt;Most Tier-1 queues don't have a knowledge problem. They have a &lt;strong&gt;consistency&lt;/strong&gt; problem. The same ticket ("VPN says connected but I can't reach anything") gets handled four different ways by four techs. One flushes DNS, one reinstalls the client, one escalates right away, and one asks the user to "try again tomorrow."&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;triage card library&lt;/strong&gt; fixes that without a 400-page wiki. Each card is one page for one common ticket: what the user sees, what to check in order, what Tier-1 is allowed to fix, and the exact point where you stop and escalate. Ten to fifteen cards cover most of a Tier-1 day.&lt;/p&gt;

&lt;p&gt;This post covers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The card format, and why it beats long KB articles for Tier-1&lt;/li&gt;
&lt;li&gt;How to organize a small card library (naming, IDs, ownership)&lt;/li&gt;
&lt;li&gt;An intake card that every other card depends on&lt;/li&gt;
&lt;li&gt;Four copy-ready cards: MFA prompt loop, VPN with no internal access, "PC is slow," and OneDrive stuck syncing&lt;/li&gt;
&lt;li&gt;An escalation matrix and handoff note&lt;/li&gt;
&lt;li&gt;A monthly upkeep routine so the library doesn't rot&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you only want one card to start with, the earlier post on the &lt;a href="https://dev.to/adminpackstudio/a-tier-1-helpdesk-card-for-outlook-keeps-asking-for-my-password-symptoms-checks-and-when-to-3cag"&gt;"Outlook keeps asking for my password" card&lt;/a&gt; walks through a single card in depth. This one is about building the set.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Scope: Windows 10/11, Microsoft 365, Entra ID (Azure AD) accounts. Menu names and commands move around, so check every card against your own build, tools, and policies before you publish it to your team. Only work tickets for users and devices you're authorized to support.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  1. Why cards beat long KB articles for Tier-1
&lt;/h2&gt;

&lt;p&gt;Long knowledge base articles are written for the person who already understands the problem. Tier-1 techs need something different. They're on a call, the user is waiting, and they need to know the next check in the order that matters.&lt;/p&gt;

&lt;p&gt;A good card is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Short.&lt;/strong&gt; One screen, or one printed page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ordered.&lt;/strong&gt; The checks run cheapest and most decisive first, and each one says what a result means.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bounded.&lt;/strong&gt; It names what Tier-1 may fix and, just as important, what Tier-1 must not do.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escalation-aware.&lt;/strong&gt; It says exactly when to stop, who gets the ticket, and what to attach.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The format used throughout this post:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CARD &amp;lt;ID&amp;gt;: &amp;lt;the user's words, not the technical cause&amp;gt;

SYMPTOMS     what the user sees / reports
CHECKS       ordered, read-only first, each with "if X -&amp;gt; Y"
TIER-1 FIXES only what your playbook allows
DO NOT       the common mistakes that make things worse
ESCALATE     specific triggers -&amp;gt; specific queue
ATTACH       what Tier-2 needs so they don't call the user back
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Name cards with &lt;strong&gt;the user's words&lt;/strong&gt; ("PC is slow," "VPN connected but nothing works"), not the root cause ("DNS suffix misconfiguration"). The tech searches for what the user said, because the cause isn't known yet.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Organizing a small card library
&lt;/h2&gt;

&lt;p&gt;You don't need a fancy tool. A folder of Markdown files, a OneNote section, a Confluence space, or a set of ticket macros all work. What matters is structure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Group cards into four shelves:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Shelf&lt;/th&gt;
&lt;th&gt;Example cards&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0. Intake &amp;amp; rules&lt;/td&gt;
&lt;td&gt;Intake script, priority rubric, escalation matrix, note template&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1. Identity &amp;amp; sign-in&lt;/td&gt;
&lt;td&gt;Password doesn't work, MFA prompt loop, repeated Office password prompt, VPN no internal access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2. Endpoint basics&lt;/td&gt;
&lt;td&gt;PC is slow, disk full, Wi-Fi with no internet, printer, dock/monitor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3. M365 apps&lt;/td&gt;
&lt;td&gt;Outlook can't send, Outlook search, Teams audio, OneDrive stuck, "I lost a file"&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Give every card a short ID&lt;/strong&gt; (&lt;code&gt;ID-02&lt;/code&gt;, &lt;code&gt;EP-01&lt;/code&gt;, &lt;code&gt;M365-04&lt;/code&gt;). Then a ticket note can say "Ran EP-01 checks 1–4," and the next tech knows exactly what was done.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Put a header on every card:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ID: EP-01   Owner: &amp;lt;team/lead&amp;gt;   Last reviewed: &amp;lt;date&amp;gt;   Applies to: Win 10/11
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An owner and a review date are what keep a card library alive. Cards without them quietly go stale.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Start small.&lt;/strong&gt; Pull your last 30 days of tickets, sort by category, and write cards for the top 8–10. That usually covers most of the volume. Add a card only when the same ticket shows up three times without one.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. The intake card (every other card depends on it)
&lt;/h2&gt;

&lt;p&gt;Most bad escalations aren't caused by bad troubleshooting. They're caused by missing basics. An intake card makes sure every ticket starts with the same facts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CARD IN-00: Intake (use on every ticket)

ASK
1. Who: name + email/UPN. Verify identity per YOUR org's procedure.
2. Device: name or asset tag (if it's an endpoint issue).
3. Goal: what are you trying to do?
4. Error: exact text or a screenshot. "It doesn't work" isn't an error.
5. Since when? What changed? (password, new laptop, travel, VPN, update)
6. Where: office / home / hotel, wired / Wi-Fi, on VPN or not.
7. Impact: just you, your team, or customers?

DECIDE
- Many users, same symptom -&amp;gt; stop. Tell your lead / check service health.
- Security smell (unexpected MFA prompts, odd inbox rules, "I clicked a link")
  -&amp;gt; follow the security procedure. Don't troubleshoot it as a normal ticket.
- Otherwise -&amp;gt; pick the matching card.

NEVER
- Ask for a password in chat, email, or on the phone.
- Bypass MFA or Conditional Access "as a favor."

DONE WHEN
Another tech could pick up this ticket without calling the user back for basics.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That last line is the whole test for good intake.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Four copy-ready Tier-1 cards
&lt;/h2&gt;

&lt;p&gt;These are written to be pasted into your KB and edited. Replace the tool names, queues, and allowed actions with your own.&lt;/p&gt;

&lt;h3&gt;
  
  
  Card ID-03: MFA prompt loop / "it keeps asking me to approve"
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CARD ID-03: MFA prompt loop / endless "approve sign-in"

SYMPTOMS
- Authenticator push arrives, user approves, and sign-in asks again
- "Try another way" goes nowhere
- Often after: new phone, restored phone backup, reinstalled Authenticator

CHECKS (in order)
1. Did the user START this sign-in? If they're getting pushes they didn't
   trigger -&amp;gt; STOP. Treat as possible account compromise. Security procedure.
2. Right account in Authenticator? (work account, not a personal one)
3. Number matching shown? Is the user entering the number from the screen,
   or only tapping "Approve"?
4. Phone time set automatically? (codes fail when the clock drifts)
5. New phone recently? The old phone may still be the registered method.
6. Can they sign in using a code (OTP) instead of a push?

TIER-1 FIXES (only if your role and playbook allow)
- Have the user use the code option instead of push.
- Walk them through re-adding the work account in Authenticator ONLY via
  your org's supported registration flow, after identity is verified.

DO NOT
- Remove or reset MFA methods without verified identity and the right role
- Approve or relay prompts on the user's behalf
- Reset the password to "fix" an MFA loop (it rarely helps)

ESCALATE WHEN
- Unrequested prompts / suspected MFA fatigue        -&amp;gt; Security, now
- Method reset needed and Tier-1 isn't allowed       -&amp;gt; Identity admin
- "Blocked by policy" / Conditional Access wording   -&amp;gt; Identity / CA owner

ATTACH
- Time of last attempt, app/browser used, exact error or screenshot,
  phone change details, whether the user started each prompt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The most important line is check 1. An MFA loop the user didn't start isn't a helpdesk ticket. It's a security event.&lt;/p&gt;

&lt;h3&gt;
  
  
  Card ID-04: VPN connected but no internal resources
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CARD ID-04: VPN says "connected" but file shares / intranet don't work

SYMPTOMS
- VPN client shows connected
- Internal sites, mapped drives, or apps time out
- Internet browsing may still work (split tunnel) or may not

CHECKS (in order)
1. Scope: one user or many? Many -&amp;gt; lead / network team. Stop.
2. One resource or all internal resources?
   One -&amp;gt; could be that app/server, or the user's access to it.
3. Name vs address: run  nslookup &amp;lt;internal-name&amp;gt;
   Fails -&amp;gt; likely DNS over the VPN. Try the full name (server.corp.example).
4. Read-only network info:  ipconfig /all
   Does the VPN adapter have an IP and the expected DNS servers?
5. Another VPN, a "privacy" VPN, or a security tool also running?
6. Right VPN profile / gateway for this user's group or region?
7. Did VPN MFA actually complete, or is the client stuck half-connected?

TIER-1 FIXES
- Disconnect fully, close the client, reconnect.
- Turn off any other VPN or proxy and retest.
- ipconfig /flushdns, then retest by full name (FQDN).
- Reboot once.
- Reinstall the VPN client ONLY from your approved source, and only after
  confirming the profile is correct.

DO NOT
- Edit hosts files or hard-code DNS on the user's laptop
- Install a different VPN client from the internet
- Add the user to network/VPN groups yourself unless that's your role

ESCALATE WHEN
- Multiple users, same resource                   -&amp;gt; Network team
- Adapter has no DNS servers / wrong subnet       -&amp;gt; Network team
- User lacks access to the resource itself        -&amp;gt; App owner / access request
- Works on hotspot, fails on home network         -&amp;gt; Tier-2 (likely IP conflict
                                                     or router issue; document)

ATTACH
- ipconfig /all output, nslookup result, resource(s) affected,
  network type (home/hotel/office), VPN client version, time of test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check 3 settles most of these. If the name won't resolve but the full name or IP works, it's DNS, not "the VPN is broken."&lt;/p&gt;

&lt;h3&gt;
  
  
  Card EP-01: "My PC is slow"
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CARD EP-01: "My computer is slow"

SYMPTOMS
- Apps hang, long boot, fan loud, "Not responding"

CHECKS (in order)
1. Slow at everything, or one app? One app -&amp;gt; that app's card / vendor.
2. Task Manager &amp;gt; Processes: sort by CPU, Memory, Disk. Note the top 3.
3. Free space on C:. Under ~10% free is a red flag.
4. Last reboot (Task Manager &amp;gt; Performance &amp;gt; CPU &amp;gt; Up time).
   Days or weeks? Pending updates?
5. Anything new: an install, update, or browser extension?
6. Anything suspicious: pop-ups, unknown processes, security alerts?
   -&amp;gt; STOP. Security procedure. Don't "clean it up" yourself.

TIER-1 FIXES
- Reboot (a real restart, not just closing the lid).
- Close runaway apps; trim browser tabs and extensions.
- Free disk space: Storage Sense / Disk Cleanup, Recycle Bin, Downloads.
- Install pending updates if policy allows.
- On managed devices: sync from Company Portal / Settings rather than
  disabling management components.

DO NOT
- Install "PC optimizer" or registry-cleaner tools
- Disable antivirus / Defender to "speed it up"
- Delete files you can't identify, or user data without consent

ESCALATE WHEN
- Disk health warnings, or drive always near full on a standard image -&amp;gt; Tier-2 / hardware
- Malware suspicion                                                  -&amp;gt; Security
- Repeated high CPU from a managed/security agent                    -&amp;gt; Endpoint team
- Hardware age/spec clearly below standard                           -&amp;gt; Lead (refresh)

ATTACH
- Top processes (CPU/Mem/Disk), free space, uptime, recent changes,
  what you already tried
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Card M365-04: OneDrive stuck on "processing changes"
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CARD M365-04: OneDrive stuck syncing / "processing changes" forever

SYMPTOMS
- Sync icon keeps spinning; files show pending or have a red X
- "Processing changes" or "Looking for changes" for hours

CHECKS (in order)
1. Click the OneDrive cloud icon. Is there a specific error or file listed?
   Screenshot it.
2. Free disk space on the device.
3. Problem file names/paths: very long paths, unusual characters,
   or files open/locked in another app.
4. A huge folder just added or moved? (it may just be slow, not stuck)
5. Can the user open the same files at office.com / in the browser?
   Yes -&amp;gt; the cloud copy is fine; the problem is the local client.
6. Shared library: does the user still have permission to that site?

TIER-1 FIXES
- Pause sync, wait a minute, resume.
- Fully quit OneDrive (cloud icon &amp;gt; Settings &amp;gt; Pause/Quit), reopen.
- Close apps holding the problem file; rename it if the name/path is the issue.
- Free up disk space.
- Make sure the OneDrive client is up to date.

DO NOT
- Unlink the account or delete the local OneDrive folder as a first step
- "Fix" a conflict by deleting one copy before confirming which one is current
- Move the user's data around without telling them

ESCALATE WHEN
- Files exist locally but not in the cloud, and the user needs them  -&amp;gt; Tier-2 (data risk)
- Permission errors on a SharePoint library                          -&amp;gt; Site owner / Tier-2
- Storage quota warnings                                             -&amp;gt; M365 admin
- Unlink/reset is the next step and your playbook reserves it        -&amp;gt; Tier-2

ATTACH
- Error text/screenshot, affected paths, free disk space,
  browser test result, client version, what you already tried
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check 5 is the OneDrive version of the Outlook web test. If the files look right in the browser, the data is safe, and you're only fixing the sync client.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. The escalation matrix
&lt;/h2&gt;

&lt;p&gt;Cards tell a tech &lt;em&gt;when&lt;/em&gt; to escalate. A single matrix tells them &lt;em&gt;where&lt;/em&gt;. Keep it on its own page and link every card to it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ESCALATION MATRIX (edit queue names to match yours)

Trigger                                              -&amp;gt; Queue
-----------------------------------------------------------------------------
Many users, same symptom                             -&amp;gt; Lead + service health
Suspected compromise / unrequested MFA / phishing    -&amp;gt; Security (immediately)
Sign-in blocked: "policy", "compliant", "managed"    -&amp;gt; Identity / CA owner, or
                                                        Endpoint / Intune admin
Device missing from management / enrollment broken   -&amp;gt; Endpoint / Intune admin
Network: DNS, VPN gateway, Wi-Fi floor-wide          -&amp;gt; Network team
App-specific access or data                          -&amp;gt; App owner
Possible data loss (sync, deleted files)             -&amp;gt; Tier-2, flagged as data risk
Hardware failure                                     -&amp;gt; Tier-2 / hardware / RMA
Card's fixes done, problem back within a day         -&amp;gt; Tier-2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Handoff note&lt;/strong&gt; (paste into the escalation):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Escalating to: &amp;lt;queue&amp;gt;        Card used: &amp;lt;ID&amp;gt;, checks 1–&amp;lt;n&amp;gt;
User / UPN:                   Device:
Business impact:
Ruled out:
Tried (and result):
Key errors + timestamps:
Attachments: (screenshots, ipconfig/dsregcmd output, etc.)
User available: &amp;lt;window&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;"Card used: ID-04, checks 1–7" tells Tier-2 more in one line than a paragraph of "tried everything."&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Keeping the library alive (monthly, ~30 minutes)
&lt;/h2&gt;

&lt;p&gt;Card libraries die quietly. Here's a routine that keeps one useful:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pull the top 10 ticket categories&lt;/strong&gt; for the month. Any without a card? Draft one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check reopened and bounced tickets.&lt;/strong&gt; If a card's fixes keep failing, the order or the escalation trigger is wrong. Fix the card, not the tech.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ask Tier-2 one question:&lt;/strong&gt; "Which escalations arrived missing something?" Add that item to the card's ATTACH list.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Update menu names&lt;/strong&gt; after major Windows or Microsoft 365 changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bump the "Last reviewed" date&lt;/strong&gt; on every card you touched, and archive cards for tickets that no longer happen.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A useful signal to watch: &lt;strong&gt;escalations that bounce back to Tier-1 for missing information.&lt;/strong&gt; When that number drops, the cards are working.&lt;/p&gt;




&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What's the difference between a triage card and a KB article?&lt;/strong&gt;&lt;br&gt;
A KB article explains a topic. A triage card drives a live ticket: ordered checks, allowed fixes, and a hard stop for escalation. Many teams keep both and link the card to the deeper article.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How many cards does a Tier-1 team need?&lt;/strong&gt;&lt;br&gt;
Start with 8–10 that match your top ticket categories. Most small teams level off around 15–25. If a card hasn't been used in six months, archive it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Should Tier-1 be allowed to reset passwords and MFA?&lt;/strong&gt;&lt;br&gt;
That's your org's decision, and it should be written down. If it is allowed, it should always come after identity verification. The cards above keep it behind "only if your role and playbook allow."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I automate data collection for cards?&lt;/strong&gt;&lt;br&gt;
Yes, carefully. A &lt;strong&gt;read-only&lt;/strong&gt; script that gathers local info (OS, uptime, disk space, network config, join state) and saves it to a file saves a lot of back-and-forth. Keep collection scripts read-only so Tier-1 can run them without risk.&lt;/p&gt;




&lt;h2&gt;
  
  
  Want a ready-made card library?
&lt;/h2&gt;

&lt;p&gt;The cards above are samples of the format used in the &lt;strong&gt;IT Helpdesk Tier-1 Break/Fix Runbook Pack&lt;/strong&gt; ($24) from Admin Pack Studio. It's a ready-made version of the library described in this post:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Intake and escalation rules:&lt;/strong&gt; an intake script, a priority rubric, escalation triggers, and verification steps before any password reset&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identity and sign-in cards:&lt;/strong&gt; password problems, MFA loops, work-account sync errors, VPN with no internal access, guest access to SharePoint links&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Endpoint cards:&lt;/strong&gt; slow PC, disk full, Wi-Fi with no internet, printers, docks and monitors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Microsoft 365 cards:&lt;/strong&gt; Outlook send/receive and search, Teams audio/video, OneDrive sync, "I lost a file"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notes and handoff templates&lt;/strong&gt; plus a weekly queue hygiene routine&lt;/li&gt;
&lt;li&gt;One &lt;strong&gt;read-only&lt;/strong&gt; PowerShell local snapshot script for Windows triage. It only reads: no password changes, no device actions, no Graph writes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of it is plain Markdown, so you can paste it into whatever KB or ticket tool you use.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://cashflow4375.gumroad.com/l/tezla" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/tezla&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If a lot of your escalations end up at &lt;strong&gt;Intune enrollment or device compliance&lt;/strong&gt;, the &lt;em&gt;Intune &amp;amp; M365 Admin Starter Pack&lt;/em&gt; covers that side for admins ($19 during launch week, normally $29): &lt;a href="https://cashflow4375.gumroad.com/l/joonf" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/joonf&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You don't need either one. The intake card, the four cards, and the matrix above are enough to start a library this week.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Admin Pack Studio. Not affiliated with or endorsed by Microsoft. For IT staff authorized to support their organization's users and devices. Follow your own policies, and check current Microsoft documentation for menu names and behavior.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>helpdesk</category>
      <category>itsupport</category>
      <category>sysadmin</category>
      <category>microsoft365</category>
    </item>
    <item>
      <title>Windows Autopilot ESP Stuck? The Complete Runway Guide: Hash, Profile Assignment, Blocking Apps, Network/TLS, and CA Deadlocks</title>
      <dc:creator>AdminPackStudio</dc:creator>
      <pubDate>Wed, 07 Oct 2026 14:08:29 +0000</pubDate>
      <link>https://dev.to/adminpackstudio/windows-autopilot-esp-stuck-the-complete-runway-guide-hash-profile-assignment-blocking-apps-28p5</link>
      <guid>https://dev.to/adminpackstudio/windows-autopilot-esp-stuck-the-complete-runway-guide-hash-profile-assignment-blocking-apps-28p5</guid>
      <description>&lt;h1&gt;
  
  
  Windows Autopilot ESP Stuck? The Complete Runway Guide
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Short version:&lt;/strong&gt; when Windows Autopilot stalls on the Enrollment Status Page (ESP), the cause almost always sits on one of five layers: &lt;strong&gt;registration (hash)&lt;/strong&gt;, &lt;strong&gt;profile assignment&lt;/strong&gt;, &lt;strong&gt;ESP blocking design&lt;/strong&gt;, &lt;strong&gt;network/TLS&lt;/strong&gt;, or &lt;strong&gt;Conditional Access&lt;/strong&gt;. Work through them in that order and collect evidence with read-only tools before anyone resets the device.&lt;/p&gt;

&lt;p&gt;This is the long version of an earlier, shorter triage checklist. That one is a single page for the moment a laptop is stuck. This one is the &lt;strong&gt;runway&lt;/strong&gt;: what each layer does, how it fails, what you'll see, how to prove it, and how to stop it coming back on the next dock day.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;No Microsoft affiliation. Operational guidance for admins who are authorized to manage their tenant and devices. Check current Microsoft Learn docs for your OS build and cloud, because endpoints and ESP behavior change over time.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;How Autopilot and ESP actually fit together&lt;/li&gt;
&lt;li&gt;Before you touch anything: capture the state&lt;/li&gt;
&lt;li&gt;Layer 1: Hardware hash and Autopilot registration&lt;/li&gt;
&lt;li&gt;Layer 2: Deployment profile assignment&lt;/li&gt;
&lt;li&gt;Layer 3: ESP blocking apps, policies, and timeouts&lt;/li&gt;
&lt;li&gt;Layer 4: Network, proxy, and TLS inspection&lt;/li&gt;
&lt;li&gt;Layer 5: The Conditional Access enrollment deadlock&lt;/li&gt;
&lt;li&gt;Hybrid join sidebar: when ESP takes the blame for AD&lt;/li&gt;
&lt;li&gt;Read-only diagnostics toolkit&lt;/li&gt;
&lt;li&gt;Symptom to layer lookup table&lt;/li&gt;
&lt;li&gt;Escalation note template&lt;/li&gt;
&lt;li&gt;Making dock day boring: prevention habits&lt;/li&gt;
&lt;li&gt;FAQ&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  How Autopilot and ESP actually fit together
&lt;/h2&gt;

&lt;p&gt;People say "Autopilot is stuck" for problems in very different places, so it helps to split the flow into stages:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Stage&lt;/th&gt;
&lt;th&gt;What happens&lt;/th&gt;
&lt;th&gt;What has to be true&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OOBE network&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Device gets online&lt;/td&gt;
&lt;td&gt;Reachable internet, no captive portal, sane clock&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Profile download&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Device asks the Autopilot service "who am I?"&lt;/td&gt;
&lt;td&gt;Hash registered &lt;strong&gt;and&lt;/strong&gt; a deployment profile assigned to this device&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Identity / join&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;User signs in (user-driven) or device authenticates (self-deploying / pre-provisioning)&lt;/td&gt;
&lt;td&gt;Join type matches profile; TPM attestation works where required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MDM enrollment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Device enrolls into Intune&lt;/td&gt;
&lt;td&gt;License, MDM user scope, CA doesn't block enrollment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ESP device phase&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Device-targeted policies, certificates, and blocking apps install&lt;/td&gt;
&lt;td&gt;Assignments reach the &lt;em&gt;device&lt;/em&gt;; content downloads; apps detect correctly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ESP account phase&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;User-targeted policies and apps&lt;/td&gt;
&lt;td&gt;Assignments reach the &lt;em&gt;user&lt;/em&gt;; CA allows token issuance for the session&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Desktop&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;User can work&lt;/td&gt;
&lt;td&gt;ESP released&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two things to keep in mind for the rest of this guide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ESP only waits for what it's told to wait for.&lt;/strong&gt; If a blocking app or policy never succeeds, or never &lt;strong&gt;targets&lt;/strong&gt; the device, ESP keeps waiting until it times out.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A failure in an early stage often shows up later.&lt;/strong&gt; A profile assignment gap can look like an ESP hang, and a CA policy can look like a broken app. The layered order exists so you don't fix the wrong thing.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Before you touch anything: capture the state
&lt;/h2&gt;

&lt;p&gt;The most expensive mistake in Autopilot troubleshooting is resetting a device &lt;em&gt;before&lt;/em&gt; you know why it failed. A reset removes local evidence, and if the cause is assignment, network, or CA, the next attempt fails the same way.&lt;/p&gt;

&lt;p&gt;Capture these first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] &lt;strong&gt;Serial number&lt;/strong&gt; and model&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Exact ESP text and phase&lt;/strong&gt;: "Device preparation", "Device setup", or "Account setup", plus the item it's stuck on&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Elapsed time&lt;/strong&gt; and the timeout configured in the ESP profile&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Network type&lt;/strong&gt;: corporate wired, corporate Wi-Fi, home, hotel/guest, branch&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Error code&lt;/strong&gt; if the ESP shows one (photo is fine)&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Did a sister device succeed&lt;/strong&gt; on the same network with the same profile today?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;During OOBE, &lt;strong&gt;Shift+F10&lt;/strong&gt; usually opens a command prompt (unless you've disabled it by policy). That's enough to run the read-only checks in the diagnostics section.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 1: Hardware hash and Autopilot registration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What it does
&lt;/h3&gt;

&lt;p&gt;Autopilot identifies the device from its hardware hash. No registered hash means no profile, which means a generic, consumer-style OOBE however good your Intune configuration is.&lt;/p&gt;

&lt;h3&gt;
  
  
  How it fails
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Failure&lt;/th&gt;
&lt;th&gt;What you see&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;OEM / partner never uploaded this order&lt;/td&gt;
&lt;td&gt;Generic OOBE on brand-new hardware&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hash captured but CSV import failed or was never done&lt;/td&gt;
&lt;td&gt;Device absent from Autopilot devices list&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Motherboard replaced after registration&lt;/td&gt;
&lt;td&gt;Device behaves as unregistered or mismatched&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Duplicate / stale objects from a prior life&lt;/td&gt;
&lt;td&gt;Wrong profile, wrong Group Tag, confusing assignment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Group Tag typo (&lt;code&gt;CORP-STD&lt;/code&gt; vs &lt;code&gt;CORP_STD&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Registered but never lands in the dynamic group&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  How to prove it
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Look the &lt;strong&gt;serial&lt;/strong&gt; up in the Autopilot devices list. Is it there, and is there exactly &lt;strong&gt;one&lt;/strong&gt; entry?&lt;/li&gt;
&lt;li&gt;Check &lt;strong&gt;Group Tag&lt;/strong&gt; / Order ID against the dynamic group rule character for character.&lt;/li&gt;
&lt;li&gt;Check the device's &lt;strong&gt;profile status&lt;/strong&gt;. "Not assigned" after a sync points to Layer 2, not Layer 1.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How to fix it
&lt;/h3&gt;

&lt;p&gt;Register the hash (OEM/partner, or capture and import in your normal process), wait for the service to sync, then confirm a profile is assigned &lt;strong&gt;before&lt;/strong&gt; restarting OOBE. Resetting an unregistered device won't make a profile appear.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prevention:&lt;/strong&gt; one source of truth that maps purchase order, asset tag, serial, and hash, plus a pre-ship check that every device appears with the correct tag.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 2: Deployment profile assignment
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What it does
&lt;/h3&gt;

&lt;p&gt;The deployment profile tells the device which mode to use (user-driven, self-deploying, pre-provisioning), which join type (Entra or hybrid), and how OOBE should behave. The profile has to reach the device &lt;strong&gt;before the user signs in&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The device-group vs user-group trap
&lt;/h3&gt;

&lt;p&gt;This causes more "Autopilot is haunted" tickets than anything else:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deployment profiles should target &lt;strong&gt;device groups&lt;/strong&gt; that contain Autopilot device objects, often through a dynamic rule on Group Tag or &lt;code&gt;ZTDId&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Assigning a deployment profile to a &lt;strong&gt;user&lt;/strong&gt; group doesn't work the way people expect, because during OOBE there's no user yet. The device has to be in scope on its own.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overlapping assignments&lt;/strong&gt; (the device is in two groups with two profiles) give unpredictable results. Aim for one device, one winning profile.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Dynamic group lag
&lt;/h3&gt;

&lt;p&gt;Dynamic membership is not instant. Right after registration a device may not be in the group yet, and then the profile isn't assigned yet. Testing too early causes plenty of false failures. Check membership and profile status first, then start OOBE.&lt;/p&gt;

&lt;h3&gt;
  
  
  Checklist
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Device is a &lt;strong&gt;member&lt;/strong&gt; of the targeted device group (check the group, not just the rule)&lt;/li&gt;
&lt;li&gt;[ ] Profile status for the device shows &lt;strong&gt;assigned&lt;/strong&gt;, and it's the profile you expected&lt;/li&gt;
&lt;li&gt;[ ] Mode and join type match the scenario (self-deploying needs TPM 2.0 and no user affinity; hybrid needs directory prerequisites)&lt;/li&gt;
&lt;li&gt;[ ] ESP profile targets the &lt;strong&gt;same population&lt;/strong&gt; as the deployment profile&lt;/li&gt;
&lt;li&gt;[ ] Profile names carry intent and version, e.g. &lt;code&gt;AP-UserDriven-Entra-Std-v3&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; if the device showed the &lt;em&gt;right&lt;/em&gt; branding and sign-in page, Layer 2 probably worked. If it showed a generic OOBE or the wrong join behavior, stay here.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 3: ESP blocking apps, policies, and timeouts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What it does
&lt;/h3&gt;

&lt;p&gt;ESP holds the desktop until selected apps and policies finish. Done well, users get a ready-to-work PC. Done badly, it turns every flaky installer into a dock-day outage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common ESP blockers
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Blocker&lt;/th&gt;
&lt;th&gt;Why it stalls ESP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Too many blocking apps&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Every extra app adds download time and another chance to fail&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Win32 detection rule that never matches&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;App installs fine, Intune thinks it didn't, ESP waits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Requirement rules&lt;/strong&gt; (OS build, architecture, disk) excluding the device&lt;/td&gt;
&lt;td&gt;App never applies, so "blocking" means waiting forever&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dependencies / supersedence chains&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;One failure deep in the chain stops everything&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Installer needs user context or a reboot nobody planned&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Exit codes misread; hard reboot mid-ESP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mixed app types colliding&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Different install channels fighting during provisioning&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Timeout shorter than real-world p95&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fine in the lab on gigabit, fails on branch Wi-Fi&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Design rules that keep ESP sane
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Block only what's needed before the desktop.&lt;/strong&gt; Usually security agent, Company Portal, and the bare minimum of line-of-business apps. A starter cap of around five proven apps is a reasonable first production ring.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New apps are never ESP-blocking on day one.&lt;/strong&gt; Deploy as required/available outside ESP until installs are reliable, then promote.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detection must reflect what the installer actually leaves behind.&lt;/strong&gt; Validate on a clean device, not your packaging VM.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run a timing study.&lt;/strong&gt; Ten pilot devices across office, home, and branch networks. Record minutes to ESP complete. If your p95 goes past the timeout, shrink the blocking set or fix the app before you raise the timeout.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Device ESP vs account ESP.&lt;/strong&gt; Know which phase each blocking item lands in. User-targeted items stall the &lt;em&gt;account&lt;/em&gt; phase, device-targeted items stall the &lt;em&gt;device&lt;/em&gt; phase.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  When ESP names a specific app
&lt;/h3&gt;

&lt;p&gt;Don't raise the timeout first. Check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install status for that app on that device&lt;/li&gt;
&lt;li&gt;The install command, return codes, and the detection rule against what's actually on disk or in the registry&lt;/li&gt;
&lt;li&gt;Requirements and dependencies&lt;/li&gt;
&lt;li&gt;The Intune Management Extension logs (see diagnostics)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fix the package, test it outside ESP, and only then put it back in the blocking list.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 4: Network, proxy, and TLS inspection
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why network problems look like ESP problems
&lt;/h3&gt;

&lt;p&gt;ESP downloads policy, certificates, and Win32 content from cloud endpoints. If the network quietly interferes, ESP sees "not installed yet", not "network broken". The classic sign is: &lt;strong&gt;works on the lab bench, fails at the branch or on home Wi-Fi.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Network failure modes
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Captive portal / guest Wi-Fi&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Online for the first sign-in, then content stops after the session expires&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Proxy requiring user authentication&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;OOBE and system-context downloads can't do interactive proxy auth&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TLS / SSL inspection&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Certificate mismatch on endpoints that expect the real Microsoft chain; enrollment or content download fails without a clear message&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Firewall category blocks&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Some endpoints allowed, CDN / content endpoints blocked&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DNS filtering&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Name resolution fails for content or attestation hosts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Clock skew&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Token and certificate validation fails in ways that look random&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;TPM attestation blocked&lt;/strong&gt; (self-deploying / pre-provisioning)&lt;/td&gt;
&lt;td&gt;Device can't reach the TPM manufacturer certificate endpoints and attestation fails early&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Low bandwidth + large blocking payload&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not "broken", just slower than the ESP timeout&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  What to do
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Compare with a known-good network (wired corporate or a phone hotspot). If the same device succeeds, the problem is the path, not the profile.&lt;/li&gt;
&lt;li&gt;[ ] Use the &lt;strong&gt;current&lt;/strong&gt; Microsoft network endpoint guidance for Autopilot, Entra, Intune, and Win32 content delivery in your cloud, and allowlist through your normal change process.&lt;/li&gt;
&lt;li&gt;[ ] Exclude enrollment and content endpoints from &lt;strong&gt;TLS inspection&lt;/strong&gt; where your security process allows. Inspection appliances break more provisioning than almost anything else.&lt;/li&gt;
&lt;li&gt;[ ] Keep provisioning on a network segment &lt;strong&gt;without&lt;/strong&gt; captive portals or per-user proxy auth.&lt;/li&gt;
&lt;li&gt;[ ] Check the device clock / time sync before you chase token errors.&lt;/li&gt;
&lt;li&gt;[ ] Include at least one &lt;strong&gt;branch&lt;/strong&gt; device in every ESP timing study.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If several devices enroll fine but then fail the same Win32 installs, fix delivery before you rewrite detection rules again.&lt;/p&gt;




&lt;h2&gt;
  
  
  Layer 5: The Conditional Access enrollment deadlock
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The chicken-and-egg
&lt;/h3&gt;

&lt;p&gt;A device has to &lt;strong&gt;enroll&lt;/strong&gt; before it can be &lt;strong&gt;compliant&lt;/strong&gt;. Compliance evaluation also needs time after enrollment. A broad CA policy such as &lt;em&gt;"All cloud apps → require compliant device"&lt;/em&gt; can block the sign-ins and token requests the device needs during enrollment and the ESP account phase. You get a loop: can't finish enrollment → can't become compliant → CA blocks → can't finish enrollment.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it looks like
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;ESP reaches the &lt;strong&gt;account setup&lt;/strong&gt; phase, then fails or prompts for sign-in again&lt;/li&gt;
&lt;li&gt;Errors mention the device not being compliant, managed, or registered&lt;/li&gt;
&lt;li&gt;Sign-in logs show CA &lt;strong&gt;failures&lt;/strong&gt; for the user during the provisioning window&lt;/li&gt;
&lt;li&gt;It started right after someone &lt;strong&gt;enforced&lt;/strong&gt; a CA policy that worked fine in report-only&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How to prove it
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Pull the user's &lt;strong&gt;sign-in logs&lt;/strong&gt; for the provisioning window. Which policy applied, and which grant control failed?&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;What If&lt;/strong&gt; with the user, the app, and the device platform to see which policies would apply.&lt;/li&gt;
&lt;li&gt;Check whether the policy is &lt;strong&gt;report-only&lt;/strong&gt; or &lt;strong&gt;on&lt;/strong&gt;. If report-only shows it &lt;em&gt;would&lt;/em&gt; have failed, you've found the likely future deadlock before it happens.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How to break the loop safely
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Follow current Microsoft guidance on how enrollment-related apps should be handled in "require compliant device" policies. Don't invent broad exclusions under pressure.&lt;/li&gt;
&lt;li&gt;[ ] Keep new device-compliance CA policies in &lt;strong&gt;report-only&lt;/strong&gt; until Autopilot success rates are stable.&lt;/li&gt;
&lt;li&gt;[ ] Watch &lt;strong&gt;MFA and registration requirements&lt;/strong&gt; (for example, "register or join devices" user actions) so they don't fight the OOBE sign-in.&lt;/li&gt;
&lt;li&gt;[ ] Keep &lt;strong&gt;break-glass&lt;/strong&gt; accounts excluded and monitored, as with every CA rollout.&lt;/li&gt;
&lt;li&gt;[ ] Document every exclusion with an owner and a review date.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Rule:&lt;/strong&gt; keep CA enforcement one step &lt;strong&gt;behind&lt;/strong&gt; your Autopilot success rate. Tighten after provisioning is boring, not before.&lt;/p&gt;




&lt;h2&gt;
  
  
  Hybrid join sidebar: when ESP takes the blame for AD
&lt;/h2&gt;

&lt;p&gt;Hybrid Autopilot adds failure domains: the on-prem directory, sync, and a line of sight to domain controllers. Plenty of "ESP hangs" are really hybrid prerequisites failing quietly.&lt;/p&gt;

&lt;p&gt;Check before blaming ESP:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Directory sync healthy&lt;/li&gt;
&lt;li&gt;[ ] Service connection point (SCP) configured correctly&lt;/li&gt;
&lt;li&gt;[ ] Provisioning network can reach domain controllers when the domain-join step runs&lt;/li&gt;
&lt;li&gt;[ ] Offline domain join connector / components healthy, with rights to create computer objects in the target OU&lt;/li&gt;
&lt;li&gt;[ ] Naming template respects AD / NetBIOS limits&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your apps don't strictly need hybrid join on day one, it's worth reviewing whether Entra join could be the default with hybrid as a documented exception. That's an architecture decision for your org, not a quick fix in the middle of an incident.&lt;/p&gt;




&lt;h2&gt;
  
  
  Read-only diagnostics toolkit
&lt;/h2&gt;

&lt;p&gt;Everything in this section &lt;strong&gt;reads&lt;/strong&gt; state or &lt;strong&gt;collects&lt;/strong&gt; logs. None of it enrolls, resets, wipes, or changes policy. Only run it on devices you're authorized to support.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Join and MDM state: &lt;code&gt;dsregcmd /status&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Read-only: summarize join + MDM signals&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$raw&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dsregcmd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/status&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Out-String&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$pick&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'AzureAdJoined'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'DomainJoined'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'TenantName'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'DeviceId'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'MDMUrl'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'AzureAdPrt'&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kr"&gt;foreach&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$pick&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$raw&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-match&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"(?m)^\s*&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="s2"&gt;\s*:\s*(.*)$"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s1"&gt;'{0,-14} {1}'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$Matches&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How to read it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;AzureAdJoined : NO&lt;/code&gt; after the user signed in → join stage failed (Layer 2 / identity)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;MDMUrl&lt;/code&gt; empty → not enrolled into MDM (license, MDM user scope, or CA)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AzureAdPrt : NO&lt;/code&gt; during the account phase → token problems; look at CA and network&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Autopilot and MDM event logs
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Read-only: recent Autopilot + MDM enrollment events&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$logs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@(&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s1"&gt;'Microsoft-Windows-ModernDeployment-Diagnostics-Provider/Autopilot'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s1"&gt;'Microsoft-Windows-DeviceManagement-Enterprise-Diagnostics-Provider/Admin'&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kr"&gt;foreach&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$l&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$logs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;Get-WinEvent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-LogName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$l&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-MaxEvents&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ErrorAction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;SilentlyContinue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;TimeCreated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;LevelDisplayName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;@{&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Msg'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-split&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;`n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for profile download results, enrollment errors, and repeated failures around the time the ESP stalled.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Win32 app logs (Intune Management Extension)
&lt;/h3&gt;

&lt;p&gt;Win32 installs and detection results are logged under:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C:\ProgramData\Microsoft\IntuneManagementExtension\Logs\
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;IntuneManagementExtension.log&lt;/code&gt; (and related logs in that folder) shows download progress, exit codes, and detection results. A "detection rule not satisfied" after a successful install exit code is the classic Layer 3 detection bug.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Built-in diagnostic bundle
&lt;/h3&gt;

&lt;p&gt;Windows includes an MDM diagnostics tool that &lt;strong&gt;collects&lt;/strong&gt; logs into an archive for offline review:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mdmdiagnosticstool.exe -area "DeviceEnrollment;DeviceProvisioning;Autopilot" -cab C:\Temp\ap-diag.cab
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It writes a log bundle and doesn't change device configuration. Attach the bundle to the escalation instead of resetting first.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Local snapshot to CSV
&lt;/h3&gt;

&lt;p&gt;For dock days with many devices, a small read-only script that writes join state, tenant, MDM URL, and OS version to CSV makes it easy to compare a failing device with a working one. The Autopilot pack below includes one (&lt;code&gt;Get-LocalAutopilotEspSnapshot.ps1&lt;/code&gt;). It only reads local signals and writes an optional CSV.&lt;/p&gt;




&lt;h2&gt;
  
  
  Symptom to layer lookup table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;Most likely layer&lt;/th&gt;
&lt;th&gt;First check&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Generic OOBE, no org branding&lt;/td&gt;
&lt;td&gt;1 Registration / 2 Assignment&lt;/td&gt;
&lt;td&gt;Serial in Autopilot devices; profile status&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wrong join type or mode&lt;/td&gt;
&lt;td&gt;2 Assignment&lt;/td&gt;
&lt;td&gt;Overlapping profiles; device group membership&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stuck in "Device preparation"&lt;/td&gt;
&lt;td&gt;4 Network / TPM&lt;/td&gt;
&lt;td&gt;Known-good network test; attestation reachability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stuck in "Device setup" on an app&lt;/td&gt;
&lt;td&gt;3 ESP blocker&lt;/td&gt;
&lt;td&gt;IME log; detection rule; requirements&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stuck in "Device setup" on policies/certs&lt;/td&gt;
&lt;td&gt;3 ESP / 4 Network&lt;/td&gt;
&lt;td&gt;Assignment of the blocking items; content reachability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fails in "Account setup" with sign-in loop&lt;/td&gt;
&lt;td&gt;5 CA deadlock&lt;/td&gt;
&lt;td&gt;Sign-in logs; What If; report-only results&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Works on HQ wired, fails on branch/home&lt;/td&gt;
&lt;td&gt;4 Network&lt;/td&gt;
&lt;td&gt;Proxy, TLS inspection, captive portal, bandwidth&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hybrid device fails at domain join&lt;/td&gt;
&lt;td&gt;Hybrid sidebar&lt;/td&gt;
&lt;td&gt;Directory sync, SCP, DC line of sight&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pre-provisioning (technician phase) red screen&lt;/td&gt;
&lt;td&gt;3 / 4&lt;/td&gt;
&lt;td&gt;Apps in technician phase; network; TPM&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Escalation note template
&lt;/h2&gt;

&lt;p&gt;Paste this into the ticket so the next person doesn't start from zero:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AUTOPILOT / ESP ESCALATION
Serial / model:
Autopilot registered (Y/N), Group Tag:
Device group member (Y/N), deployment profile assigned:
Mode / join type:
ESP phase + item stuck on:
Elapsed time vs ESP timeout:
Network type (and known-good network test result):
dsregcmd: AzureAdJoined / MDMUrl / AzureAdPrt:
CA sign-in log result (policy + grant failed):
Logs attached (IME / diag cab):
Sister device on same profile+network succeeded? (Y/N)
Actions taken so far (no reset yet? Y/N):
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Making dock day boring: prevention habits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pre-ship registration check&lt;/strong&gt;: every device present, one object, correct tag.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One primary profile&lt;/strong&gt; covering most of the fleet; exceptions get a second profile, not seven.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ESP blocking cap&lt;/strong&gt; with a promotion rule: only apps that have installed reliably outside ESP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timing study&lt;/strong&gt; on every major change (new blocking app, new site, new OS build).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provisioning network standard&lt;/strong&gt;: no captive portal, no user-auth proxy, TLS inspection exclusions approved.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CA changes go through report-only&lt;/strong&gt; and are checked against Autopilot sign-ins before enforcement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Written reset criteria&lt;/strong&gt;: a reset/retry happens only after the layers above are checked and evidence is collected, and always under your org's change and device policy.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why is my Autopilot device stuck on "Setting up your device for work"?&lt;/strong&gt;&lt;br&gt;
Usually an ESP blocking app or policy that never succeeds or never targets the device. Check which phase it's in, which item is pending, and the Intune Management Extension log for that app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why does Autopilot show a normal OOBE instead of my company's?&lt;/strong&gt;&lt;br&gt;
The device either isn't registered (no hash) or has no deployment profile assigned yet. Check the serial in Autopilot devices, device group membership, and profile status.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Should the deployment profile be assigned to users or devices?&lt;/strong&gt;&lt;br&gt;
Devices. The profile has to reach the device before anyone signs in, so target a device group containing the Autopilot device objects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can Conditional Access break Autopilot?&lt;/strong&gt;&lt;br&gt;
Yes. A "require compliant device" policy that also applies to the sign-ins needed during enrollment can create a loop. Validate with sign-in logs and What If, and keep new compliance policies in report-only until Autopilot is stable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can TLS inspection cause ESP failures?&lt;/strong&gt;&lt;br&gt;
Yes. Inspection can break certificate validation for enrollment and content endpoints. Exclude them according to current Microsoft guidance and your security process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Should I just increase the ESP timeout?&lt;/strong&gt;&lt;br&gt;
Only after you've fixed failing apps and confirmed content delivery. A longer timeout on a broken app just makes users wait longer for the same failure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When is resetting the device the right call?&lt;/strong&gt;&lt;br&gt;
When registration, assignment, ESP design, network, and CA all check out, the evidence is collected, and the device is in a bad local state. Do it under your org's policy and confirm hash and profile are still correct before the next OOBE.&lt;/p&gt;




&lt;h2&gt;
  
  
  Want the full Autopilot runbooks?
&lt;/h2&gt;

&lt;p&gt;This guide gives you the triage order. If you'd like the rest written down, the &lt;strong&gt;Windows Autopilot &amp;amp; ESP Ops Pack&lt;/strong&gt; ($29) from Admin Pack Studio has five markdown modules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Registration hygiene (OEM/hash paths, Group Tag strategy, duplicate cleanup, hand-off template)&lt;/li&gt;
&lt;li&gt;Deployment profiles that stick (decision matrix, assignment rules, hybrid gates, change-control snippet)&lt;/li&gt;
&lt;li&gt;ESP design and timing (blocking-set rules, configuration checklist, timing study template)&lt;/li&gt;
&lt;li&gt;Cloud vs hybrid join ops (decision prompts, migration path, exec one-pager)&lt;/li&gt;
&lt;li&gt;Seven break/fix cards (generic OOBE, ESP hangs, failing Win32, hybrid join, branch-only failures, CA deadlock, pre-provisioning)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also includes the &lt;strong&gt;read-only&lt;/strong&gt; local snapshot script mentioned above. The script reads local signals and writes an optional CSV. It does not enroll, reset, wipe, or change policy.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://cashflow4375.gumroad.com/l/hlanei" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/hlanei&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If your problem is more about enrollment and compliance than Autopilot itself, the &lt;strong&gt;Intune &amp;amp; M365 Admin Starter Pack&lt;/strong&gt; covers enrollment hygiene, baseline compliance with report-only CA phasing, and break/fix cards. It's $19 during launch week (normally $29): &lt;a href="https://cashflow4375.gumroad.com/l/joonf" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/joonf&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The checklist above works fine without either pack. Questions and war stories welcome in the comments.&lt;/p&gt;

&lt;p&gt;— Admin Pack Studio&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Not affiliated with or endorsed by Microsoft. Windows, Intune, Autopilot, and Entra are trademarks of their respective owners. Operational guidance for admins authorized to manage their tenant and devices. Test in a pilot first; provided AS-IS, no warranty.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>intune</category>
      <category>windows</category>
      <category>autopilot</category>
      <category>sysadmin</category>
    </item>
    <item>
      <title>Conditional Access baseline for Entra ID: naming, pilot groups, report-only, Insights, break-glass and rollout waves</title>
      <dc:creator>AdminPackStudio</dc:creator>
      <pubDate>Wed, 07 Oct 2026 14:02:13 +0000</pubDate>
      <link>https://dev.to/adminpackstudio/conditional-access-baseline-for-entra-id-naming-pilot-groups-report-only-insights-break-glass-2dng</link>
      <guid>https://dev.to/adminpackstudio/conditional-access-baseline-for-entra-id-naming-pilot-groups-report-only-insights-break-glass-2dng</guid>
      <description>&lt;h1&gt;
  
  
  Conditional Access baseline for Entra ID: from report-only to enforce, step by step
&lt;/h1&gt;

&lt;p&gt;Conditional Access (CA) is the most powerful switch in a Microsoft 365 tenant, and the easiest one to get wrong. One policy scoped to &lt;em&gt;All users&lt;/em&gt; and &lt;em&gt;All cloud apps&lt;/em&gt;, set to &lt;strong&gt;On&lt;/strong&gt; on a Friday afternoon, and Monday starts with a helpdesk queue full of people who can't open Outlook. Sometimes that includes the admins.&lt;/p&gt;

&lt;p&gt;The policies themselves are rarely the issue. The trouble usually comes from the &lt;strong&gt;rollout&lt;/strong&gt;: no naming standard, no pilot group, report-only skipped or never actually reviewed, no emergency access, and a big-bang switch to "everyone."&lt;/p&gt;

&lt;p&gt;This guide is the long version of a baseline that avoids that. It covers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What a CA baseline is (and isn't)&lt;/li&gt;
&lt;li&gt;Prerequisites: licenses, roles, inventory&lt;/li&gt;
&lt;li&gt;A naming convention you'll still like in a year&lt;/li&gt;
&lt;li&gt;Pilot groups that actually tell you something&lt;/li&gt;
&lt;li&gt;Report-only mode, done properly&lt;/li&gt;
&lt;li&gt;What If and Insights and reporting&lt;/li&gt;
&lt;li&gt;Break-glass (emergency access) accounts&lt;/li&gt;
&lt;li&gt;The starter policy set&lt;/li&gt;
&lt;li&gt;Expanding in waves&lt;/li&gt;
&lt;li&gt;Troubleshooting table&lt;/li&gt;
&lt;li&gt;Ongoing operating rhythm&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you only want the five-minute version, the short post is here: &lt;a href="https://dev.to/adminpackstudio/conditional-access-without-the-monday-lockout-report-only-enforce-4jbj"&gt;Conditional Access without the Monday lockout: report-only → enforce&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What a Conditional Access baseline is (and isn't)
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;CA baseline&lt;/strong&gt; is a small set of policies that every tenant should have, plus the process you use to change them safely. The policies are the easy part. The process is what keeps you from locking people out.&lt;/p&gt;

&lt;p&gt;What CA does: it evaluates a sign-in to a cloud app (who, what app, what device, where from, how risky) and decides &lt;em&gt;allow&lt;/em&gt;, &lt;em&gt;require something&lt;/em&gt; (MFA, a compliant device, an authentication strength), &lt;em&gt;block&lt;/em&gt;, or &lt;em&gt;limit the session&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;What CA does &lt;strong&gt;not&lt;/strong&gt; do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It doesn't configure devices. Intune does that. CA only &lt;em&gt;reads&lt;/em&gt; the device's compliance state as a signal.&lt;/li&gt;
&lt;li&gt;It doesn't fix a broken MFA registration process. It will expose one, loudly.&lt;/li&gt;
&lt;li&gt;It doesn't apply to things that never touch Entra sign-in (an on-prem file share over SMB, for example).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last distinction matters for planning. If you plan to require a compliant device, your Intune compliance has to be green &lt;em&gt;first&lt;/em&gt;. Otherwise CA just turns every compliance gap into an access outage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prerequisites: licenses, roles, and an inventory
&lt;/h2&gt;

&lt;p&gt;Before you design anything, check these three things.&lt;/p&gt;

&lt;h3&gt;
  
  
  Licenses
&lt;/h3&gt;

&lt;p&gt;Conditional Access needs &lt;strong&gt;Microsoft Entra ID P1&lt;/strong&gt; for every user the policies cover. P1 is included in Microsoft 365 Business Premium and E3/E5 suites. Risk-based conditions (sign-in risk, user risk) need &lt;strong&gt;P2&lt;/strong&gt;. Build the baseline on P1 and treat risk policies as a later upgrade. Don't hold the baseline back waiting for them.&lt;/p&gt;

&lt;p&gt;If your tenant runs on &lt;strong&gt;security defaults&lt;/strong&gt;, know that you'll have to turn them off to use CA. Plan your replacement MFA policy &lt;em&gt;before&lt;/em&gt; you do, so there's no gap where nothing enforces MFA.&lt;/p&gt;

&lt;h3&gt;
  
  
  Roles
&lt;/h3&gt;

&lt;p&gt;Day-to-day CA work doesn't need Global Administrator:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Create and edit policies&lt;/td&gt;
&lt;td&gt;Conditional Access Administrator&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Read policies, logs, exports&lt;/td&gt;
&lt;td&gt;Security Reader or Global Reader&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Emergency recovery&lt;/td&gt;
&lt;td&gt;Global Administrator (break-glass only)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Inventory what already exists
&lt;/h3&gt;

&lt;p&gt;Many tenants already have a few CA policies from a previous admin, a consultant, or Microsoft-managed policies. Before you add anything, write down every existing policy: its state (On / Report-only / Off), who it targets, and what it grants. Export it to CSV so you have a "before" picture for change control. Any &lt;strong&gt;On&lt;/strong&gt; policy that nobody can explain should get reviewed before you add new ones on top of it.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Conditional Access naming convention that scales
&lt;/h2&gt;

&lt;p&gt;At 3 a.m. during an incident, you'll be scanning a list of 25 policies to find the one blocking finance. Names like &lt;code&gt;MFA&lt;/code&gt;, &lt;code&gt;Test&lt;/code&gt;, and &lt;code&gt;New policy (2)&lt;/code&gt; are no help then.&lt;/p&gt;

&lt;p&gt;Use a structured name that reads like a change ticket:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CA - &amp;lt;Who&amp;gt; - &amp;lt;Control&amp;gt; - &amp;lt;Apps/Scope&amp;gt; - &amp;lt;Phase&amp;gt; - v&amp;lt;n&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;Reads as&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CA - AllUsers - Require MFA - O365 - ReportOnly - v1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Broad MFA design, still observing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CA - Admins - Require MFA - AllApps - Enforce - v2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Admin hardening, live, second revision&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CA - AllUsers - Block Legacy Auth - AllApps - Enforce - v1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Legacy protocols blocked&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CA - Guests - Require MFA - AllApps - Pilot - v1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Guest policy in pilot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CA - Windows - Require Compliant - O365 - Wave2 - v1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Device gate, second rollout wave&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A few rules that make the convention stick:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Same field order every time.&lt;/strong&gt; Alphabetical sorting then groups policies by audience automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pick one source of truth for phase.&lt;/strong&gt; Either put the phase in the name and rename at each step, or keep names stable and rely on the portal's state column plus your export. Don't mix the two habits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use the Description field&lt;/strong&gt; for owner, ticket number, last review date and a warning: &lt;code&gt;Owner: SecOps | Ticket: CHG-1042 | Reviewed: 2026-10-06 | Do not widen scope without pilot sign-off&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bump the version&lt;/strong&gt; whenever the grant or the scope changes. That makes before-and-after exports easy to diff.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Name your &lt;strong&gt;groups&lt;/strong&gt; the same way: &lt;code&gt;CA-Pilot-Wave0&lt;/code&gt;, &lt;code&gt;CA-Wave2-Finance&lt;/code&gt;, &lt;code&gt;CA-Excl-LegacyApp-Exp2026-11-30&lt;/code&gt;. An exclusion group with its expiry date in the name is much harder to forget.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pilot groups: who goes first and why
&lt;/h2&gt;

&lt;p&gt;A pilot only helps if it's realistic. If the pilot is three IT admins on brand-new laptops, every policy will look fine until it reaches the warehouse.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A good pilot group (&lt;code&gt;CA-Pilot-Wave0&lt;/code&gt;) has:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;5–15 people across roles: IT, someone in finance, someone who travels or works in the field, an executive assistant (they act on behalf of others and hit edge cases early).&lt;/li&gt;
&lt;li&gt;A mix of devices: managed Windows, a Mac if you have them, a phone using Outlook mobile, and if possible one device you &lt;em&gt;know&lt;/em&gt; is noncompliant, so you can see what failure looks like.&lt;/li&gt;
&lt;li&gt;People who know they're in a pilot. Send a short note: what's changing, when, and who to call.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Scope rules for the pilot:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Include the pilot group only. &lt;strong&gt;Never start with "All users"&lt;/strong&gt; on a Block or a hard device requirement.&lt;/li&gt;
&lt;li&gt;Exclude break-glass accounts from day one, even in pilot (see below).&lt;/li&gt;
&lt;li&gt;For harsh grants (compliant device, block), start with a specific app such as Office 365 instead of "All cloud apps." Widen the app scope later, as a separate change.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Report-only mode: how to use it properly
&lt;/h2&gt;

&lt;p&gt;Report-only is the most useful CA feature and the most often wasted. Admins turn it on, never look at the results, and then flip to On a week later. All that tells you is that a week went by.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What report-only does:&lt;/strong&gt; the policy is evaluated on every matching sign-in and the result is logged, but nothing is enforced. Each sign-in shows outcomes like &lt;em&gt;Report-only: Success&lt;/em&gt;, &lt;em&gt;Report-only: Failure&lt;/em&gt;, or &lt;em&gt;Report-only: User action required&lt;/em&gt; (for example, the user would have been asked for MFA).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to run a report-only window:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create the policy with Enable policy = Report-only.&lt;/strong&gt; Don't create it as On "just to test."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leave it running for at least 3–5 business days.&lt;/strong&gt; You want a Monday in there, plus month-end if the policy touches finance apps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review the results daily&lt;/strong&gt; (next section shows where).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Classify every report-only failure&lt;/strong&gt; as either:

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Expected&lt;/em&gt;: this person genuinely isn't ready (no MFA method, noncompliant device). That's a &lt;strong&gt;remediation ticket&lt;/strong&gt;, not a reason to weaken the policy.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Bug&lt;/em&gt;: the policy hits something it shouldn't (a service account, a guest, an app you didn't mean to include, an Intune enrollment flow). That's an &lt;strong&gt;assignment fix&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set an exit bar before you start.&lt;/strong&gt; For example: "≥95% of pilot users have a registered MFA method, and zero unexplained report-only failures for 3 consecutive days."&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A word of caution: a policy that requires a &lt;strong&gt;compliant device&lt;/strong&gt; can trigger device-related prompts during report-only on some platforms. Read the current Microsoft documentation for any device-based policy before you put it in report-only, and test it on a pilot device first.&lt;/p&gt;




&lt;h2&gt;
  
  
  What If and Insights and reporting: reading the results
&lt;/h2&gt;

&lt;p&gt;Two tools cover most of the investigation work. Use both.&lt;/p&gt;

&lt;h3&gt;
  
  
  What If (before and after every change)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Entra admin center → Protection → Conditional Access → Policies → What If.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run these scenarios on every new or changed policy:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Expected result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Pilot user + Office 365 + normal location&lt;/td&gt;
&lt;td&gt;Your policy &lt;strong&gt;applies&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Break-glass account + any app&lt;/td&gt;
&lt;td&gt;Your policy &lt;strong&gt;does not apply&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-pilot user&lt;/td&gt;
&lt;td&gt;Your policy &lt;strong&gt;does not apply&lt;/strong&gt; (while still pilot-scoped)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Guest user (if guests are in scope)&lt;/td&gt;
&lt;td&gt;Matches your guest design&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If What If surprises you, fix the assignment before you go any further.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sign-in logs (single-user truth)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Entra → Monitoring &amp;amp; health → Sign-in logs.&lt;/strong&gt; Open a sign-in and look at the &lt;strong&gt;Conditional Access&lt;/strong&gt; and &lt;strong&gt;Report-only&lt;/strong&gt; tabs. You'll see every policy that was evaluated, whether it applied, and which grant control passed or failed. This is where you confirm a specific user's story ("I got blocked at 8:05").&lt;/p&gt;

&lt;h3&gt;
  
  
  Insights and reporting (the aggregate view)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Entra → Protection → Conditional Access → Insights and reporting&lt;/strong&gt; shows the combined effect of one or more policies across all sign-ins over a time range, broken down by user, app, and result.&lt;/p&gt;

&lt;p&gt;Practical notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The workbook reads sign-in logs from a &lt;strong&gt;Log Analytics workspace&lt;/strong&gt;. If you haven't set up diagnostic settings to send sign-in logs there, set that up first, or the view will be empty.&lt;/li&gt;
&lt;li&gt;Filter to &lt;strong&gt;one policy at a time&lt;/strong&gt; during a report-only window.&lt;/li&gt;
&lt;li&gt;Sort by &lt;em&gt;Failure&lt;/em&gt; and &lt;em&gt;User action required&lt;/em&gt;, then open 3–5 sample sign-ins for each pattern. Don't try to read every row.&lt;/li&gt;
&lt;li&gt;Screenshot or export the summary for your change ticket. "Report-only reviewed, 2 false failures fixed, 0 outstanding" is the evidence your CAB wants.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If Insights shows a pile of "would block" results for normal, expected work, you aren't ready to enforce, no matter how long the policy has been in report-only.&lt;/p&gt;




&lt;h2&gt;
  
  
  Break-glass accounts: before you enforce anything
&lt;/h2&gt;

&lt;p&gt;A break-glass (emergency access) account is how you get back in when CA, MFA, or a bad change locks out every admin. Without one, your rollback plan depends on another Global Admin being reachable and not locked out too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Baseline setup:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;At least two&lt;/strong&gt; cloud-only accounts on the &lt;code&gt;*.onmicrosoft.com&lt;/code&gt; domain (not synced from on-prem AD, so an AD or sync problem can't take them out).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Global Administrator&lt;/strong&gt;, permanently assigned. Not PIM-eligible, because activation may depend on the same systems that are broken.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Excluded from your CA policies&lt;/strong&gt;, ideally through one &lt;code&gt;CA-Excl-BreakGlass&lt;/code&gt; group that you add to every policy's exclusions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A strong, phishing-resistant sign-in method.&lt;/strong&gt; Microsoft now requires MFA to sign in to its admin portals, and that applies to emergency accounts as well, so plan for something like a FIDO2 security key stored with the sealed credentials. Check current Microsoft guidance on emergency access accounts when you set this up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Credentials kept offline&lt;/strong&gt; in a sealed, documented process, so that two people can retrieve them without depending on the tenant being up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitored.&lt;/strong&gt; Every break-glass sign-in should raise an alert and be treated as an incident until explained.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tested quarterly&lt;/strong&gt;: sign in, open the CA policy list, sign out, write down that the test happened.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The emergency disable procedure&lt;/strong&gt; (print it and keep it with the credentials):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sign in as break-glass from a known clean device.&lt;/li&gt;
&lt;li&gt;Go to Conditional Access → Policies → the offending policy.&lt;/li&gt;
&lt;li&gt;Set it to &lt;strong&gt;Report-only&lt;/strong&gt; (keeps logging for root cause) or &lt;strong&gt;Off&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Post in the incident channel: what changed, when, who.&lt;/li&gt;
&lt;li&gt;After recovery: root cause, rotate the break-glass credential, and reintroduce the fix through the normal report-only path.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Exclusion hygiene:&lt;/strong&gt; break-glass is the only permanent exclusion that's acceptable. Every other exclusion (a legacy app, a user stuck mid-migration) should be a &lt;strong&gt;group&lt;/strong&gt; with an owner, a ticket and an expiry date in its description. Exclusions that never get removed are how a CA baseline slowly stops protecting anything.&lt;/p&gt;




&lt;h2&gt;
  
  
  The starter baseline policy set
&lt;/h2&gt;

&lt;p&gt;Don't enable everything on day one. Most tenants get the most value from these, introduced &lt;strong&gt;one at a time&lt;/strong&gt;, each going through pilot → report-only → enforce:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Policy&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;th&gt;Watch for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Require MFA for admin roles&lt;/td&gt;
&lt;td&gt;Highest-value accounts first; small blast radius&lt;/td&gt;
&lt;td&gt;Target directory roles, exclude break-glass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Block legacy authentication&lt;/td&gt;
&lt;td&gt;Legacy protocols can't do MFA, so they bypass it&lt;/td&gt;
&lt;td&gt;Old Outlook clients, IMAP/POP, scan-to-email devices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Require MFA for all users&lt;/td&gt;
&lt;td&gt;The core control&lt;/td&gt;
&lt;td&gt;MFA registration gaps; use Temporary Access Pass for stragglers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Require MFA for guests&lt;/td&gt;
&lt;td&gt;B2B accounts are often forgotten&lt;/td&gt;
&lt;td&gt;Separate policy, separate pilot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Require compliant device (Windows first)&lt;/td&gt;
&lt;td&gt;Only managed, healthy devices reach data&lt;/td&gt;
&lt;td&gt;Intune compliance must be green first&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Policy 5 is the one most likely to cause a Monday lockout, because it depends on a whole separate system (Intune) being in good shape. Two things to settle before it goes beyond pilot:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Compliance has to be reliably green.&lt;/strong&gt; Devices that are still encrypting, haven't checked in, or are inside a compliance grace period are common causes of false "not compliant" blocks. I covered one of the most common in &lt;a href="https://dev.to/adminpackstudio/bitlocker-still-encrypting-why-intune-marks-you-noncompliant-and-how-grace-periods-save-monday-2l6h"&gt;BitLocker still encrypting: why Intune marks you noncompliant (and how grace periods save Monday)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't create a circular dependency with enrollment.&lt;/strong&gt; If a "require compliant device" policy covers the apps a device needs in order to &lt;em&gt;enroll&lt;/em&gt; (Microsoft Intune / Microsoft Intune Enrollment), new devices can't get compliant because they can't finish enrolling. Check Microsoft's current guidance on which enrollment apps to exclude.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(If your enrollment and compliance side needs work first, there's a separate Intune &amp;amp; M365 Admin Starter Pack for that, linked at the end.)&lt;/p&gt;




&lt;h2&gt;
  
  
  Rolling out in waves instead of a big bang
&lt;/h2&gt;

&lt;p&gt;Once a policy has been enforced on the pilot for a couple of days without drama, expand it in waves. Use &lt;strong&gt;nested groups&lt;/strong&gt;: add wave groups into the policy's include list instead of switching to "All users" and adding exclusions.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Wave&lt;/th&gt;
&lt;th&gt;Who&lt;/th&gt;
&lt;th&gt;Enter when&lt;/th&gt;
&lt;th&gt;Hold for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;Pilot (&lt;code&gt;CA-Pilot-Wave0&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Report-only clean, What If verified&lt;/td&gt;
&lt;td&gt;48 hours enforced&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;IT + Security&lt;/td&gt;
&lt;td&gt;Wave 0 had no emergency rollback&lt;/td&gt;
&lt;td&gt;3 business days&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;One department (pick a cooperative one)&lt;/td&gt;
&lt;td&gt;Helpdesk ticket rate normal&lt;/td&gt;
&lt;td&gt;1 week&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Remaining staff&lt;/td&gt;
&lt;td&gt;Remediation backlog cleared&lt;/td&gt;
&lt;td&gt;Monitor 2 weeks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Guests / vendors&lt;/td&gt;
&lt;td&gt;Separate guest policy validated&lt;/td&gt;
&lt;td&gt;Ongoing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Rules for each wave:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tell people before the wave, not after.&lt;/strong&gt; One paragraph: what changes, what they'll see, what to do if they're blocked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watch the helpdesk queue and Insights&lt;/strong&gt; for 48 hours after each wave.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Have a pre-agreed rollback trigger&lt;/strong&gt;, for example "more than 5 lockout tickets in an hour from the new wave → remove that wave group, investigate." Removing one wave group is a much smaller, safer change than turning the whole policy off.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't expand on Fridays&lt;/strong&gt; or right before holidays or month-end close.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the final wave is in, you can switch the include list to "All users" (still excluding break-glass) and retire the wave groups, or keep the waves for the next policy. Either works, as long as it's written down.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conditional Access troubleshooting table
&lt;/h2&gt;

&lt;p&gt;These are the tickets you'll see during and after rollout. &lt;strong&gt;Rule zero: don't disable CA org-wide as a first response.&lt;/strong&gt; Scope the fix to the affected user or wave and time-box it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Triage in five minutes:&lt;/strong&gt; get the error screenshot with the &lt;strong&gt;Correlation ID / Request ID&lt;/strong&gt; → open that user's sign-in log → &lt;strong&gt;Conditional Access&lt;/strong&gt; tab → find which policy shows &lt;em&gt;Failure&lt;/em&gt; → reproduce in &lt;strong&gt;What If&lt;/strong&gt; → then fix.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;Likely cause&lt;/th&gt;
&lt;th&gt;First check&lt;/th&gt;
&lt;th&gt;Safe fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;"More information required" / MFA registration loop&lt;/td&gt;
&lt;td&gt;No usable MFA method, or registration blocked by policy&lt;/td&gt;
&lt;td&gt;User's authentication methods; auth methods policy&lt;/td&gt;
&lt;td&gt;Issue a &lt;strong&gt;Temporary Access Pass&lt;/strong&gt;; finish registration on a trusted network&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"You can't get there from here" / device not compliant&lt;/td&gt;
&lt;td&gt;Device not enrolled, not synced, or compliance not yet evaluated&lt;/td&gt;
&lt;td&gt;Intune device record: compliance state + last check-in&lt;/td&gt;
&lt;td&gt;Sync the device, fix the failing setting; time-boxed exclusion group (≤48h) with ticket if business-critical&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compliant in Intune but CA still blocks&lt;/td&gt;
&lt;td&gt;Device identity mismatch (hybrid join vs Entra join), or browser not passing device info&lt;/td&gt;
&lt;td&gt;Device ID in sign-in log vs Intune; browser used&lt;/td&gt;
&lt;td&gt;Use a supported browser / sign-in method that passes device identity; fix join state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Old Outlook / IMAP / POP / SMTP app fails, new Outlook works&lt;/td&gt;
&lt;td&gt;Legacy authentication blocked&lt;/td&gt;
&lt;td&gt;Sign-in log &lt;strong&gt;Client app&lt;/strong&gt; column&lt;/td&gt;
&lt;td&gt;Move to a modern-auth client; temporary exception group with expiry for true business blockers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scan-to-email printer or app stops sending&lt;/td&gt;
&lt;td&gt;Device uses basic SMTP auth&lt;/td&gt;
&lt;td&gt;Sign-in log for the service account&lt;/td&gt;
&lt;td&gt;Use a supported relay/connector method; don't permanently exclude the account&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Guest can't open Teams / SharePoint&lt;/td&gt;
&lt;td&gt;Guest policy requires MFA they haven't set up, or cross-tenant settings&lt;/td&gt;
&lt;td&gt;Guest's sign-in log; cross-tenant access settings&lt;/td&gt;
&lt;td&gt;Guest completes MFA registration; adjust cross-tenant trust deliberately&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;New devices stuck during Autopilot / enrollment&lt;/td&gt;
&lt;td&gt;Compliant-device policy covers enrollment apps (circular dependency)&lt;/td&gt;
&lt;td&gt;Which policy fails on Microsoft Intune Enrollment sign-ins&lt;/td&gt;
&lt;td&gt;Exclude enrollment apps from the device policy per Microsoft guidance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Traveling user blocked or prompted unexpectedly&lt;/td&gt;
&lt;td&gt;Named location / country rule; VPN egress IP changed&lt;/td&gt;
&lt;td&gt;Sign-in log location + IP; named location definitions&lt;/td&gt;
&lt;td&gt;Update named locations; time-boxed traveler exception&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Named admin locked out of portal&lt;/td&gt;
&lt;td&gt;Admin policy too strict, MFA method broken&lt;/td&gt;
&lt;td&gt;Which policy failed; admin's auth methods&lt;/td&gt;
&lt;td&gt;Second admin sets policy to Report-only or adds timed exclusion; &lt;strong&gt;break-glass only if no other admin can act&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Report-only shows failures nobody can explain&lt;/td&gt;
&lt;td&gt;Policy scope wider than intended (apps, users, platforms)&lt;/td&gt;
&lt;td&gt;What If with a sample user&lt;/td&gt;
&lt;td&gt;Fix assignment &lt;em&gt;before&lt;/em&gt; enforcing; that's what report-only is for&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Severity guide:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Severity&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;Response&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SEV1&lt;/td&gt;
&lt;td&gt;All admins locked out&lt;/td&gt;
&lt;td&gt;Break-glass → offending policy to Report-only → incident bridge&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SEV2&lt;/td&gt;
&lt;td&gt;A whole department can't reach email&lt;/td&gt;
&lt;td&gt;Remove that wave group or scope a ≤4h exclusion; fix the root cause&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SEV3&lt;/td&gt;
&lt;td&gt;One user, one app&lt;/td&gt;
&lt;td&gt;Standard ticket; no tenant-wide changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SEV4&lt;/td&gt;
&lt;td&gt;Report-only noise&lt;/td&gt;
&lt;td&gt;Tune during business hours&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Keeping the baseline healthy
&lt;/h2&gt;

&lt;p&gt;A baseline isn't a one-time project. A light routine keeps it from drifting:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Cadence&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Weekly&lt;/td&gt;
&lt;td&gt;Skim CA failures in Insights; check for new report-only failures on anything in flight&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Monthly&lt;/td&gt;
&lt;td&gt;Export all policies to CSV and diff against last month; review exclusion groups for expired entries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quarterly&lt;/td&gt;
&lt;td&gt;Test a break-glass sign-in; run a tabletop of the emergency disable procedure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;After any big Intune or identity change&lt;/td&gt;
&lt;td&gt;Put affected device-based policies back through a short report-only check&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Checklist before any policy goes to On:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Name and Description follow the convention (owner, ticket, review date)&lt;/li&gt;
&lt;li&gt;[ ] Include = pilot or wave group, not All users&lt;/li&gt;
&lt;li&gt;[ ] Exclude = break-glass group (+ documented, expiring exceptions only)&lt;/li&gt;
&lt;li&gt;[ ] App scope isn't accidentally "All cloud apps" with a Block grant&lt;/li&gt;
&lt;li&gt;[ ] Report-only ran ≥3 business days and Insights was reviewed&lt;/li&gt;
&lt;li&gt;[ ] What If verified for pilot user, break-glass and non-pilot user&lt;/li&gt;
&lt;li&gt;[ ] Remediation tickets for false failures are closed&lt;/li&gt;
&lt;li&gt;[ ] Rollback trigger and owner written in the change ticket&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Further reading and the full pack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Short version of this pattern: &lt;a href="https://dev.to/adminpackstudio/conditional-access-without-the-monday-lockout-report-only-enforce-4jbj"&gt;Conditional Access without the Monday lockout: report-only → enforce&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The compliance side of device-based policies: &lt;a href="https://dev.to/adminpackstudio/bitlocker-still-encrypting-why-intune-marks-you-noncompliant-and-how-grace-periods-save-monday-2l6h"&gt;BitLocker still encrypting: why Intune marks you noncompliant&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you'd rather start from a written-up baseline than build these docs yourself, the &lt;strong&gt;Entra ID Conditional Access Starter Pack&lt;/strong&gt; ($29) packages it: five playbooks (foundation and naming, report-only → enforce, a starter policy library, break-glass and exclusions, and a troubleshooting runbook with triage cards), plus three &lt;strong&gt;read-only&lt;/strong&gt; Graph PowerShell exports for your policies, named locations and a sample of sign-in failures. The scripts only read. They don't create, change, or delete policies.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://cashflow4375.gumroad.com/l/nhuyrc" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/nhuyrc&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If your Intune compliance isn't steady enough for a compliant-device policy yet, the Intune &amp;amp; M365 Admin Starter Pack covers enrollment and compliance baselines ($19 during launch, normally $29): &lt;a href="https://cashflow4375.gumroad.com/l/joonf" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/joonf&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Either way, the free process above is the important part: name it, pilot it, run report-only, read Insights, protect break-glass, then expand in waves.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Not affiliated with or endorsed by Microsoft. Microsoft, Entra and Intune are trademarks of the Microsoft group of companies. Operational guidance for admins authorized to manage their own tenant. Portal paths and licensing change, so verify against current Microsoft documentation, and test in a pilot first.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>microsoft</category>
      <category>azure</category>
      <category>security</category>
      <category>sysadmin</category>
    </item>
    <item>
      <title>Excel &amp; CSV ops for IT admins: cleaning Intune device exports without breaking your UPNs (Power Query basics + 9 pitfalls)</title>
      <dc:creator>AdminPackStudio</dc:creator>
      <pubDate>Wed, 07 Oct 2026 14:01:27 +0000</pubDate>
      <link>https://dev.to/adminpackstudio/excel-csv-ops-for-it-admins-cleaning-intune-device-exports-without-breaking-your-upns-power-4cc6</link>
      <guid>https://dev.to/adminpackstudio/excel-csv-ops-for-it-admins-cleaning-intune-device-exports-without-breaking-your-upns-power-4cc6</guid>
      <description>&lt;h1&gt;
  
  
  Excel &amp;amp; CSV ops for IT admins: cleaning Intune device exports without breaking your UPNs
&lt;/h1&gt;

&lt;p&gt;Someone asks: &lt;em&gt;"How many active laptops do we actually have, and who's on them?"&lt;/em&gt; You export the device list from the Intune admin center, open it in Excel, and immediately run into problems: serial numbers in scientific notation, the same laptop listed three times, and a user who shows up as &lt;code&gt;Jane.Doe@contoso.com&lt;/code&gt; in one sheet and &lt;code&gt;jane.doe@contoso.com&lt;/code&gt; (trailing space) in the other.&lt;/p&gt;

&lt;p&gt;None of this is hard. It just needs a repeatable routine. Here's the one I'd hand to any admin who lives in CSV exports.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick version (TL;DR):&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Don't double-click the CSV. Import it with &lt;strong&gt;Data → From Text/CSV&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Normalize your join key: &lt;strong&gt;trim, clean, lowercase&lt;/strong&gt; UPNs before you match anything.&lt;/li&gt;
&lt;li&gt;Dedupe on the &lt;strong&gt;right&lt;/strong&gt; column (serial or device ID, not device name). Keep the &lt;strong&gt;latest check-in&lt;/strong&gt;, not whichever row comes first.&lt;/li&gt;
&lt;li&gt;Put it in &lt;strong&gt;Power Query&lt;/strong&gt; once, then press &lt;strong&gt;Refresh&lt;/strong&gt; every week.&lt;/li&gt;
&lt;li&gt;Keep raw data, cleaned data, and reports on separate sheets.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. Import, don't open
&lt;/h2&gt;

&lt;p&gt;Double-clicking a &lt;code&gt;.csv&lt;/code&gt; lets Excel guess every column's type. That's how you lose data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Long numbers (IMEIs, some serials) turn into &lt;code&gt;3.52E+14&lt;/code&gt;, and the original digits are &lt;strong&gt;gone&lt;/strong&gt; once you save.&lt;/li&gt;
&lt;li&gt;Leading zeros get dropped (&lt;code&gt;00123&lt;/code&gt; → &lt;code&gt;123&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Dates get read in your PC's locale, so &lt;code&gt;03/04/2026&lt;/code&gt; might become April 3rd or March 4th.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Do this instead:&lt;/strong&gt; Data → &lt;strong&gt;From Text/CSV&lt;/strong&gt; → pick the file → &lt;strong&gt;Transform Data&lt;/strong&gt;. That opens Power Query, where you set column types on purpose.&lt;/p&gt;

&lt;p&gt;Also worth checking: recent Microsoft 365 builds of Excel have &lt;strong&gt;File → Options → Data → Automatic data conversion&lt;/strong&gt; settings. You can turn off "remove leading zeros" and "convert to scientific notation" there. Option names move around, so check your build.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Rule zero: work on a &lt;strong&gt;copy&lt;/strong&gt; of the export. Keep the original file untouched in case you need it for an audit or ticket.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2. Normalize UPNs before you join anything
&lt;/h2&gt;

&lt;p&gt;The UPN (user principal name) is usually your best join key between a device export and a user or license export. It's also where the sneakiest problems hide.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pitfall&lt;/th&gt;
&lt;th&gt;What it looks like&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Trailing / leading spaces&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;jane.doe@contoso.com&lt;/code&gt; doesn't match&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;TRIM()&lt;/code&gt; / &lt;code&gt;Text.Trim&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-breaking spaces (char 160)&lt;/td&gt;
&lt;td&gt;Looks trimmed, still doesn't match&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;SUBSTITUTE(A2,CHAR(160)," ")&lt;/code&gt; before &lt;code&gt;TRIM&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Case differences&lt;/td&gt;
&lt;td&gt;Power Query merges miss rows&lt;/td&gt;
&lt;td&gt;Lowercase &lt;strong&gt;both&lt;/strong&gt; sides&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UPN ≠ email address&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;jdoe@contoso.onmicrosoft.com&lt;/code&gt; vs &lt;code&gt;jane.doe@contoso.com&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Join on UPN to UPN, never UPN to mail&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Renamed users&lt;/td&gt;
&lt;td&gt;Old UPN in last month's export&lt;/td&gt;
&lt;td&gt;For long-lived tracking, also keep the object ID if your export has it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blank primary user&lt;/td&gt;
&lt;td&gt;Shared, kiosk, or userless devices&lt;/td&gt;
&lt;td&gt;Label them &lt;code&gt;(no primary user)&lt;/code&gt;. They usually aren't errors.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A worksheet helper column if you're not using Power Query yet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=LOWER(TRIM(SUBSTITUTE([@[Primary user UPN]],CHAR(160)," ")))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why case matters:&lt;/strong&gt; Excel's &lt;code&gt;XLOOKUP&lt;/code&gt; and &lt;code&gt;COUNTIF&lt;/code&gt; don't care about case. Power Query's Merge and Remove Duplicates &lt;strong&gt;do&lt;/strong&gt;. So the same data can give you different answers depending on which tool you used. Lowercase the key, and the tools will agree.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Duplicates: dedupe on the right key, keep the right row
&lt;/h2&gt;

&lt;p&gt;Duplicates in device exports are usually real records, not export bugs. A laptop that was reset and re-enrolled can show up more than once, and so can a device that got re-imaged and renamed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pick the key on purpose:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Device name.&lt;/strong&gt; Bad key. Names get reused (&lt;code&gt;LAPTOP-001&lt;/code&gt; after a re-image) and changed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Serial number.&lt;/strong&gt; Good key for counting physical hardware. Watch for blanks and placeholder values that some VMs and white-box devices report. Filter those out and look at them separately.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Device ID.&lt;/strong&gt; Good key for counting Intune records. It changes on re-enrollment, so it's the right key for "records", not for "laptops".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Keep the latest row, not the first one.&lt;/strong&gt; Excel's grid &lt;strong&gt;Data → Remove Duplicates&lt;/strong&gt; keeps whichever row comes first. Sort by last check-in, newest first, &lt;em&gt;then&lt;/em&gt; remove duplicates. In Power Query there's one more step to remember (see the &lt;code&gt;Table.Buffer&lt;/code&gt; note below).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before you delete anything, count it:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=COUNTIFS(tblDevices[Serial number],[@[Serial number]])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Filter where that's &lt;code&gt;&amp;gt; 1&lt;/code&gt;. Those rows are your stale-record cleanup list, which is useful on its own and not just noise to get rid of.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Power Query basics: a refreshable device list
&lt;/h2&gt;

&lt;p&gt;This is the habit that saves the most time. You build the cleanup &lt;strong&gt;once&lt;/strong&gt;, and next week you drop in the new export and press &lt;strong&gt;Refresh&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In Power Query: &lt;strong&gt;Home → Advanced Editor&lt;/strong&gt;, and adapt this. Column names are examples, so rename them to match your export headers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight matlab"&gt;&lt;code&gt;&lt;span class="n"&gt;let&lt;/span&gt;
    &lt;span class="n"&gt;Source&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Csv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                 &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"C:\Exports\Intune\devices.csv"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                 &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Delimiter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;","&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Encoding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;65001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QuoteStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QuoteStyle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Csv&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="n"&gt;Headers&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Table&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PromoteHeaders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;PromoteAllScalars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;

    &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;Keep&lt;/span&gt; &lt;span class="n"&gt;serials&lt;/span&gt; &lt;span class="n"&gt;as&lt;/span&gt; &lt;span class="n"&gt;TEXT&lt;/span&gt; &lt;span class="n"&gt;so&lt;/span&gt; &lt;span class="n"&gt;nothing&lt;/span&gt; &lt;span class="n"&gt;turns&lt;/span&gt; &lt;span class="n"&gt;into&lt;/span&gt; &lt;span class="n"&gt;scientific&lt;/span&gt; &lt;span class="n"&gt;notation&lt;/span&gt;
    &lt;span class="n"&gt;Typed&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Table&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TransformColumnTypes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                 &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"Serial number"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                 &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"Primary user UPN"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                 &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"Last check-in"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="nb"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt; &lt;span class="s2"&gt;"en-US"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

    &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;Normalize&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="nb"&gt;join&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;replace&lt;/span&gt; &lt;span class="n"&gt;non&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;breaking&lt;/span&gt; &lt;span class="n"&gt;spaces&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lowercase&lt;/span&gt;
    &lt;span class="n"&gt;CleanUpn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Table&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TransformColumns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Typed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="s2"&gt;"Primary user UPN"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="err"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;null&lt;/span&gt; &lt;span class="nb"&gt;then&lt;/span&gt; &lt;span class="nb"&gt;null&lt;/span&gt;
                      &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lower&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Clean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                           &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Character&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;160&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s2"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;)))),&lt;/span&gt;
                 &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}}),&lt;/span&gt;

    &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;Newest&lt;/span&gt; &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;then&lt;/span&gt; &lt;span class="n"&gt;BUFFER&lt;/span&gt; &lt;span class="n"&gt;so&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="n"&gt;sticks&lt;/span&gt;
    &lt;span class="n"&gt;Sorted&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Table&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Table&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CleanUpn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="s2"&gt;"Last check-in"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Descending&lt;/span&gt;&lt;span class="p"&gt;}})),&lt;/span&gt;

    &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;One&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="n"&gt;physical&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;latest&lt;/span&gt; &lt;span class="nb"&gt;record&lt;/span&gt; &lt;span class="n"&gt;wins&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;Deduped&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Table&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Distinct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Sorted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"Serial number"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;in&lt;/span&gt;
    &lt;span class="n"&gt;Deduped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;"en-US"&lt;/code&gt; on the type step&lt;/strong&gt; tells Power Query how to read the date text. Set it to whatever locale your export actually uses. Timestamps in admin exports are often UTC, so label the column so nobody reads it as local time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Table.Buffer&lt;/code&gt; after the sort&lt;/strong&gt; is the classic gotcha. Without it, Power Query can reorder rows during optimization and &lt;code&gt;Table.Distinct&lt;/code&gt; might keep an older row. Buffering pins the sorted order.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Point the path at a fixed filename&lt;/strong&gt; (for example &lt;code&gt;devices.csv&lt;/code&gt;) and overwrite it each week, or use &lt;strong&gt;From Folder&lt;/strong&gt; to combine several exports.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Close &amp;amp; Load To… → Table&lt;/strong&gt; on a sheet named &lt;code&gt;clean_devices&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then join licenses or users with &lt;strong&gt;Merge Queries&lt;/strong&gt; on the lowercased UPN (Left Outer: keep all devices, bring in the matches).&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Stale devices: one column that answers the real question
&lt;/h2&gt;

&lt;p&gt;Add a custom column in Power Query (Add Column → Custom Column):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight matlab"&gt;&lt;code&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Days&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LocalNow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Last&lt;/span&gt; &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Name it &lt;code&gt;DaysSinceCheckIn&lt;/code&gt;. Then use buckets (&lt;code&gt;0–7&lt;/code&gt;, &lt;code&gt;8–30&lt;/code&gt;, &lt;code&gt;31–90&lt;/code&gt;, &lt;code&gt;90+&lt;/code&gt;) in a Pivot. That gives you "active vs stale" in one view. It's an easy number for a manager to read, and it's your cleanup queue.&lt;/p&gt;

&lt;p&gt;Be careful about the conclusion: "hasn't checked in for 90 days" means &lt;strong&gt;investigate&lt;/strong&gt;. It doesn't mean &lt;strong&gt;delete&lt;/strong&gt;. That laptop might be on someone's parental leave shelf. Clean up through your normal change process, not straight from the spreadsheet.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Workbook layout that survives next month
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;raw_*&lt;/code&gt; sheets: the untouched import (or just keep it in Power Query)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;clean_*&lt;/code&gt; sheets: Power Query output tables (&lt;code&gt;tblDevices&lt;/code&gt;, &lt;code&gt;tblLicenses&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;viz_*&lt;/code&gt; sheets: Pivots and charts built &lt;strong&gt;from Tables&lt;/strong&gt;, never from hard-coded ranges&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;README&lt;/code&gt; sheet: where each export comes from, who ran it, and when&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;More pitfalls, quick fire:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Distinct counts in Pivots:&lt;/strong&gt; check "Add this data to the Data Model" when creating the Pivot, then choose &lt;strong&gt;Distinct Count&lt;/strong&gt;. A regular Count counts rows, not users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hidden header changes:&lt;/strong&gt; if an admin portal renames a column, your query breaks on refresh. That's a good thing, because it fails loudly. Fix the column name in one step instead of hunting through formulas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Personal data:&lt;/strong&gt; device and user exports are personal data. Store them where your org says to, and don't email them around as attachments.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  7. Want the full set of patterns?
&lt;/h2&gt;

&lt;p&gt;This post covers the cleanup part. The &lt;strong&gt;Excel &amp;amp; Power Automate Ops Pack for IT Admins&lt;/strong&gt; from Admin Pack Studio ($29) goes further: Excel ops patterns for messy admin CSVs (Tables, XLOOKUP, Pivots), an admin workbook starter layout (Licenses / Devices / Tickets sheets), Power Automate cloud flow starters for IT approvals and notifications, guardrails and run-after error handling, and two read-only PowerShell helpers that generate practice CSVs so you can learn without touching production data. It teaches you a layout to build in your own tenant. It doesn't ship a macro-laden .xlsx that breaks the first time you open it.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://cashflow4375.gumroad.com/l/vougj" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/vougj&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Need the Intune exports and enrollment hygiene side?&lt;/em&gt; The Intune &amp;amp; M365 Admin Starter Pack ($19 launch price, normally $29) has enrollment/compliance checklists and read-only snapshot scripts whose output drops straight into this workbook: &lt;a href="https://cashflow4375.gumroad.com/l/joonf" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/joonf&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Admin Pack Studio. Not affiliated with Microsoft. Excel, Power Query, and Intune are Microsoft products; menu names and export columns change over time, so check current Microsoft documentation. Examples use placeholder data (contoso.com).&lt;/em&gt;&lt;/p&gt;

</description>
      <category>excel</category>
      <category>sysadmin</category>
      <category>intune</category>
      <category>powerquery</category>
    </item>
    <item>
      <title>The sysadmin interview question you'll get anyway — "Tell me about a change that locked users out" (STAR drill + worked outline)</title>
      <dc:creator>AdminPackStudio</dc:creator>
      <pubDate>Wed, 07 Oct 2026 13:54:07 +0000</pubDate>
      <link>https://dev.to/adminpackstudio/the-sysadmin-interview-question-youll-get-anyway-tell-me-about-a-change-that-locked-users-out-50oo</link>
      <guid>https://dev.to/adminpackstudio/the-sysadmin-interview-question-youll-get-anyway-tell-me-about-a-change-that-locked-users-out-50oo</guid>
      <description>&lt;h1&gt;
  
  
  "Tell me about a change that locked users out": a STAR drill for sysadmin and M365 interviews
&lt;/h1&gt;

&lt;p&gt;If you're interviewing for a sysadmin, M365, or endpoint role, expect some version of this question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Tell me about a time a change you made (or your team made) caused an outage. What happened, and what did you do?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's not a trick. The interviewer wants to know three things: &lt;strong&gt;do you check before you fix, do you communicate while it's broken, and do you change something so it doesn't happen again?&lt;/strong&gt; Most weak answers skip straight to "I rolled it back" and stop there.&lt;/p&gt;

&lt;p&gt;Here's one drill you can run in about 10 minutes, built around a very common M365 story: &lt;strong&gt;a Conditional Access policy flips to On and users get blocked on Monday morning.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The drill (do it out loud, timed)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Set a timer for 3 minutes.&lt;/strong&gt; Answer the question above out loud using your own real story. If you don't have a CA story, use any change that broke sign-in, mail, VPN, printing, or a line-of-business app.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stop at 3 minutes,&lt;/strong&gt; even if you're mid-sentence. Interview answers that run past 3 minutes lose people.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Score yourself&lt;/strong&gt; with the table in section 5.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Answer the follow-ups&lt;/strong&gt; in section 4 without notes. That's where most candidates lose points.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run it again tomorrow.&lt;/strong&gt; The second run is always tighter.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No real story yet? Use the &lt;strong&gt;scenario version&lt;/strong&gt; in section 3 instead. It's fine to say "I haven't had this exact incident. Here's how I'd handle it." &lt;strong&gt;Don't invent one.&lt;/strong&gt; Interviewers dig into details, and made-up stories fall apart on the second follow-up.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Worked STAR outline (illustrative composite)
&lt;/h2&gt;

&lt;p&gt;This is an &lt;strong&gt;example structure&lt;/strong&gt;, not a script. Swap in your own facts, numbers, and tools. Keep it small and true rather than big and vague.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;S — Situation (about 20 seconds)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;~150-seat org on M365. We were rolling out a Conditional Access policy requiring a compliant device for Exchange Online and SharePoint.&lt;/li&gt;
&lt;li&gt;The policy had run in report-only for a week, and it was switched to On late Friday.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;T — Task (about 10 seconds)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Monday 8:05am the help desk queue filled with "can't open Outlook" tickets. I was the on-call admin, so I owned getting people working again and figuring out why.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;A — Action (about 90 seconds, the heart of the answer)&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Scoped it first.&lt;/strong&gt; Was it everyone, or one group? Sign-in logs showed failures only from a group of contractor laptops that had never enrolled in Intune. Employees were fine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ruled out the obvious.&lt;/strong&gt; Checked the Microsoft 365 service health page: no incident. The only recent change was our policy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confirmed the cause.&lt;/strong&gt; The sign-in log entries showed the new CA policy as the one that failed, with "device not compliant" / not managed as the reason.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contained with the smallest safe change.&lt;/strong&gt; Rather than turn the whole policy off, we temporarily excluded the contractor group (with a ticket, a named owner, and a removal date). Employees stayed protected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Communicated on a cadence.&lt;/strong&gt; A short message to affected users and their managers at 8:20 ("we know, here's the workaround, next update at 9:00"), then an all-clear at 8:50.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Didn't break-glass for convenience.&lt;/strong&gt; Emergency access accounts stayed untouched. This wasn't that kind of outage.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;R — Result (about 20 seconds)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Contractors were back in ~45 minutes. No security policy was disabled for everyone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prevention:&lt;/strong&gt; we added a pre-enforce check (review report-only results by &lt;em&gt;group&lt;/em&gt;, not just overall) and stopped enforcing on Friday afternoons. Contractors got a documented path: enroll, or use web-only access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What I'd do differently:&lt;/strong&gt; I'd have asked "who would fail this policy?" before turning it on, not after.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last line matters. Owning a miss calmly is often the strongest part of the answer.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Scenario version (if you don't have the story)
&lt;/h2&gt;

&lt;p&gt;The interviewer says: &lt;em&gt;"It's Monday, 8am. Fifty people can't get into Outlook. A Conditional Access change went in Friday. Walk me through it."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Talk through it in this order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Clarify scope:&lt;/strong&gt; who, how many, which apps, which sites? Desktop and mobile both?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rule out the service:&lt;/strong&gt; check Microsoft 365 service health before blaming your own change.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Find evidence:&lt;/strong&gt; look up one affected user in the Entra sign-in logs. Which policy applied, and what was the failure reason?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contain narrowly:&lt;/strong&gt; a scoped, time-boxed exclusion or putting that one policy back to report-only. Not "turn off all CA."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Communicate:&lt;/strong&gt; first update within ~15 minutes, then a stated cadence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prevent:&lt;/strong&gt; a group-level review of report-only results, change windows, and a rollback note written &lt;em&gt;before&lt;/em&gt; the change.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Say out loud that you'd &lt;strong&gt;follow the change process and get approval&lt;/strong&gt; for an emergency exclusion. Interviewers listen for that.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. The follow-ups they'll actually ask
&lt;/h2&gt;

&lt;p&gt;Practice these without notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Why not just turn the policy off?" &lt;em&gt;(Answer: that removes protection for everyone to fix a problem for a few. Contain narrowly.)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;"How did you know it was CA and not an M365 outage?" &lt;em&gt;(Service health + sign-in log evidence.)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;"Who did you tell, and when?"&lt;/li&gt;
&lt;li&gt;"What's a break-glass account, and would you have used it here?"&lt;/li&gt;
&lt;li&gt;"What changed in your process afterward?"&lt;/li&gt;
&lt;li&gt;"What would you do differently?"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a follow-up stumps you, say so: "I'm not sure. Here's how I'd find out." That beats guessing.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Score yourself (1–4)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Score&lt;/th&gt;
&lt;th&gt;What it sounded like&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Jumped straight to the fix. No scoping, no evidence.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Some structure, but missed blast radius or communication.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Clear: verify → contain → communicate → result.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;All of 3, plus prevention, a "what I'd do differently," and judgment about &lt;em&gt;not&lt;/em&gt; overreacting.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Aim for a 3 on the first try and a 4 by the second or third run.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common ways to lose points:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blaming a coworker or "Microsoft."&lt;/li&gt;
&lt;li&gt;Running past 3 minutes on the Situation.&lt;/li&gt;
&lt;li&gt;No numbers at all. Even rough ones help ("about 30 users," "back in under an hour").&lt;/li&gt;
&lt;li&gt;Claiming a bigger role than you had. "I was on the team that…" is fine.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  6. Want more drills like this?
&lt;/h2&gt;

&lt;p&gt;This is one of the scenario drills in the &lt;strong&gt;Sysadmin Interview &amp;amp; Career Cheatsheet Kit&lt;/strong&gt; from Admin Pack Studio ($19). It includes a role map and a STAR story bank worksheet, core Windows/AD/networking/M365 Q&amp;amp;A, timed scenario drills (morning outage, new-hire day-one failure, Patch Tuesday fallout, "can you just make me admin?", phishing mailbox rules), offer and first-90-days prep, and a weekly scorecard with a 30-day study plan. It's practice material, not a brain dump, and no one can promise you a job. The practice is what does the work.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://cashflow4375.gumroad.com/l/nojrvg" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/nojrvg&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;On the job and want to avoid the Monday lockout in the first place?&lt;/em&gt; The Entra ID Conditional Access Starter Pack ($29) covers report-only → enforce with pilot groups, break-glass hygiene, and sign-in troubleshooting cards, with read-only export scripts: &lt;a href="https://cashflow4375.gumroad.com/l/nhuyrc" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/nhuyrc&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Admin Pack Studio. Not affiliated with Microsoft. The worked example is an illustrative composite. Use your own true experience in interviews. Check current Microsoft documentation for portal names and features, which change over time.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>sysadmin</category>
      <category>career</category>
      <category>interview</category>
      <category>microsoft</category>
    </item>
    <item>
      <title>A Tier-1 helpdesk card for "Outlook keeps asking for my password": symptoms, checks, and when to escalate</title>
      <dc:creator>AdminPackStudio</dc:creator>
      <pubDate>Wed, 07 Oct 2026 13:51:34 +0000</pubDate>
      <link>https://dev.to/adminpackstudio/a-tier-1-helpdesk-card-for-outlook-keeps-asking-for-my-password-symptoms-checks-and-when-to-3cag</link>
      <guid>https://dev.to/adminpackstudio/a-tier-1-helpdesk-card-for-outlook-keeps-asking-for-my-password-symptoms-checks-and-when-to-3cag</guid>
      <description>&lt;h1&gt;
  
  
  A Tier-1 helpdesk card for "Outlook keeps asking for my password"
&lt;/h1&gt;

&lt;p&gt;It's one of the most common tickets in any Microsoft 365 shop: &lt;em&gt;"Outlook keeps popping up a password box. I type it, it goes away, and it comes back."&lt;/em&gt; Sometimes Teams and OneDrive do it too.&lt;/p&gt;

&lt;p&gt;Most Tier-1 techs handle it from memory, and that's how you get a mix of results. One tech resets the password, which rarely fixes it and sometimes makes it worse. Another removes the work account from Windows and breaks single sign-on for the whole device.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;ticket card&lt;/strong&gt; fixes that. It's one page: what the user sees, what to check in order, what Tier-1 is allowed to fix, and the exact point where you stop and escalate. Here's one you can copy into your knowledge base.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Scope: Windows 10/11 with Microsoft 365 Apps, Entra ID (Azure AD) accounts. Menu names move around, so check them against your build and your own policies.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The card
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CARD: Outlook / M365 apps keep prompting for password (Windows)

SYMPTOMS
- Repeated password prompt in Outlook (sometimes Teams/OneDrive too)
- "Need password" banner in Outlook or OneDrive
- Password is accepted, then the prompt comes back minutes/hours later
- Often follows: password change, new laptop, VPN change, recent reboot

CHECKS (in order — stop when you find the cause)
1. Scope: one user or many? One app or all M365 apps?
   Many users at once -&amp;gt; check service health / tell your lead. Don't touch devices yet.
2. Web test: can the user sign in at outlook.office.com in a private window?
   - Fails -&amp;gt; account problem (password, lockout, MFA). Go to the password/MFA card.
   - Works -&amp;gt; account is fine. Problem is on the device/app. Continue.
3. Recent password change? Other devices (phone, old laptop) may still be
   using the old password and causing lockouts.
4. Device time: Settings &amp;gt; Time &amp;amp; language. Set automatically = On, correct time zone.
5. Network: on VPN, hotel/guest Wi-Fi, or a proxy? Test once off VPN / on another network.
6. Device state (read-only): run  dsregcmd /status  and note:
   AzureAdJoined / DomainJoined / WorkplaceJoined, AzureAdPrt (YES/NO)
   Paste the output into the ticket.
7. Error text: any message like "Your sign-in was successful but doesn't
   meet the criteria..." or "device must be managed/compliant"? Screenshot it.
   That is NOT a password problem. Go straight to ESCALATE.

TIER-1 FIXES (only what your playbook allows)
- Fully close Outlook/Teams (check the system tray), then reopen.
- In Outlook/Office: File &amp;gt; Office Account &amp;gt; Sign out, reboot, sign back in.
- Clear cached Office creds: Credential Manager &amp;gt; Windows Credentials &amp;gt;
  remove entries for MicrosoftOffice / the user's M365 address. Reboot.
- Make sure Office is up to date (File &amp;gt; Office Account &amp;gt; Update Options).
- Retest with a fresh Outlook profile only if the mailbox is cloud-only
  and your playbook allows it.

DO NOT (at Tier-1)
- Reset the password "just to see" if the web test worked
- Disconnect the work/school account from Windows Settings &amp;gt; Accounts
- Remove MFA methods without verified identity and the right role
- Unenroll, reset, or reimage the device

ESCALATE WHEN
- Web sign-in fails after password/lockout checks          -&amp;gt; Identity / Tier-2
- AzureAdPrt = NO on a device that should be Entra joined -&amp;gt; Tier-2 / endpoint
- Any "device must be compliant/managed" or CA error     -&amp;gt; Endpoint / Intune admin
- Same symptom across many users                          -&amp;gt; Lead + service health
- Fixes above done and prompt returns within a day        -&amp;gt; Tier-2

ATTACH TO THE ESCALATION
- User, device name, time of last prompt, app(s) affected
- Web test result, dsregcmd /status output, screenshot of any error
- What you already tried (so Tier-2 doesn't repeat it)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Why the order matters
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The web test (check 2) does most of the work.&lt;/strong&gt; If the user can sign in to Outlook on the web in a private window, the password and the account are fine. Resetting the password at that point only adds a new problem: every other device now has a stale password and starts locking the account.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Device state comes before "fixes."&lt;/strong&gt; If &lt;code&gt;dsregcmd /status&lt;/code&gt; shows &lt;code&gt;AzureAdPrt : NO&lt;/code&gt; on a laptop that should be Entra joined, the device has no valid primary refresh token, so apps keep falling back to asking for a password. Tier-1 can capture that. Fixing it usually needs Tier-2.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compliance errors look like password problems.&lt;/strong&gt; When Conditional Access requires a compliant device and the laptop isn't compliant (it isn't enrolled, it's missing an update, BitLocker isn't reporting, and so on), the user sees a sign-in failure right after typing a correct password. Tier-1 can't fix compliance from the user's desk. The best move is a clean escalation with the screenshot and the &lt;code&gt;dsregcmd&lt;/code&gt; output attached.&lt;/p&gt;




&lt;h2&gt;
  
  
  A note template that saves Tier-2 time
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Tier-1] Outlook repeated password prompt — &amp;lt;user&amp;gt; / &amp;lt;device&amp;gt;
Scope: single user, Outlook + Teams
Web sign-in (private window): WORKS
Time sync: OK | VPN: tested off VPN, same result
dsregcmd: AzureAdJoined YES, AzureAdPrt NO
Tried: Office sign-out/in + reboot, cleared Office creds in Credential Manager
Result: prompt returns within ~1 hour
Escalating to: endpoint team (PRT missing)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two minutes of notes like this keep the ticket from bouncing back to the user with "can you try restarting?"&lt;/p&gt;




&lt;h2&gt;
  
  
  Want the rest of the cards?
&lt;/h2&gt;

&lt;p&gt;This card is a sample of the format in the &lt;strong&gt;IT Helpdesk Tier-1 Break/Fix Runbook Pack&lt;/strong&gt; ($24). The pack uses the same Symptoms → Verify → Fix → Prevent/Escalate layout for the tickets that fill Tier-1's day: password and MFA loops, VPN with no internal access, slow PCs, full disks, Wi-Fi, printers, Outlook search and send, Teams audio, and OneDrive sync. It also includes intake and escalation rules, note and handoff templates, and one &lt;strong&gt;read-only&lt;/strong&gt; PowerShell local snapshot script. The script only reads. It makes no password changes, takes no device actions, and makes no Graph writes.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://cashflow4375.gumroad.com/l/tezla" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/tezla&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If your escalations keep landing on &lt;strong&gt;Intune enrollment or compliance&lt;/strong&gt;, the &lt;em&gt;Intune &amp;amp; M365 Admin Starter Pack&lt;/em&gt; covers that side for admins ($19 during launch week, normally $29): &lt;a href="https://cashflow4375.gumroad.com/l/joonf" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/joonf&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Neither is required. The card above works fine on its own.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Admin Pack Studio. Not affiliated with Microsoft. For IT staff authorized to support their organization's users and devices. Follow your own policies, and check current Microsoft documentation for menu names and behavior.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>helpdesk</category>
      <category>sysadmin</category>
      <category>microsoft365</category>
      <category>windows</category>
    </item>
    <item>
      <title>An offboarding checklist for M365 + Intune admins — disable vs delete, license reclaim, and the device decision</title>
      <dc:creator>AdminPackStudio</dc:creator>
      <pubDate>Wed, 07 Oct 2026 13:47:47 +0000</pubDate>
      <link>https://dev.to/adminpackstudio/an-offboarding-checklist-for-m365-intune-admins-disable-vs-delete-license-reclaim-and-the-h7c</link>
      <guid>https://dev.to/adminpackstudio/an-offboarding-checklist-for-m365-intune-admins-disable-vs-delete-license-reclaim-and-the-h7c</guid>
      <description>&lt;h1&gt;
  
  
  Offboarding in M365 + Intune: a leaver checklist that doesn't lose data or leave doors open
&lt;/h1&gt;

&lt;p&gt;Offboarding usually goes wrong in one of two ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Too slow.&lt;/strong&gt; The account stays usable for days, an old phone still syncs mail, or a SaaS admin login nobody tracked keeps working.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Too fast.&lt;/strong&gt; Someone deletes the user or pulls the license on day one, and the manager loses the mailbox and OneDrive files they needed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the short version of a leaver process for &lt;strong&gt;Microsoft 365 + Entra ID + Intune&lt;/strong&gt;, for admins authorized to manage their tenant. Follow your HR, legal, and retention policies first. Retention periods and admin-center labels change over time, so check the current Microsoft docs before you rely on any number here.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Disable first, delete much later
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Disable (block sign-in)&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Delete the user&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;What it does&lt;/td&gt;
&lt;td&gt;Stops new sign-ins. Data, groups, and licenses stay put until you change them&lt;/td&gt;
&lt;td&gt;Soft-deletes the account; it can be restored for a limited window (30 days by default), then it's gone for good&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reversible?&lt;/td&gt;
&lt;td&gt;Yes, right away&lt;/td&gt;
&lt;td&gt;Only during the soft-delete window&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mailbox / OneDrive&lt;/td&gt;
&lt;td&gt;Still there&lt;/td&gt;
&lt;td&gt;Start their own retention clocks; data is lost when those run out unless a hold or retention policy keeps it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;When&lt;/td&gt;
&lt;td&gt;Last day, at the agreed time&lt;/td&gt;
&lt;td&gt;After handoff is done and retention/legal requirements are met (often 30+ days)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Default rule: disable on the last day, delete only after the handoff is finished.&lt;/strong&gt; A disabled account costs you almost nothing for a few weeks. An early delete can lose data you can't get back.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hybrid tenants:&lt;/strong&gt; if the account syncs from on-prem AD, disable it &lt;strong&gt;in AD&lt;/strong&gt;. If you only block it in the cloud, the next sync can turn it back on. (It's one of the most common "leaver still signing in" causes.)&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The last-day sequence
&lt;/h2&gt;

&lt;p&gt;Order matters. Use this as a starter, then adjust to your policy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Before last day:  Confirm date/time with HR. Flag privileged or VIP accounts.
                  Agree who receives mailbox + OneDrive + Teams/SharePoint ownership.
                  Check for legal hold / litigation requirements.
Last day (agreed time):
  1. Block sign-in (on-prem AD first if hybrid).
  2. Revoke sessions / refresh tokens (Entra admin center → user → Revoke sessions).
  3. Remove privileged roles and PIM eligibility.
  4. Reset the password if your policy requires it.
  5. Review MFA methods; remove ones tied to shared or company phones per policy.
  6. Remove from groups, except license groups until mailbox handoff is done.
  7. Mailbox: convert / delegate / auto-reply per HR (section 3).
Day +1..7:        Check sign-in logs for failed attempts or other surprises. Make the device decision (section 4).
                  Disable non-SSO SaaS accounts. Rotate shared secrets the user knew.
Day +30 / policy: Reclaim the license if it isn't already gone, delete the account, close the ticket with evidence.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Revoking sessions isn't instant everywhere.&lt;/strong&gt; Some apps hold access tokens until they expire (often up to about an hour), and apps using continuous access evaluation react faster. Block sign-in &lt;em&gt;and&lt;/em&gt; revoke sessions, then check the sign-in logs the next day.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rotate secrets as work items.&lt;/strong&gt; If the leaver knew a shared admin password, a Wi-Fi key, or an API key, track the rotation in your ticket system. Never paste the secret into the ticket.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Mailbox and OneDrive handoff (high level)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Mailbox:&lt;/strong&gt; common options are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Convert to a shared mailbox&lt;/strong&gt; and give the manager or team access. Convert &lt;em&gt;before&lt;/em&gt; you remove the license. Shared mailboxes have size limits without a license (check current docs), and hold or archive features may still need one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delegate access&lt;/strong&gt; (Full Access / Send As) for a fixed period with an end date.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-reply&lt;/strong&gt; pointing senders to the right contact. Avoid forwarding to external addresses; many orgs block it on purpose.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;OneDrive:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set the manager (or named delegate) to receive access. In many tenants, deleting the user gives the manager access automatically for the OneDrive retention period. Confirm your tenant's retention setting so nobody gets surprised.&lt;/li&gt;
&lt;li&gt;Tell the receiver &lt;strong&gt;what to move and the deadline&lt;/strong&gt;. Files that matter to the team belong in a SharePoint/Teams site, not in a former user's OneDrive.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Teams / SharePoint:&lt;/strong&gt; if the leaver was the &lt;em&gt;only&lt;/em&gt; owner of a Team, group, or site, add a new owner first. Ownerless groups turn into cleanup work later.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. The device decision: retire vs wipe (it's a judgment call)
&lt;/h2&gt;

&lt;p&gt;Intune gives you device actions in the admin center. Pick one based on &lt;strong&gt;who owns the device&lt;/strong&gt; and &lt;strong&gt;what policy and legal holds require&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Usual direction&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Personal (BYOD) phone or PC&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Retire&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Removes company data, managed apps, and profiles. Leaves personal data alone&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Corporate device, returned to IT&lt;/td&gt;
&lt;td&gt;Reset for reuse, per your reimage process&lt;/td&gt;
&lt;td&gt;Check legal hold first. Keep the Autopilot record if the hardware stays in the fleet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Corporate device, &lt;strong&gt;not&lt;/strong&gt; returned&lt;/td&gt;
&lt;td&gt;Escalate per policy; a remote wipe may be appropriate&lt;/td&gt;
&lt;td&gt;Get documented approval. Lost/stolen handling differs from "employee kept the laptop"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Device under legal hold / investigation&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Don't touch it&lt;/strong&gt; until counsel clears it&lt;/td&gt;
&lt;td&gt;Wiping evidence is a serious problem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hardware leaving the org for good&lt;/td&gt;
&lt;td&gt;Remove it from Autopilot / Intune after the reset&lt;/td&gt;
&lt;td&gt;Otherwise the next owner hits your enrollment&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Treat retire and wipe as &lt;strong&gt;deliberate, approved actions done by an authorized admin in the Intune admin center&lt;/strong&gt;, with the ticket ID recorded. Don't fire them off from a quick script at 5pm on a Friday. Confirm ownership (corporate vs personal) in the device record before you click.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. License reclaim without breaking things
&lt;/h2&gt;

&lt;p&gt;Pulling licenses too early is the most common way offboarding causes data loss.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Order:&lt;/strong&gt; convert the mailbox / finish handoff → &lt;strong&gt;then&lt;/strong&gt; remove the license. Removing an Exchange license starts a countdown on the mailbox data unless a hold or a shared-mailbox conversion protects it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Group-based licensing:&lt;/strong&gt; if licenses come from groups like &lt;code&gt;LIC-M365-E3&lt;/code&gt;, removing the user from the group removes the license. Keep that membership until handoff is finished, then remove it on purpose.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Weekly orphan check:&lt;/strong&gt; look for accounts that are &lt;strong&gt;disabled but still licensed&lt;/strong&gt;. That's money spent on nobody. A read-only Graph query is enough:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Connect-MgGraph&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Scopes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'User.Read.All'&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;Get-MgUser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-All&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Filter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'accountEnabled eq false'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Property&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'displayName'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'userPrincipalName'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'assignedLicenses'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'accountEnabled'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;Where-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AssignedLicenses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-gt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DisplayName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;UserPrincipalName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@{&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'LicenseCount'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AssignedLicenses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It only reads. Review the list with whoever owns licensing before you change anything. Some disabled accounts are kept licensed on purpose, for holds or shared mailboxes over the size limit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conditional Access and break-glass awareness
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CA exclusion groups:&lt;/strong&gt; if the leaver was in a Conditional Access exclusion group (travel exceptions, legacy-app exceptions, "temporary" bypasses), remove them. Exclusions outlive the people they were made for.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Break-glass accounts:&lt;/strong&gt; don't disable or delete your emergency-access accounts as part of someone's offboarding. If the leaver &lt;strong&gt;knew or held&lt;/strong&gt; break-glass credentials (password, FIDO key, safe combination), rotate them and record that you did, using your normal break-glass procedure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Admins leaving:&lt;/strong&gt; check what they owned: app registrations, service principals with their own credentials, automation accounts, scheduled flows running as them. Reassign ownership before those quietly break or stay unowned.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;If your CA exclusions and break-glass setup have drifted, the &lt;strong&gt;Entra ID Conditional Access Starter Pack&lt;/strong&gt; ($29) covers exclusion hygiene and emergency-access patterns: &lt;a href="https://cashflow4375.gumroad.com/l/nhuyrc" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/nhuyrc&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  6. Evidence: close the ticket like an auditor will read it
&lt;/h2&gt;

&lt;p&gt;A few lines per leaver saves a painful audit later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Leaver ticket / Last day / Sign-in blocked (time) / Sessions revoked (time) /
Roles removed / Groups removed / Mailbox action / OneDrive delegate /
Device action + approver / License removed (date) / Account deleted (date) /
Performed by (role) / Verified by (role)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Record &lt;strong&gt;roles&lt;/strong&gt;, not personal names, if the evidence gets shared widely.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common mistakes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mistake&lt;/th&gt;
&lt;th&gt;What happens&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Delete on day one&lt;/td&gt;
&lt;td&gt;Manager loses mail/files; restore window runs out&lt;/td&gt;
&lt;td&gt;Disable first; delete after handoff + retention&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;License removed before mailbox conversion&lt;/td&gt;
&lt;td&gt;Mailbox data starts expiring&lt;/td&gt;
&lt;td&gt;Convert/delegate first, then reclaim&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud-only block on a synced account&lt;/td&gt;
&lt;td&gt;Account comes back after the next sync&lt;/td&gt;
&lt;td&gt;Disable in on-prem AD&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Leaver was sole Team/site owner&lt;/td&gt;
&lt;td&gt;Ownerless groups, nobody can manage access&lt;/td&gt;
&lt;td&gt;Add new owners before the last day&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wiping a device under legal hold&lt;/td&gt;
&lt;td&gt;Evidence destroyed&lt;/td&gt;
&lt;td&gt;Check holds; get approval for any wipe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Forgetting CA exclusions / break-glass knowledge&lt;/td&gt;
&lt;td&gt;Old exceptions and known secrets linger&lt;/td&gt;
&lt;td&gt;Remove exclusions; rotate what they knew&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-SSO SaaS logins ignored&lt;/td&gt;
&lt;td&gt;Access continues outside Entra&lt;/td&gt;
&lt;td&gt;Keep a SaaS inventory in the checklist&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Want the full joiner / mover / leaver checklists?
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Entra ID Joiner-Mover-Leaver Ops Pack&lt;/strong&gt; ($29) from Admin Pack Studio turns this into repeatable checklists: joiner day-1 definition of done, a mover access-diff worksheet, leaver timeline lanes and a revoke checklist, group-based licensing and orphan hunts, plus audit evidence and JML break/fix cards. The one bonus script writes a &lt;strong&gt;blank local checklist CSV&lt;/strong&gt;. It makes no tenant calls and takes no account or device actions.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://cashflow4375.gumroad.com/l/vljmze" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/vljmze&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Managing the device side too? The &lt;strong&gt;Intune &amp;amp; M365 Admin Starter Pack&lt;/strong&gt; ($19 during launch week; normally $29) covers enrollment hygiene, compliance baselines, inventory snapshots, and break/fix cards, with read-only PowerShell scripts: &lt;a href="https://cashflow4375.gumroad.com/l/joonf" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/joonf&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Admin Pack Studio. Not affiliated with Microsoft. Operational guidance for admins authorized to manage their tenant and devices. Follow your HR, legal hold, and retention policies, and check current Microsoft documentation for retention periods and admin-center steps.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>microsoft</category>
      <category>sysadmin</category>
      <category>security</category>
      <category>identity</category>
    </item>
    <item>
      <title>Intune Win32 app shows "Failed" after a successful install? It's usually the detection rule</title>
      <dc:creator>AdminPackStudio</dc:creator>
      <pubDate>Wed, 07 Oct 2026 13:45:15 +0000</pubDate>
      <link>https://dev.to/adminpackstudio/intune-win32-app-shows-failed-after-a-successful-install-its-usually-the-detection-rule-me8</link>
      <guid>https://dev.to/adminpackstudio/intune-win32-app-shows-failed-after-a-successful-install-its-usually-the-detection-rule-me8</guid>
      <description>&lt;h1&gt;
  
  
  Intune Win32 app shows "Failed" after a successful install? It's usually the detection rule
&lt;/h1&gt;

&lt;p&gt;Here's a ticket most Intune admins have seen. The installer ran and the app opens fine on the device, but Intune reports &lt;strong&gt;Failed&lt;/strong&gt;. Or the app installs again every few hours. Or a Required app stays "Install pending" forever.&lt;/p&gt;

&lt;p&gt;In most cases the installer is fine. &lt;strong&gt;The detection rule is wrong.&lt;/strong&gt; This post covers why that happens, how detection differs from requirement rules, the mistakes that come up most, and where to look in the logs. Everything here is read-only troubleshooting. You don't need any special tooling.&lt;/p&gt;

&lt;p&gt;Intune UI labels and log names change over time, so check them against current Microsoft docs.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. How Intune decides "installed"
&lt;/h2&gt;

&lt;p&gt;For a Win32 app, the Intune Management Extension (IME) on the device runs roughly this sequence:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Requirement rules.&lt;/strong&gt; Is this device allowed to get the app (OS version, architecture, disk space, custom checks)? If not, the app shows &lt;strong&gt;Not applicable&lt;/strong&gt; and nothing else happens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detection (before install).&lt;/strong&gt; Is the app already there? If yes, the install is skipped and the app reports as installed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install.&lt;/strong&gt; Runs your install command and reads the &lt;strong&gt;exit code&lt;/strong&gt; against your return-code mapping.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detection (after install).&lt;/strong&gt; Runs the detection rule again. &lt;strong&gt;This step decides the final status.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That last step is the part people forget. A clean exit code 0 followed by a detection rule that comes back false means Intune reports the app as &lt;em&gt;not detected after installation&lt;/em&gt;, and the status goes to &lt;strong&gt;Failed&lt;/strong&gt;. A Required assignment then retries on its normal schedule, so you get the install loop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule of thumb:&lt;/strong&gt; exit code success + Failed status = look at detection first.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Detection rules vs requirement rules
&lt;/h2&gt;

&lt;p&gt;These two get mixed up a lot:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Requirement rule&lt;/th&gt;
&lt;th&gt;Detection rule&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Question it answers&lt;/td&gt;
&lt;td&gt;"Should this device get the app?"&lt;/td&gt;
&lt;td&gt;"Is the app on this device right now?"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;When false&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Not applicable&lt;/strong&gt; (no install attempt)&lt;/td&gt;
&lt;td&gt;Install attempted (before) or &lt;strong&gt;Failed&lt;/strong&gt; (after)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical checks&lt;/td&gt;
&lt;td&gt;OS build, x64, free disk, a prerequisite present&lt;/td&gt;
&lt;td&gt;MSI product code, file + version, registry value, script&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Common mistake&lt;/td&gt;
&lt;td&gt;Using it to check "already installed"&lt;/td&gt;
&lt;td&gt;Checking something the installer doesn't actually write&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If a device shows &lt;strong&gt;Not applicable&lt;/strong&gt; and you expected an install, check the requirement rules. If it shows &lt;strong&gt;Failed&lt;/strong&gt; or keeps retrying, check the detection rule.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. The detection mistakes that cause most loops
&lt;/h2&gt;

&lt;h3&gt;
  
  
  MSI product code
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The product code changes between versions.&lt;/strong&gt; You upgrade the package, keep the old detection rule, and either the new version never detects or the old version detects as "good enough."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The MSI is wrapped in an EXE bootstrapper&lt;/strong&gt; that installs several MSIs, and you picked the wrong product code.&lt;/li&gt;
&lt;li&gt;Fix: read the product code from the exact MSI you're shipping, and update it whenever you change versions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  File or folder
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;x86 vs x64 paths.&lt;/strong&gt; A 32-bit app installs to &lt;code&gt;C:\Program Files (x86)\...&lt;/code&gt; and your rule checks &lt;code&gt;C:\Program Files\...&lt;/code&gt;, or the other way round. Check the "Associated with a 32-bit app on 64-bit clients" setting. It changes which path and registry view the IME checks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User-profile installs.&lt;/strong&gt; The app writes to &lt;code&gt;%LOCALAPPDATA%&lt;/code&gt; but the app is set to install in system context, so detection looks in the wrong profile.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"File exists" with no version.&lt;/strong&gt; It passes for an old version and leaves you thinking the upgrade worked. Use a version comparison (greater than or equal to the version you ship) where you can.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Files that stay behind after uninstall.&lt;/strong&gt; Logs, configs, or an updater folder. Detection stays true and uninstall looks like it failed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Registry
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WOW6432Node.&lt;/strong&gt; 32-bit installers write under &lt;code&gt;HKLM\SOFTWARE\WOW6432Node\...&lt;/code&gt;. If the 32-bit setting doesn't match, the IME looks in the wrong view.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HKCU vs HKLM.&lt;/strong&gt; The IME runs system-context detection, so a value written per user under HKCU isn't where it looks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Value type and comparison.&lt;/strong&gt; Comparing a version stored as a string with an integer or version operator gives results you didn't expect. Check the type in Registry Editor first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uninstall GUID keys that change per version.&lt;/strong&gt; Same problem as MSI product codes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Custom detection script
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Detected means exit code 0 &lt;em&gt;and&lt;/em&gt; output written to STDOUT.&lt;/strong&gt; A script that exits 0 and prints nothing counts as &lt;em&gt;not detected&lt;/em&gt;. A script that writes errors to STDERR also counts as not detected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slow scripts&lt;/strong&gt; (network calls, big searches) can time out.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;32-bit vs 64-bit PowerShell.&lt;/strong&gt; The script may run in a 32-bit host unless you set it to run as 64-bit, which changes what the registry and file system show it.&lt;/li&gt;
&lt;li&gt;Keep detection scripts &lt;strong&gt;read-only and fast&lt;/strong&gt;. They should check state, never change it.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. Test detection before you assign Required
&lt;/h2&gt;

&lt;p&gt;Do this on a lab VM before you upload. It takes about ten minutes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Expected&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Run your exact silent install command manually&lt;/td&gt;
&lt;td&gt;Exit code is what you mapped as success&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Check the detection target (file/registry/MSI)&lt;/td&gt;
&lt;td&gt;Present, correct version&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Run your exact uninstall command&lt;/td&gt;
&lt;td&gt;Exit code success&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Check the detection target again&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Gone&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If detection still matches after uninstall, or doesn't match after install, fix the rule before any Required assignment. Pilot the app as &lt;strong&gt;Available&lt;/strong&gt; or on a small Required group of lab devices first.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Reading the IME logs (high level)
&lt;/h2&gt;

&lt;p&gt;On the device, with authorization, the logs are in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C:\ProgramData\Microsoft\IntuneManagementExtension\Logs\
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Useful files (names vary by IME version):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AppWorkload.log&lt;/strong&gt;: newer builds put most Win32 app download, install, and detection activity here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IntuneManagementExtension.log&lt;/strong&gt;: the main IME log. Older builds put Win32 app activity here too.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AgentExecutor.log&lt;/strong&gt;: what happened when PowerShell scripts ran, including custom detection and requirement scripts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How to read them without getting lost:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the log in a log viewer that handles CMTrace-format logs (or just a text editor) and &lt;strong&gt;search for the app name or its app ID&lt;/strong&gt; (the GUID from the Intune portal URL).&lt;/li&gt;
&lt;li&gt;Find the &lt;strong&gt;requirement&lt;/strong&gt; result. If it's "not applicable," stop here and fix requirements.&lt;/li&gt;
&lt;li&gt;Find the &lt;strong&gt;install&lt;/strong&gt; step and note the &lt;strong&gt;exit code&lt;/strong&gt;. Compare it with your return-code mapping.&lt;/li&gt;
&lt;li&gt;Find the &lt;strong&gt;detection after install&lt;/strong&gt; result. If it's false following a successful exit code, your detection rule doesn't match what the installer wrote. Go back to section 3.&lt;/li&gt;
&lt;li&gt;Check the &lt;strong&gt;vendor's own install log&lt;/strong&gt; too (add a &lt;code&gt;/log&lt;/code&gt; or &lt;code&gt;/l*v&lt;/code&gt; switch to your install command). It tells you what was actually written, and where.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can also gather these logs remotely with the &lt;strong&gt;Collect diagnostics&lt;/strong&gt; device action in Intune where your tenant supports it. That's read-only. It doesn't change the device.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Quick triage table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;Most likely cause&lt;/th&gt;
&lt;th&gt;First check&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Failed, but the app works&lt;/td&gt;
&lt;td&gt;Detection doesn't match the install&lt;/td&gt;
&lt;td&gt;Detection target vs what the installer wrote&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reinstalls every few hours&lt;/td&gt;
&lt;td&gt;Detection false after a successful install&lt;/td&gt;
&lt;td&gt;Same, plus 32-bit setting and HKCU vs HKLM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Not applicable&lt;/td&gt;
&lt;td&gt;Requirement rule&lt;/td&gt;
&lt;td&gt;OS/arch/disk/custom requirement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Install pending forever&lt;/td&gt;
&lt;td&gt;Device not checking in, or IME not getting the assignment&lt;/td&gt;
&lt;td&gt;Device sync, assignment group&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uninstall "fails"&lt;/td&gt;
&lt;td&gt;Detection still true after uninstall&lt;/td&gt;
&lt;td&gt;Files or registry keys left behind&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Upgrade never happens&lt;/td&gt;
&lt;td&gt;Old version still satisfies detection&lt;/td&gt;
&lt;td&gt;Add version comparison; update the MSI code&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Want the full packaging workflow?
&lt;/h2&gt;

&lt;p&gt;Detection is one piece. The &lt;strong&gt;Intune Win32 App Packaging Starter Pack&lt;/strong&gt; from Admin Pack Studio ($39) covers the whole workflow: packaging basics and silent-switch research, detection truth tables for MSI/file/registry/script rules, install and uninstall commands with return codes and logging, six failure triage cards, and pilot-to-production gates including supersedence. It includes one &lt;strong&gt;read-only&lt;/strong&gt; local evidence helper script that checks whether a file or registry path exists and records the file version, so you can design detection rules from real evidence. It doesn't install, uninstall, or change anything.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://cashflow4375.gumroad.com/l/cgnpzt" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/cgnpzt&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If your apps are fine and the real problem is enrollment or compliance, our Intune &amp;amp; M365 Admin Starter Pack covers that ($19 launch week, normally $29): &lt;a href="https://cashflow4375.gumroad.com/l/joonf" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/joonf&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Admin Pack Studio. Not affiliated with Microsoft. Operational guidance for admins authorized to manage their tenant and devices. Pilot first, and check current Microsoft documentation for setting names and log locations.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>microsoft</category>
      <category>sysadmin</category>
      <category>windows</category>
      <category>devops</category>
    </item>
    <item>
      <title>Windows Update rings for Intune pilots — pilot vs broad, deferrals, and why "minimum OS" compliance fails first</title>
      <dc:creator>AdminPackStudio</dc:creator>
      <pubDate>Wed, 07 Oct 2026 13:41:52 +0000</pubDate>
      <link>https://dev.to/adminpackstudio/windows-update-rings-for-intune-pilots-pilot-vs-broad-deferrals-and-why-minimum-os-compliance-dmp</link>
      <guid>https://dev.to/adminpackstudio/windows-update-rings-for-intune-pilots-pilot-vs-broad-deferrals-and-why-minimum-os-compliance-dmp</guid>
      <description>&lt;h1&gt;
  
  
  Windows Update rings for Intune pilots: a starter layout that won't page you
&lt;/h1&gt;

&lt;p&gt;If every device takes this month's quality update the day it ships, one bad driver or a broken line-of-business app hits the whole company at once. &lt;strong&gt;Update rings exist to buy you detection time.&lt;/strong&gt; A small group gets updates first, you watch for problems, and the rest of the fleet follows a few days later.&lt;/p&gt;

&lt;p&gt;This is the short, practical version for admins using &lt;strong&gt;Intune → Devices → Windows → Update rings for Windows 10 and later&lt;/strong&gt;. It covers Windows only. Exact setting names and limits move over time, so check them against current Microsoft docs before you copy any numbers.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. A starter ring layout
&lt;/h2&gt;

&lt;p&gt;Three rings covers most small and mid-size tenants:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Ring&lt;/th&gt;
&lt;th&gt;Who&lt;/th&gt;
&lt;th&gt;Size (starter idea)&lt;/th&gt;
&lt;th&gt;Quality deferral (starter idea)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ring 0 — IT&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;IT staff + a few willing champions&lt;/td&gt;
&lt;td&gt;~1–3%&lt;/td&gt;
&lt;td&gt;0 days&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ring 1 — Pilot&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A mix across departments (not only IT)&lt;/td&gt;
&lt;td&gt;~10–15%&lt;/td&gt;
&lt;td&gt;A few days (e.g. 3–5)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ring 2 — Broad&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Everyone else&lt;/td&gt;
&lt;td&gt;The rest&lt;/td&gt;
&lt;td&gt;About a week or more, inside your patch SLA&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A few rules that save pain later:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Assign rings to device groups&lt;/strong&gt;, not just user groups. Patching is a device problem, and shared or multi-user devices make user targeting messy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One ring per device.&lt;/strong&gt; If a device lands in two update ring policies with different values, you'll get conflicts and confusing reports. Use clear names like &lt;code&gt;WU-Ring0-IT&lt;/code&gt;, &lt;code&gt;WU-Ring1-Pilot&lt;/code&gt;, &lt;code&gt;WU-Ring2-Broad&lt;/code&gt;, and make the broad group exclude the earlier rings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pilot ≠ IT only.&lt;/strong&gt; Your pilot ring needs Finance's and Ops' real apps on it. That's where the breakage shows up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execs usually follow Broad&lt;/strong&gt;, not first. If someone senior insists on being early, write down that they agreed to it.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Quality vs feature updates (they're not the same dial)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Quality updates&lt;/th&gt;
&lt;th&gt;Feature updates&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;What&lt;/td&gt;
&lt;td&gt;Monthly cumulative security + fixes (Patch Tuesday)&lt;/td&gt;
&lt;td&gt;New Windows version (e.g. a new 24H2-style release)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Risk&lt;/td&gt;
&lt;td&gt;Usually lower, but a bad one still hurts&lt;/td&gt;
&lt;td&gt;Higher. Apps, drivers, and hardware eligibility all matter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ring setting&lt;/td&gt;
&lt;td&gt;Quality update deferral (days)&lt;/td&gt;
&lt;td&gt;Feature update deferral (days), or a separate &lt;strong&gt;Feature updates&lt;/strong&gt; policy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical pace&lt;/td&gt;
&lt;td&gt;Days&lt;/td&gt;
&lt;td&gt;Weeks to months, pilot first&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two practical points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you control the Windows version with a &lt;strong&gt;Feature updates policy&lt;/strong&gt; (pin a target version), Microsoft's guidance is to leave the feature deferral in the update ring at &lt;strong&gt;0&lt;/strong&gt; so the two settings don't fight. Check current docs for your setup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deferral and deadline are different things.&lt;/strong&gt; Deferral controls &lt;em&gt;when the update is offered&lt;/em&gt;. Deadline settings (plus grace period and restart behavior) control &lt;em&gt;how long the user can put off installing and rebooting&lt;/em&gt; after it's offered. A pilot ring with 0-day deferral and a long deadline can still be weeks behind in practice.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Why "minimum OS version" compliance fails first
&lt;/h2&gt;

&lt;p&gt;This is the most common way rings and compliance end up fighting each other.&lt;/p&gt;

&lt;p&gt;You set a compliance policy with &lt;strong&gt;Minimum OS version&lt;/strong&gt; = this month's build (e.g. &lt;code&gt;10.0.22631.xxxx&lt;/code&gt;) right after Patch Tuesday. Then:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ring 0 gets the update, but some of it is still waiting on a reboot.&lt;/li&gt;
&lt;li&gt;Rings 1 and 2 &lt;strong&gt;haven't been offered the build yet&lt;/strong&gt;, because you deferred them on purpose.&lt;/li&gt;
&lt;li&gt;Compliance evaluates them anyway. Every device below that build shows &lt;strong&gt;noncompliant&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;If Conditional Access requires a compliant device, those users are now &lt;strong&gt;blocked from email and Teams&lt;/strong&gt; because of a schedule &lt;em&gt;you&lt;/em&gt; chose.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The device didn't do anything wrong. The compliance rule got ahead of the ring.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Safer habits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set minimum OS to a build that &lt;strong&gt;your broad ring has actually received&lt;/strong&gt;: usually last month's cumulative, or the org standard (N-1). Raise it only after Ring 2's deadline has passed and your reports show the fleet caught up.&lt;/li&gt;
&lt;li&gt;Use the compliance &lt;strong&gt;grace period / actions for noncompliance&lt;/strong&gt; so a device gets time (and a notification) before it's marked noncompliant, instead of being blocked right away.&lt;/li&gt;
&lt;li&gt;Look at the gap before you raise the bar. A read-only Graph pull of OS versions tells you how many devices you'd break:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Connect-MgGraph&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Scopes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'DeviceManagementManagedDevices.Read.All'&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;Get-MgDeviceManagementManagedDevice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-All&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Filter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"operatingSystem eq 'Windows'"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Property&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'deviceName'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'osVersion'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'lastSyncDateTime'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;Group-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;OsVersion&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Sort-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Count&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Descending&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a big chunk of the fleet sits below the build you were about to require, wait.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Treat &lt;strong&gt;feature-version minimums&lt;/strong&gt; (e.g. "must be on 23H2 or later") as a separate, slower project with its own pilot. Don't bundle it into a monthly change.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. A simple monthly rhythm
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Patch Tuesday:     Ring 0 offered (0-day deferral). Read known-issues notes.
Wed–Thu:           Validate Ring 0: install success, reboots done, smoke tests.
Following days:    Ring 1 offered (deferral expires). Watch helpdesk volume.
~1 week+ later:    Ring 2 offered if Ring 1 is clean.
After Ring 2 deadline + reports caught up:  consider raising min OS in compliance.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Smoke tests worth five minutes on Ring 0/1:&lt;/strong&gt; Outlook send/receive, a Teams call, VPN connect, your top 3–5 line-of-business apps, printing, browser sign-in to your identity provider, and a check that BitLocker still reports healthy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When something breaks:&lt;/strong&gt; pause the affected rings (quality and feature pauses are separate, and pauses expire on their own, so note when). Write down who approved it, the reopen criteria, and a reopen date. A pause with no end date turns into unpatched devices.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Common mistakes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mistake&lt;/th&gt;
&lt;th&gt;What happens&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Min OS compliance raised on Patch Tuesday&lt;/td&gt;
&lt;td&gt;Deferred rings go noncompliant, CA blocks users&lt;/td&gt;
&lt;td&gt;Raise only after the broad ring has the build&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Device in two ring policies&lt;/td&gt;
&lt;td&gt;Conflicts, reports nobody trusts&lt;/td&gt;
&lt;td&gt;One ring per device, exclusions on the broad group&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pilot ring is only IT laptops&lt;/td&gt;
&lt;td&gt;LOB app breakage found in Broad&lt;/td&gt;
&lt;td&gt;Add real users from each department&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Treating "deferral 0" as "patched today"&lt;/td&gt;
&lt;td&gt;Long deadlines and pending reboots mean it isn't installed&lt;/td&gt;
&lt;td&gt;Watch install/reboot status, not just policy assignment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Feature deferral in the ring + a Feature updates policy&lt;/td&gt;
&lt;td&gt;Confusing or blocked version offers&lt;/td&gt;
&lt;td&gt;Pick one control. With a Feature updates policy, ring feature deferral = 0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pausing with no reopen date&lt;/td&gt;
&lt;td&gt;Security debt piles up quietly&lt;/td&gt;
&lt;td&gt;Time-box every pause with an owner&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exec devices excluded "temporarily"&lt;/td&gt;
&lt;td&gt;Forgotten, unpatched for months&lt;/td&gt;
&lt;td&gt;Every exclusion gets an owner and a review date&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ignoring the reports&lt;/td&gt;
&lt;td&gt;Problems found by users first&lt;/td&gt;
&lt;td&gt;Check Intune's Windows update reports for errors weekly&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  6. When it's not actually an update-ring problem
&lt;/h2&gt;

&lt;p&gt;Not every "it broke after Tuesday" ticket is about Windows Update:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Device isn't getting the ring at all:&lt;/strong&gt; check enrollment, sync, and group membership before you touch ring settings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compliance flapping right after patching:&lt;/strong&gt; usually the min-OS timing from section 3, or BitLocker/health attestation re-evaluating after a reboot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An app failed to install or update:&lt;/strong&gt; that's app deployment, not update rings.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Side note: app installs are a different problem.&lt;/strong&gt; Update rings only control &lt;em&gt;Windows&lt;/em&gt; quality and feature updates. They don't install or update your Win32 apps. If your real headache is Win32 apps failing to install, reinstalling in a loop, or showing "not detected" after a successful install, that's packaging and detection rules. We cover it separately in a Win32 app packaging pack ($39): &lt;a href="https://cashflow4375.gumroad.com/l/cgnpzt" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/cgnpzt&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Want the compliance side done properly?
&lt;/h2&gt;

&lt;p&gt;Most ring pain shows up as compliance pain. The &lt;strong&gt;Intune &amp;amp; M365 Admin Starter Pack&lt;/strong&gt; ($19 during launch week; normally $29) covers enrollment hygiene, a baseline Windows compliance bar (including minimum OS set to builds you actually patch to), inventory snapshots, M365 admin hygiene, and break/fix cards. It also includes three &lt;strong&gt;read-only&lt;/strong&gt; PowerShell scripts: a local enrollment snapshot, a Graph managed-device snapshot, and a compliance policy summary. The scripts only read. They take no device actions and make no policy changes.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://cashflow4375.gumroad.com/l/joonf" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/joonf&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Admin Pack Studio. Not affiliated with Microsoft. Operational guidance for admins authorized to manage their tenant. Pilot first, and check current Microsoft documentation for setting names and limits.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>microsoft</category>
      <category>sysadmin</category>
      <category>windows</category>
      <category>security</category>
    </item>
    <item>
      <title>"Company Portal can't connect" / device not syncing — a 10-minute triage order for Intune admins</title>
      <dc:creator>AdminPackStudio</dc:creator>
      <pubDate>Wed, 07 Oct 2026 04:09:52 +0000</pubDate>
      <link>https://dev.to/adminpackstudio/company-portal-cant-connect-device-not-syncing-a-10-minute-triage-order-for-intune-admins-2ab7</link>
      <guid>https://dev.to/adminpackstudio/company-portal-cant-connect-device-not-syncing-a-10-minute-triage-order-for-intune-admins-2ab7</guid>
      <description>&lt;h1&gt;
  
  
  "Company Portal can't connect": a 10-minute triage order
&lt;/h1&gt;

&lt;p&gt;The ticket says &lt;em&gt;"Company Portal can't connect"&lt;/em&gt; or &lt;em&gt;"my laptop isn't getting the new policy."&lt;/em&gt; The tempting move is to start re-enrolling. Usually you don't need to. Most of these tickets come down to the same handful of causes, and you can check all of them &lt;strong&gt;without changing anything on the device or in the tenant&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here's the order we work through, cheapest checks first. It's Windows-focused; mobile platforms have their own quirks.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Is the user actually in scope? (license + MDM scope)
&lt;/h2&gt;

&lt;p&gt;You'd be surprised how many "Intune is broken" tickets end right here.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Check&lt;/th&gt;
&lt;th&gt;Where&lt;/th&gt;
&lt;th&gt;What you want&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Intune-eligible license&lt;/td&gt;
&lt;td&gt;Microsoft 365 admin center → user → Licenses&lt;/td&gt;
&lt;td&gt;e.g. Business Premium, E3/E5 with Intune, or Intune Plan 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MDM user scope&lt;/td&gt;
&lt;td&gt;Entra admin center → Mobility (MDM and MAM) → Microsoft Intune&lt;/td&gt;
&lt;td&gt;User is in the scoped group (or scope is All) — &lt;strong&gt;not&lt;/strong&gt; left on a pilot group they're not in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enrollment restrictions&lt;/td&gt;
&lt;td&gt;Intune admin center → Devices → Enrollment → restrictions&lt;/td&gt;
&lt;td&gt;Platform/personal-device restrictions and device limit aren't blocking this user&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Right account&lt;/td&gt;
&lt;td&gt;Ask the user&lt;/td&gt;
&lt;td&gt;Signed in with their &lt;strong&gt;work&lt;/strong&gt; account, not a personal Microsoft account or a second tenant&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If the license was just assigned, give it a little time to propagate before you decide it didn't work.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. What does the device think it is? (&lt;code&gt;dsregcmd /status&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;Run this in a normal command prompt on the device:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dsregcmd /status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look at:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;What it tells you&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;AzureAdJoined&lt;/code&gt; / &lt;code&gt;DomainJoined&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Matches the join type you expect (Entra joined vs hybrid)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;WorkplaceJoined&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;YES&lt;/code&gt; on a corporate device often means a user added a work account to a personal-style setup — check it's the path you intended&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AzureAdPrt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;NO&lt;/code&gt; points at a sign-in/token problem, not an Intune policy problem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;MdmUrl&lt;/code&gt; (Tenant details)&lt;/td&gt;
&lt;td&gt;Empty usually means the device never completed MDM enrollment — go back to section 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TenantName&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;It's &lt;em&gt;your&lt;/em&gt; tenant&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Also check &lt;strong&gt;Settings → Accounts → Access work or school&lt;/strong&gt;. A healthy enrolled device shows the work account with an &lt;strong&gt;Info&lt;/strong&gt; button. No Info button = MDM enrollment isn't there.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Trigger a sync — and look at the result, not just the spinner
&lt;/h2&gt;

&lt;p&gt;Three places to kick a check-in:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Company Portal&lt;/strong&gt; → Settings → &lt;strong&gt;Sync&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Settings → Accounts → Access work or school&lt;/strong&gt; → account → &lt;strong&gt;Info&lt;/strong&gt; → &lt;strong&gt;Sync&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Intune admin center&lt;/strong&gt; → Devices → the device → &lt;strong&gt;Sync&lt;/strong&gt; (this only &lt;em&gt;asks&lt;/em&gt; the device to check in; it doesn't force a result)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then look at the outcome:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Info page&lt;/strong&gt; shows the last attempted and last successful sync times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event Viewer&lt;/strong&gt; → Applications and Services Logs → Microsoft → Windows → &lt;code&gt;DeviceManagement-Enterprise-Diagnostics-Provider&lt;/code&gt; → &lt;strong&gt;Admin&lt;/strong&gt;. Errors here are much more useful than "can't connect" in the UI.&lt;/li&gt;
&lt;li&gt;In the Intune admin center, compare the device's &lt;strong&gt;Last check-in&lt;/strong&gt; with what the user is telling you.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the sync time moves but the policy still doesn't show up, it's an &lt;strong&gt;assignment&lt;/strong&gt; problem (wrong group, filter, user vs device targeting), not a connectivity problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Network, proxy, and TLS inspection
&lt;/h2&gt;

&lt;p&gt;When the device is in scope and enrolled but still can't reach the service, it's usually the network path:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Date/time and time zone.&lt;/strong&gt; A clock that's off breaks TLS and token checks. Check this first, it's free.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proxy.&lt;/strong&gt; Company Portal and the MDM client need to reach Microsoft's Intune and Entra endpoints. An authenticated proxy that the system context can't satisfy will block check-ins even when the browser works fine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSL/TLS inspection.&lt;/strong&gt; Breaking and re-signing traffic to Intune/Entra endpoints is a classic cause of "can't connect." Use Microsoft's published Intune network endpoints list and exclude them from inspection per your security team's process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Different network test.&lt;/strong&gt; If it works on a phone hotspot and fails on the office LAN, stop debugging the laptop and talk to whoever owns the firewall.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VPN split tunnel.&lt;/strong&gt; Some full-tunnel VPN configs route management traffic somewhere it can't get out.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  5. Common false alarms
&lt;/h2&gt;

&lt;p&gt;These look like failures but often aren't:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What you see&lt;/th&gt;
&lt;th&gt;What's often really going on&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Device shows stale "last check-in"&lt;/td&gt;
&lt;td&gt;Laptop was asleep, off, or in a bag over the weekend. Check whether it's actually been online.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;New policy "not applied" 10 minutes after assignment&lt;/td&gt;
&lt;td&gt;Regular check-ins run on a schedule (hours, not minutes). Trigger a sync and give it time before escalating.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compliance shows "Not evaluated" / "In grace period"&lt;/td&gt;
&lt;td&gt;Evaluation hasn't completed or grace hasn't expired yet — not the same as noncompliant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Company Portal says "can't connect", but &lt;code&gt;MdmUrl&lt;/code&gt; is set and sync times are moving&lt;/td&gt;
&lt;td&gt;Often the Company Portal app itself (sign-in cache, outdated app version). Device management may be fine.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Two device records for one laptop&lt;/td&gt;
&lt;td&gt;Stale record from a previous enrollment. Look at enrolled date + last check-in before assuming the "broken" one is the live one.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Company Portal missing entirely&lt;/td&gt;
&lt;td&gt;Microsoft Store access blocked or the app isn't assigned/available to the user&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  6. A read-only check from the admin side
&lt;/h2&gt;

&lt;p&gt;If you want to confirm what Intune sees without touching the device, a delegated Graph read with a read-only scope is enough:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Connect-MgGraph&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Scopes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'DeviceManagementManagedDevices.Read.All'&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;Get-MgDeviceManagementManagedDevice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Filter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deviceName eq 'LAPTOP-123'"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Property&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="s1"&gt;'deviceName'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'userPrincipalName'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'complianceState'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'lastSyncDateTime'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'enrolledDateTime'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'managementAgent'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DeviceName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;UserPrincipalName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ComplianceState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;LastSyncDateTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;EnrolledDateTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ManagementAgent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Id&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Intune Reader (or an equivalent read role) is enough for this. You don't need Global Admin to look. Keep the output off public forums, since it includes UPNs and device IDs.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. When to stop and escalate
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Section 1 fails:&lt;/strong&gt; licensing / Entra admin. Not an Intune bug.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Section 4 fails:&lt;/strong&gt; network / security team, with your evidence (works on hotspot, fails on LAN, event log errors).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Device enrolled, syncing, still wrong policy:&lt;/strong&gt; assignment review (groups, filters, user vs device targeting).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hybrid joined but no MDM:&lt;/strong&gt; check the automatic MDM enrollment GPO and that hybrid join itself is healthy before anything else.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Side note — new device stuck during setup?&lt;/strong&gt; If the "can't connect" is really a brand-new device hanging on the Enrollment Status Page during Autopilot, that's a different triage order (hash → profile assignment → ESP blockers → network). We packaged that one separately as an Autopilot ESP pack ($29): &lt;a href="https://cashflow4375.gumroad.com/l/hlanei" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/hlanei&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Write the ticket up with the dsregcmd output (redacted), the sync timestamps, and which section failed. Next time, helpdesk can get through sections 1–3 before it reaches you.&lt;/p&gt;




&lt;h2&gt;
  
  
  Related reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/adminpackstudio/bitlocker-still-encrypting-why-intune-marks-you-noncompliant-and-how-grace-periods-save-monday-2l6h"&gt;BitLocker still encrypting? Why Intune marks you noncompliant (and how grace periods save Monday)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/adminpackstudio/the-30-minute-monday-habit-weekly-read-only-intune-device-compliance-csv-snapshots-3fd2"&gt;The 30-minute Monday habit: weekly read-only Intune device compliance CSV snapshots (Graph)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/adminpackstudio/conditional-access-without-the-monday-lockout-report-only-enforce-4jbj"&gt;Conditional Access without the Monday lockout: report-only → enforce&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Want the full runbook?
&lt;/h2&gt;

&lt;p&gt;This post is the short version. The &lt;strong&gt;Intune &amp;amp; M365 Admin Starter Pack&lt;/strong&gt; ($19 during launch week; normally $29) includes enrollment hygiene (with a triage map for exactly these symptoms), baseline compliance, inventory snapshots, M365 admin hygiene, and break/fix cards. It also comes with three &lt;strong&gt;read-only&lt;/strong&gt; PowerShell scripts: a local enrollment snapshot (no Graph needed, handy for "is &lt;code&gt;MdmUrl&lt;/code&gt; empty?"), a Graph managed-device snapshot, and a compliance policy summary. The scripts only read. They take no device actions and make no policy changes.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://cashflow4375.gumroad.com/l/joonf" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/joonf&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Admin Pack Studio. Not affiliated with Microsoft. Operational guidance for admins authorized to manage their tenant. Pilot first.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>microsoft</category>
      <category>sysadmin</category>
      <category>windows</category>
      <category>security</category>
    </item>
    <item>
      <title>The 30-minute Monday habit — weekly read-only Intune device + compliance CSV snapshots</title>
      <dc:creator>AdminPackStudio</dc:creator>
      <pubDate>Wed, 07 Oct 2026 04:05:38 +0000</pubDate>
      <link>https://dev.to/adminpackstudio/the-30-minute-monday-habit-weekly-read-only-intune-device-compliance-csv-snapshots-3fd2</link>
      <guid>https://dev.to/adminpackstudio/the-30-minute-monday-habit-weekly-read-only-intune-device-compliance-csv-snapshots-3fd2</guid>
      <description>&lt;h1&gt;
  
  
  The 30-minute Monday habit: weekly read-only Intune snapshots
&lt;/h1&gt;

&lt;p&gt;"Are we healthier than last month?" is a hard question to answer from the Intune portal. Portal views show &lt;em&gt;now&lt;/em&gt;. They don't version-control, they don't diff, and nobody remembers what the noncompliant count was three Mondays ago.&lt;/p&gt;

&lt;p&gt;The fix is boring: &lt;strong&gt;export device and compliance state to a dated CSV once a week, read-only, and compare.&lt;/strong&gt; Here's the pattern we use.&lt;/p&gt;

&lt;p&gt;Related reading:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to/adminpackstudio/conditional-access-without-the-monday-lockout-report-only-enforce-4jbj"&gt;Conditional Access without the Monday lockout&lt;/a&gt; (report-only → enforce)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/adminpackstudio/bitlocker-still-encrypting-why-intune-marks-you-noncompliant-and-how-grace-periods-save-monday-2l6h"&gt;BitLocker still encrypting? Why Intune marks you noncompliant&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Read-only, least privilege, on purpose
&lt;/h2&gt;

&lt;p&gt;A snapshot job should never be able to change anything. Set it up so it &lt;em&gt;can't&lt;/em&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Choice&lt;/th&gt;
&lt;th&gt;Starter setting&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Entra role for the person running it&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Intune Reader&lt;/strong&gt; or &lt;strong&gt;Global Reader&lt;/strong&gt; if that's sufficient in your tenant — not Global Admin for a weekly export&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Graph scope — devices&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DeviceManagementManagedDevices.Read.All&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Graph scope — compliance policies&lt;/td&gt;
&lt;td&gt;&lt;code&gt;DeviceManagementConfiguration.Read.All&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Where it runs&lt;/td&gt;
&lt;td&gt;A dedicated admin workstation or hardened jump box — not a shared PC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auth&lt;/td&gt;
&lt;td&gt;Interactive delegated sign-in to start; automate later with app permissions + certificate only once you've thought it through&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If &lt;code&gt;Connect-MgGraph&lt;/code&gt; fails with insufficient privileges, stop and get consent the proper way. Don't "fix" it by borrowing a more powerful session.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The export (one-time setup, then copy-paste)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Install-Module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Microsoft.Graph.Authentication&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Scope&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CurrentUser&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Install-Module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Microsoft.Graph.DeviceManagement&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Scope&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CurrentUser&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(If your org blocks PSGallery, use your internal module distribution.)&lt;/p&gt;

&lt;p&gt;Each Monday:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$week&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Get-Date&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'yyyy-MM-dd'&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$out&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".\snapshots\&lt;/span&gt;&lt;span class="nv"&gt;$week&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;New-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ItemType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Directory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$out&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Out-Null&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;Connect-MgGraph&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Scopes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'DeviceManagementManagedDevices.Read.All'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'DeviceManagementConfiguration.Read.All'&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Managed devices: a small, useful property set&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-MgDeviceManagementManagedDevice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-All&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Property&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s1"&gt;'deviceName'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'operatingSystem'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'osVersion'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'complianceState'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'lastSyncDateTime'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s1"&gt;'enrolledDateTime'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'userPrincipalName'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'isEncrypted'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'azureADDeviceId'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DeviceName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;OperatingSystem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;OsVersion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ComplianceState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="n"&gt;LastSyncDateTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;EnrolledDateTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;UserPrincipalName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="n"&gt;IsEncrypted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;AzureADDeviceId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;Export-Csv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$out&lt;/span&gt;&lt;span class="s2"&gt;\intune-devices.csv"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-NoTypeInformation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Encoding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;UTF8&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then export your compliance policy list (names, platform, last modified) into the same folder. That second file is what tells you &lt;em&gt;"someone edited a live policy on Thursday"&lt;/em&gt; — the device CSV alone won't.&lt;/p&gt;

&lt;p&gt;Testing on a big tenant? Use &lt;code&gt;-Top 50&lt;/code&gt; instead of &lt;code&gt;-All&lt;/code&gt; for a pilot-sized sample first.&lt;/p&gt;

&lt;p&gt;You end up with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;snapshots/
  2026-09-28/intune-devices.csv
  2026-09-28/compliance-policies.csv
  2026-10-05/intune-devices.csv
  2026-10-05/compliance-policies.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. What to track week over week
&lt;/h2&gt;

&lt;p&gt;Don't build a dashboard. Track five numbers in a ticket or wiki table:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Why it matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Total managed devices&lt;/td&gt;
&lt;td&gt;Sudden drops = enrollment or licensing problem; sudden jumps = someone enrolled personal devices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Noncompliant count (and %)&lt;/td&gt;
&lt;td&gt;The headline trend. Should fall as pilots mature&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stale sync (&lt;code&gt;LastSyncDateTime&lt;/code&gt; &amp;gt; ~7 days)&lt;/td&gt;
&lt;td&gt;Usually powered-off laptops or broken enrollment — &lt;em&gt;not&lt;/em&gt; compliance logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;IsEncrypted&lt;/code&gt; false on Windows rows&lt;/td&gt;
&lt;td&gt;Cross-check vs a BitLocker requirement; treat odd/null values on non-Windows rows carefully&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compliance policy count / last-modified changes&lt;/td&gt;
&lt;td&gt;Unannounced policy edits are the #1 cause of "nothing changed but everything broke"&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A quick comparison of two weeks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$prev&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Import-Csv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;\snapshots\2026-09-28\intune-devices.csv&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$curr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Import-Csv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;\snapshots\2026-10-05\intune-devices.csv&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="s1"&gt;'Last week:'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$prev&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Group-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ComplianceState&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Count&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="s1"&gt;'This week:'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$curr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Group-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ComplianceState&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Count&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Devices that went from compliant to anything else&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$prevState&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@{};&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$prev&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ForEach-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$prevState&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ComplianceState&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$curr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Where-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$prevState&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-eq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'compliant'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ComplianceState&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-ne&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'compliant'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DeviceName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ComplianceState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;LastSyncDateTime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Format-Table&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-AutoSize&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Stale sync this week&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$cutoff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Get-Date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddDays&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;-7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$curr&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Where-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LastSyncDateTime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LastSyncDateTime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-lt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$cutoff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;Measure-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Count&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The "went from compliant to noncompliant" list is the one worth 5 minutes of human attention. Everything else is trend.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. The ritual (≤30 minutes)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Run the device export → save under &lt;code&gt;yyyy-mm-dd/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Run the compliance policy export&lt;/li&gt;
&lt;li&gt;Write down the five numbers next to last week's&lt;/li&gt;
&lt;li&gt;Spot-check 1–2 weird devices on the endpoint itself (&lt;code&gt;dsregcmd /status&lt;/code&gt;, encryption status)&lt;/li&gt;
&lt;li&gt;Open a ticket &lt;strong&gt;only&lt;/strong&gt; if the trend worsens — or if Conditional Access report-only "would block" numbers spike&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it. After a month you have real evidence for "ready to move CA from report-only to enforce?" instead of a gut feeling.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Where NOT to put these CSVs
&lt;/h2&gt;

&lt;p&gt;These files contain device names, user principal names, and tenant-linked IDs. Treat them like internal data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Public Teams/Slack channels with guests, Discord servers, community forums&lt;/li&gt;
&lt;li&gt;❌ Pasted into public AI chat tools or GitHub issues&lt;/li&gt;
&lt;li&gt;❌ Attached to vendor tickets without trimming to the rows they need&lt;/li&gt;
&lt;li&gt;❌ Product reviews or blog screenshots (redact names/UPNs/IDs first)&lt;/li&gt;
&lt;li&gt;✅ An access-controlled share or repo your org approves, with a retention rule (e.g. keep 12 weeks)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you need help from a forum, share the &lt;em&gt;counts&lt;/em&gt; or a redacted row — never the file.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Common snags
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;Likely cause&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Missing module Microsoft.Graph.*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Installed under a different PowerShell edition/host than the one running the script&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Consent prompt loop&lt;/td&gt;
&lt;td&gt;Admin consent required once per tenant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Empty device list&lt;/td&gt;
&lt;td&gt;Wrong tenant — check &lt;code&gt;Get-MgContext&lt;/code&gt; — or scope too weak&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Graph 403&lt;/td&gt;
&lt;td&gt;Role doesn't cover Intune read; assign Intune Reader or an appropriate role&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Execution policy blocks &lt;code&gt;.ps1&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Use process-scoped bypass or signed scripts per IT policy — don't weaken machine policy casually&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Want this ready-made?
&lt;/h2&gt;

&lt;p&gt;This post is the short version. The &lt;strong&gt;Intune &amp;amp; M365 Admin Starter Pack&lt;/strong&gt; ($19 during launch week; normally $29) includes the full inventory-snapshot module plus enrollment hygiene, baseline compliance, M365 admin hygiene, and break/fix cards — and three &lt;strong&gt;read-only&lt;/strong&gt; PowerShell scripts: a local enrollment snapshot (no Graph), a Graph managed-device snapshot, and a compliance policy summary. The scripts only read; they take no device actions and make no policy changes.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://cashflow4375.gumroad.com/l/joonf" rel="noopener noreferrer"&gt;https://cashflow4375.gumroad.com/l/joonf&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Not affiliated with Microsoft. Operational guidance for admins authorized to manage their tenant. Pilot first.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>microsoft</category>
      <category>powershell</category>
      <category>sysadmin</category>
      <category>security</category>
    </item>
  </channel>
</rss>
