{
  "title": "How to Use Azure AD and Conditional Access to Meet NIST SP 800-171 REV.2 / CMMC 2.0 Level 2 - Control - IA.L2-3.5.6: Disable Identifiers After Inactivity",
  "date": "2026-04-07",
  "author": "Lakeridge Technologies",
  "featured_image": "/assets/images/blog/2026/4/how-to-use-azure-ad-and-conditional-access-to-meet-nist-sp-800-171-rev2-cmmc-20-level-2-control-ial2-356-disable-identifiers-after-inactivity.jpg",
  "content": {
    "full_html": "<p>NIST SP 800-171 Rev.2 / CMMC 2.0 Level 2 control IA.L2-3.5.6 requires organizations to disable identifiers after a period of inactivity — a simple-sounding control that, when implemented in Azure Active Directory, significantly reduces the attack surface from forgotten accounts, orphaned credentials, and stale service principals.</p>\n\n<h2>Understanding the control and practical objectives</h2>\n<p>This control's objective is to ensure accounts (human and non-human) that are not in active use are not available to attackers. For small businesses, that typically means automatically identifying users and service accounts with no sign-ins over a configured time window (commonly 60–180 days), notifying affected owners, and disabling or otherwise blocking access after the grace period while maintaining audit evidence of the action.</p>\n\n<h2>Implementation approach in Azure AD and Compliance Framework context</h2>\n<p>To meet Compliance Framework requirements you need a repeatable, auditable process: (1) define inactivity period and exceptions in policy, (2) periodically identify inactive identifiers using Azure AD sign-in data (Microsoft Graph or audit logs), (3) take an enforcement action (disable account or block via Conditional Access group), (4) log and retain evidence, and (5) run periodic reviews. Azure AD capabilities that help: Azure AD access reviews and identity governance (for user and group reviews), Conditional Access (to block access based on group membership), Microsoft Graph (to query sign-in activity) and automation (Azure Automation, Logic Apps, or Functions) to implement scheduled enforcement.</p>\n\n<h3>Using Conditional Access + automation instead of toggling accountEnabled directly</h3>\n<p>A practical, low-risk pattern for small organizations is to create a dedicated \"StaleAccounts\" security group and a Conditional Access policy that blocks any sign-in attempts for members of that group. An automation job (Azure Function/Automation Runbook or Logic App) runs weekly, queries Microsoft Graph for users whose lastSignIn was older than the policy threshold (e.g., 90 days), and adds them to the \"StaleAccounts\" group. Blocking via Conditional Access has advantages: it is immediately reversible (remove from group to restore access), preserves account attributes and mailbox content, and centralizes enforcement without directly editing userEnabled flags which can have downstream effects on services.</p>\n\n<h2>Example automation and a safe PowerShell pattern</h2>\n<p>Below is a concise example workflow you can run as an Azure Automation runbook or Azure Function using a managed identity. The automation queries sign-in activity via Microsoft Graph, emails the account owner (or ticketing system), waits the configured grace period, and then places the account in the \"StaleAccounts\" group to trigger Conditional Access blocking. Adjust the scope and permissions: the automation needs Directory.Read.All and Group.ReadWrite.All (use least privilege and a managed identity).</p>\n\n<pre><code># Pseudocode/PowerShell outline (implement in Azure Runbook/Function with Managed Identity)\nConnect-MgGraph -Identity\n$threshold = (Get-Date).AddDays(-90)\n$users = Invoke-MgGraphRequest -Method GET -Uri \"https://graph.microsoft.com/v1.0/users?$select=id,displayName,mail,signInActivity\"\nforeach ($u in $users) {\n  $last = $u.signInActivity.lastSignInDateTime\n  if (-not $last -or [datetime]$last -lt $threshold) {\n    # create ticket / send notification (store evidence)\n    # if grace period passed, add to StaleAccounts group:\n    Invoke-MgGraphRequest -Method POST -Uri \"https://graph.microsoft.com/v1.0/groups/{StaleGroupId}/members/$ref\" -Body (@{ \"@odata.id\" = \"https://graph.microsoft.com/v1.0/directoryObjects/$($u.id)\" } | ConvertTo-Json)\n  }\n}\n</code></pre>\n\n<h2>Service accounts, exceptions, access reviews and PIM</h2>\n<p>Not all identifiers should be disabled automatically — service principals, application identities, and privileged accounts often require special handling. Tag these with an extension attribute or place them in an \"ExemptFromAutoDisable\" group so the automation skips them. For privileged roles, implement Azure AD Privileged Identity Management (PIM) to reduce standing privileges: administrators should be eligible rather than permanent. Additionally, run Access Reviews (Identity Governance) quarterly to validate exceptions and to remove users from privileged groups; Access Reviews provide built-in attestations and evidence for compliance audits.</p>\n\n<h2>Compliance tips, logging and best practices</h2>\n<p>Best practices to make this control practical and auditable: set and document an inactivity threshold in your formal policy (common values: 60–90 days for interactive users, 180 for vendor accounts), notify users 14–30 days before disablement, maintain an evidence store (tickets/notifications + automation logs) for auditors, test the automation in a pilot group, and keep Azure AD sign-in and audit logs ingested into your SIEM for at least the retention period your framework requires. Note licensing: Conditional Access and Access Reviews typically require Azure AD P1/P2 — inventory your licenses and document compensating controls if you lack them.</p>\n\n<h2>Risk of not implementing IA.L2-3.5.6</h2>\n<p>If you fail to disable inactive identifiers you increase the risk of account takeover (old credentials reused), unauthorized pivoting from orphaned accounts, compliance failures during CMMC/NIST assessments, and exposure of legacy permissions. Attackers frequently target stale accounts and service principals because they tend to be unmonitored and often have elevated privileges. From an audit perspective, lack of an automated, repeatable process and missing evidence are common findings that can delay certification or cause remediation orders.</p>\n\n<p>Summary: implement a documented inactivity policy, use Microsoft Graph to identify stale accounts, enforce blocking through a Conditional Access group (or directly disable where acceptable), handle exceptions for service and privileged accounts, and keep notification and audit evidence for compliance. For most small businesses, combining automation + Conditional Access + periodic Access Reviews delivers an auditable, reversible, and low-risk implementation that satisfies IA.L2-3.5.6 while minimizing business disruption.</p>",
    "plain_text": "NIST SP 800-171 Rev.2 / CMMC 2.0 Level 2 control IA.L2-3.5.6 requires organizations to disable identifiers after a period of inactivity — a simple-sounding control that, when implemented in Azure Active Directory, significantly reduces the attack surface from forgotten accounts, orphaned credentials, and stale service principals.\n\nUnderstanding the control and practical objectives\nThis control's objective is to ensure accounts (human and non-human) that are not in active use are not available to attackers. For small businesses, that typically means automatically identifying users and service accounts with no sign-ins over a configured time window (commonly 60–180 days), notifying affected owners, and disabling or otherwise blocking access after the grace period while maintaining audit evidence of the action.\n\nImplementation approach in Azure AD and Compliance Framework context\nTo meet Compliance Framework requirements you need a repeatable, auditable process: (1) define inactivity period and exceptions in policy, (2) periodically identify inactive identifiers using Azure AD sign-in data (Microsoft Graph or audit logs), (3) take an enforcement action (disable account or block via Conditional Access group), (4) log and retain evidence, and (5) run periodic reviews. Azure AD capabilities that help: Azure AD access reviews and identity governance (for user and group reviews), Conditional Access (to block access based on group membership), Microsoft Graph (to query sign-in activity) and automation (Azure Automation, Logic Apps, or Functions) to implement scheduled enforcement.\n\nUsing Conditional Access + automation instead of toggling accountEnabled directly\nA practical, low-risk pattern for small organizations is to create a dedicated \"StaleAccounts\" security group and a Conditional Access policy that blocks any sign-in attempts for members of that group. An automation job (Azure Function/Automation Runbook or Logic App) runs weekly, queries Microsoft Graph for users whose lastSignIn was older than the policy threshold (e.g., 90 days), and adds them to the \"StaleAccounts\" group. Blocking via Conditional Access has advantages: it is immediately reversible (remove from group to restore access), preserves account attributes and mailbox content, and centralizes enforcement without directly editing userEnabled flags which can have downstream effects on services.\n\nExample automation and a safe PowerShell pattern\nBelow is a concise example workflow you can run as an Azure Automation runbook or Azure Function using a managed identity. The automation queries sign-in activity via Microsoft Graph, emails the account owner (or ticketing system), waits the configured grace period, and then places the account in the \"StaleAccounts\" group to trigger Conditional Access blocking. Adjust the scope and permissions: the automation needs Directory.Read.All and Group.ReadWrite.All (use least privilege and a managed identity).\n\n# Pseudocode/PowerShell outline (implement in Azure Runbook/Function with Managed Identity)\nConnect-MgGraph -Identity\n$threshold = (Get-Date).AddDays(-90)\n$users = Invoke-MgGraphRequest -Method GET -Uri \"https://graph.microsoft.com/v1.0/users?$select=id,displayName,mail,signInActivity\"\nforeach ($u in $users) {\n  $last = $u.signInActivity.lastSignInDateTime\n  if (-not $last -or [datetime]$last -lt $threshold) {\n    # create ticket / send notification (store evidence)\n    # if grace period passed, add to StaleAccounts group:\n    Invoke-MgGraphRequest -Method POST -Uri \"https://graph.microsoft.com/v1.0/groups/{StaleGroupId}/members/$ref\" -Body (@{ \"@odata.id\" = \"https://graph.microsoft.com/v1.0/directoryObjects/$($u.id)\" } | ConvertTo-Json)\n  }\n}\n\n\nService accounts, exceptions, access reviews and PIM\nNot all identifiers should be disabled automatically — service principals, application identities, and privileged accounts often require special handling. Tag these with an extension attribute or place them in an \"ExemptFromAutoDisable\" group so the automation skips them. For privileged roles, implement Azure AD Privileged Identity Management (PIM) to reduce standing privileges: administrators should be eligible rather than permanent. Additionally, run Access Reviews (Identity Governance) quarterly to validate exceptions and to remove users from privileged groups; Access Reviews provide built-in attestations and evidence for compliance audits.\n\nCompliance tips, logging and best practices\nBest practices to make this control practical and auditable: set and document an inactivity threshold in your formal policy (common values: 60–90 days for interactive users, 180 for vendor accounts), notify users 14–30 days before disablement, maintain an evidence store (tickets/notifications + automation logs) for auditors, test the automation in a pilot group, and keep Azure AD sign-in and audit logs ingested into your SIEM for at least the retention period your framework requires. Note licensing: Conditional Access and Access Reviews typically require Azure AD P1/P2 — inventory your licenses and document compensating controls if you lack them.\n\nRisk of not implementing IA.L2-3.5.6\nIf you fail to disable inactive identifiers you increase the risk of account takeover (old credentials reused), unauthorized pivoting from orphaned accounts, compliance failures during CMMC/NIST assessments, and exposure of legacy permissions. Attackers frequently target stale accounts and service principals because they tend to be unmonitored and often have elevated privileges. From an audit perspective, lack of an automated, repeatable process and missing evidence are common findings that can delay certification or cause remediation orders.\n\nSummary: implement a documented inactivity policy, use Microsoft Graph to identify stale accounts, enforce blocking through a Conditional Access group (or directly disable where acceptable), handle exceptions for service and privileged accounts, and keep notification and audit evidence for compliance. For most small businesses, combining automation + Conditional Access + periodic Access Reviews delivers an auditable, reversible, and low-risk implementation that satisfies IA.L2-3.5.6 while minimizing business disruption."
  },
  "metadata": {
    "description": "Step-by-step guidance to disable inactive Azure AD accounts using automation, Conditional Access, Access Reviews and logging to satisfy NIST SP 800-171 Rev.2 / CMMC 2.0 IA.L2-3.5.6.",
    "permalink": "/how-to-use-azure-ad-and-conditional-access-to-meet-nist-sp-800-171-rev2-cmmc-20-level-2-control-ial2-356-disable-identifiers-after-inactivity.json",
    "categories": [],
    "tags": []
  }
}