Introduction to Just-In-Time Administration on Windows Server 2022

Just-In-Time (JIT) administration is a security model that eliminates persistent privileged access. Instead of assigning administrators to privileged groups permanently, JIT grants elevated access only for a specific task window — typically minutes or hours — after which the privilege is automatically revoked. This dramatically reduces the attack surface against credential theft, pass-the-hash, and lateral movement attacks that rely on abusing long-lived admin accounts.

Windows Server 2022 supports JIT administration through several mechanisms: the native Privileged Access Management (PAM) feature in Active Directory, Microsoft Identity Manager (MIM) PAM, and Azure Privileged Identity Management (Azure PIM) for hybrid environments. Each tier serves different organizational maturity levels, from pure on-premises AD shops to hybrid Azure deployments. This guide covers all three approaches with practical PowerShell implementation.

Understanding the Threat Model JIT Solves

In a traditional Active Directory environment, a domain admin account is a permanent member of Domain Admins. If that account is compromised — even briefly — an attacker has indefinite access to every system in the domain. Pass-the-hash attacks, Kerberoasting, and Golden Ticket attacks all rely on the assumption that privileged group membership persists between logon sessions.

JIT eliminates this persistence. An admin requests elevated access, performs their work within the approved time window, and the group membership expires automatically. An attacker who steals a ticket or hash after expiry gains nothing because the account no longer has the required group membership to perform privileged operations.

Microsoft Tier 0 assets — domain controllers, AD itself, PKI infrastructure — are the highest-value targets. JIT should be enforced most strictly at Tier 0, where even 15-minute access windows are appropriate for sensitive operations like schema modifications or GPO edits on domain controllers.

Enabling the Privileged Access Management Feature in Active Directory

Before configuring shadow groups and time-limited membership, you must enable the Privileged Access Management (PAM) optional feature on your Active Directory forest. This feature is available starting with Windows Server 2016 forest functional level.

First, verify your forest functional level meets the requirement:

Get-ADForest | Select-Object Name, ForestMode

The ForestMode must be Windows2016Forest or higher. If it is not, raise it:

Set-ADForestMode -Identity "corp.example.com" -ForestMode Windows2016Forest -Confirm:$false

Now enable the PAM optional feature. This is a one-way, irreversible change for the forest:

Enable-ADOptionalFeature -Identity "Privileged Access Management Feature" `
    -Scope ForestOrConfigurationSet `
    -Target "corp.example.com" `
    -Confirm:$false

Verify the feature is active:

Get-ADOptionalFeature -Filter {Name -eq "Privileged Access Management Feature"} | 
    Select-Object Name, EnabledScopes

Once enabled, AD will honour the Time-To-Live (TTL) attribute on group memberships. This is the core mechanism that makes JIT possible natively in AD.

Shadow Security Groups and Time-Limited Group Membership

Shadow security groups are privileged AD groups used exclusively for JIT access. Rather than adding users directly to Domain Admins or Server Operators, you create shadow groups with equivalent or scoped permissions, then grant time-limited membership to those shadow groups. The shadow group itself may be a permanent (but empty) member of the target privileged group, or it may be granted rights directly.

Create a shadow group for Domain Controller administration:

New-ADGroup -Name "ShadowGroup-DCAdmins" `
    -GroupScope Global `
    -GroupCategory Security `
    -Path "OU=JIT-Groups,DC=corp,DC=example,DC=com" `
    -Description "JIT shadow group for DC administration - time-limited membership"

Grant the shadow group membership in Domain Admins (the shadow group itself is the permanent member — users are only temporarily added to the shadow group):

Add-ADGroupMember -Identity "Domain Admins" -Members "ShadowGroup-DCAdmins"

Now use the TTL-aware Add-ADGroupMember to grant a user temporary membership in the shadow group. The MemberTimeToLive parameter requires the PAM feature to be enabled:

# Grant jdoe 2 hours of membership in the shadow group
Add-ADGroupMember -Identity "ShadowGroup-DCAdmins" `
    -Members "jdoe" `
    -MemberTimeToLive (New-TimeSpan -Hours 2)

To verify that the TTL has been set on the membership:

Get-ADGroup -Identity "ShadowGroup-DCAdmins" -Properties member | 
    Select-Object -ExpandProperty member

AD will automatically remove the user from the group when the TTL expires. No scheduled task or cleanup job is required — this is handled natively by the AD replication engine.

Building a JIT Workflow with PowerShell (Without MIM)

For organizations that want JIT without deploying the full MIM PAM solution, you can build a lightweight JIT workflow using PowerShell, a request log, and approval automation. The following pattern implements a simple request-and-approve model.

Create a function that admins call to request elevated access:

function Request-JITAccess {
    param(
        [Parameter(Mandatory=$true)]
        [string]$Requestor,
        [Parameter(Mandatory=$true)]
        [string]$ShadowGroup,
        [Parameter(Mandatory=$true)]
        [int]$DurationMinutes,
        [Parameter(Mandatory=$true)]
        [string]$Justification
    )

    # Log the request to a central CSV
    $logPath = "\dc01JITRequestsrequests.csv"
    $request = [PSCustomObject]@{
        RequestID   = [System.Guid]::NewGuid().ToString()
        Requestor   = $Requestor
        ShadowGroup = $ShadowGroup
        Duration    = $DurationMinutes
        Justification = $Justification
        RequestTime = (Get-Date -Format "yyyy-MM-dd HH:mm:ss")
        Status      = "Pending"
        Approver    = ""
        GrantTime   = ""
    }
    $request | Export-Csv -Path $logPath -Append -NoTypeInformation

    Write-Host "JIT request $($request.RequestID) submitted. Awaiting approval."
    return $request.RequestID
}

Create the approval and grant function, to be run by a senior admin:

function Approve-JITAccess {
    param(
        [Parameter(Mandatory=$true)]
        [string]$RequestID,
        [Parameter(Mandatory=$true)]
        [string]$Approver
    )

    $logPath = "\dc01JITRequestsrequests.csv"
    $requests = Import-Csv -Path $logPath
    $req = $requests | Where-Object { $_.RequestID -eq $RequestID -and $_.Status -eq "Pending" }

    if (-not $req) {
        Write-Error "Request not found or already processed."
        return
    }

    # Grant time-limited group membership
    Add-ADGroupMember -Identity $req.ShadowGroup `
        -Members $req.Requestor `
        -MemberTimeToLive (New-TimeSpan -Minutes [int]$req.Duration)

    # Update the log
    $req.Status   = "Approved"
    $req.Approver = $Approver
    $req.GrantTime = (Get-Date -Format "yyyy-MM-dd HH:mm:ss")
    $requests | Export-Csv -Path $logPath -NoTypeInformation -Force

    Write-Host "JIT access granted to $($req.Requestor) for $($req.Duration) minutes."
}

Microsoft Identity Manager PAM Solution

Microsoft Identity Manager (MIM) 2016 SP2 provides an enterprise-grade PAM solution with a full request/approval portal, REST API, and audit trail. MIM PAM uses a separate, hardened “bastion forest” (PRIV forest) that is trusted by the production forest (CORP forest). Privileged users have shadow accounts in the PRIV forest and request access from there, keeping the production forest clean of any privileged activity.

The MIM PAM architecture consists of:

PRIV Forest — The hardened bastion forest. Contains shadow accounts and shadow groups that mirror the privileged groups in CORP. This forest should be managed with strict security controls: no internet access, dedicated admin workstations only, and full endpoint detection coverage.

CORP Forest — The production environment. The PAM feature is enabled here, and shadow groups in PRIV are granted time-limited membership in CORP privileged groups via the cross-forest trust.

Install MIM PAM components on the PRIV domain controller. First ensure the PAM feature is enabled on CORP and a two-way trust (with SID history filtering disabled for PAM) exists between PRIV and CORP:

# Run on CORP DC — enable selective authentication on the trust
netdom trust CORP.EXAMPLE.COM /domain:PRIV.EXAMPLE.COM /EnableSIDHistory:yes
netdom trust CORP.EXAMPLE.COM /domain:PRIV.EXAMPLE.COM /quarantine:no

After MIM is installed, you define PAM roles using the MIM portal or PowerShell via the MIM PAM PowerShell module. A role defines which CORP group a PRIV shadow group can activate, the maximum TTL, and optional MFA/approval requirements:

# Import MIM PAM module (run on MIM service server)
Import-Module MIMPAM

# Connect to MIM service
$cred = Get-Credential
$session = New-PAMSession -Credentials $cred

# Create a PAM role
$corpGroup   = Get-PAMGroup -Session $session -Filter "sAMAccountName=ShadowGroup-DCAdmins" -SourceDomain CORP
$privGroup   = Get-ADGroup -Identity "priv.ShadowGroup-DCAdmins"
New-PAMRole -Session $session `
    -DisplayName "DC Administration" `
    -Groups $corpGroup `
    -TTL 120 `
    -AvailableFrom "08:00" `
    -AvailableTo "20:00" `
    -Approvers "privadmins"

Users with PRIV shadow accounts request activation via the MIM PAM REST API or the MIM portal. Once approved, the shadow group in PRIV receives time-limited membership in the CORP shadow group, and the Kerberos ticket issued contains the appropriate SID for CORP resource access.

MIM PAM REST API for Programmatic Access Requests

The MIM PAM REST API allows custom tooling, ticketing system integration, and automated workflows. The API endpoint is hosted on the MIM Service server:

# Request elevation via MIM PAM REST API using PowerShell
$mimServiceUrl = "https://mimsvc.priv.example.com/api/pamrequests"
$headers = @{
    "Authorization" = "Negotiate"
    "Content-Type"  = "application/json"
}

$body = @{
    RoleName      = "DC Administration"
    Justification = "Emergency GPO change for security policy update"
    TTL           = 60
} | ConvertTo-Json

$response = Invoke-RestMethod -Uri $mimServiceUrl `
    -Method Post `
    -Headers $headers `
    -Body $body `
    -UseDefaultCredentials

Write-Host "PAM Request ID: $($response.Id)"
Write-Host "Status: $($response.RequestStatus)"

Azure PIM for Hybrid JIT Scenarios

For organizations with Azure AD Connect syncing on-premises AD to Azure AD (or Entra ID), Azure Privileged Identity Management provides a cloud-managed JIT experience that covers both Azure RBAC roles and on-premises AD groups (when using PIM for Groups). Azure PIM is available with Entra ID P2 licensing.

Configure PIM for an on-premises synchronized group using the Azure PowerShell module:

# Requires Az.Resources and Microsoft.Graph modules
Connect-MgGraph -Scopes "PrivilegedAccess.ReadWrite.AzureADGroup"

# Find the group object ID in Entra ID
$group = Get-MgGroup -Filter "DisplayName eq 'ShadowGroup-DCAdmins'"

# Enable PIM management for the group
New-MgIdentityGovernancePrivilegedAccessGroupEligibilityScheduleRequest -Body @{
    accessId     = "member"
    principalId  = "user-object-id-here"
    groupId      = $group.Id
    action       = "adminAssign"
    justification = "Eligible for DC Admin JIT"
    scheduleInfo = @{
        startDateTime = (Get-Date -Format "o")
        expiration    = @{
            type        = "afterDuration"
            duration    = "P365D"
        }
    }
}

Once eligible, users activate their membership through the Entra ID portal or via the Graph API. The activation is time-limited (configurable per role, typically 1–8 hours) and can require MFA, approval, and justification entry.

Monitoring JIT Activations in the AD Audit Log

All JIT group membership changes generate Windows Security events. Event ID 4728 logs a user being added to a global security group. When the PAM feature is enabled, the event includes the TTL value in the Additional Information field, making it straightforward to distinguish JIT membership grants from permanent ones.

Query the security event log on domain controllers for recent JIT grants:

# Search for group membership additions with TTL (JIT activations)
Get-WinEvent -ComputerName DC01 -LogName Security -FilterHashtable @{
    Id = 4728
} | Where-Object {
    $_.Message -match "TTL" -or $_.Message -match "ShadowGroup"
} | Select-Object TimeCreated, Message | Format-List

For broader auditing across all DCs, use the following pattern with a domain-aware sweep:

$dcs = (Get-ADDomainController -Filter *).HostName
foreach ($dc in $dcs) {
    Write-Host "=== $dc ==="
    Get-WinEvent -ComputerName $dc -LogName Security `
        -FilterHashtable @{ Id = @(4728, 4729); StartTime = (Get-Date).AddDays(-1) } |
        Select-Object TimeCreated, @{n="DC";e={$dc}}, Message |
        Where-Object { $_.Message -match "ShadowGroup" }
}

When a JIT membership expires, AD generates Event ID 4729 (member removed from security group) with a source of the AD DC performing the TTL cleanup. These events should be forwarded to your SIEM and treated as normal operational activity — alerting only on unexpected removals outside business hours or on groups not in your JIT inventory.

JIT Access for Tier 0 Assets

Tier 0 in the Microsoft Enterprise Access Model includes domain controllers, AD itself, AD CS (Certificate Services), ADFS, and Azure AD Connect. Access to Tier 0 systems should always be mediated through JIT. Permanent membership in Domain Admins or Enterprise Admins should be limited to break-glass emergency accounts stored in sealed safes with dual control.

Enforce JIT at Tier 0 with a GPO that denies interactive logon to the domain admin group except from Privileged Access Workstations (PAWs):

# Verify no non-service accounts have permanent Domain Admins membership
$domainAdmins = Get-ADGroupMember -Identity "Domain Admins" -Recursive
foreach ($member in $domainAdmins) {
    $user = Get-ADUser -Identity $member.SamAccountName `
        -Properties Description, LastLogonDate, PasswordNeverExpires
    if ($user.PasswordNeverExpires -or $user.Description -notmatch "break.glass") {
        Write-Warning "Non-compliant permanent member: $($user.SamAccountName)"
    }
}

Regularly review and enforce that the Domain Admins group contains only the break-glass account and the shadow group for JIT grants. Automate this check as a scheduled script that alerts if unexpected permanent members are found, to catch any manual additions that bypass the JIT workflow.

Summary

Just-In-Time administration on Windows Server 2022 fundamentally changes the privileged access model from persistent trust to ephemeral trust. By enabling the AD PAM optional feature, using shadow security groups with TTL-based membership, and integrating approval workflows — whether through PowerShell, MIM, or Azure PIM — you eliminate the most common attack vector against Active Directory: the persistent privileged account. Combined with robust audit logging and Tier 0 access controls, JIT administration is the single most impactful security improvement available to Windows Server environments today.