Introduction

Recently, I encountered an issue where we had a customer that needed to be migrated to a larger environment but was not ready to remove the local administrator rights from their end users. The new environment decided to leave the migrated users admin privileges during the initial enrollment and planned to remove them later once the end users where able to perform their tasks without it.

All users were enrolled through Autopilot, which means we utilized the setting under the Autopilot profile to make the enrolled user a local admin on their device. However, a problem arises if we want to revoke this right after enrollment. Currently, there is no straightforward way to remove the local admin privileges, and the only solution is to edit the Autopilot profile to make the end user a ‘standard user’ and afterwards reset the computer.

Because I was not a fan of that solution, I took the initiative to develop a custom script that efficiently manages this issue. The script will handle both the adding and removal of the user who enrolled the device via Autopilot to the Local Administrators group.

Please be aware that this solution is specifically designed for scenarios where devices are Azure Active Directory Joined (AADJ) using Windows Autopilot. It has not been tested for hybrid deployments yet, so further testing is required to ensure compatibility in such setups. Additionally, for Windows 365 PCs, this script is not supported, as the enrolled user is identified as 'fooUser@yourdomain.com’.

All following scripts will be available on my github repository.

To facilitate script deployment, I have chosen to utilize a win32 application due to its straightforward installation and uninstallation process. Although proactive remediation and other options exist, I find this method to be the most practical and efficient for my needs. For this solution the following scripts will be needed:

Add-LocalAdmin-AAD

This script will use the info gathered on registry path:

HKLM:/SYSTEM/CurrentControlSet/Control/CloudDomainJoin/JoinInfo

Sea

Out of this registry we will be able to get the email address of the user who enrolled the device with Autopilot.
Once we have that email address we can add it to the Administrators group on the local machine.

Above this, we will create following registry path:

HKLM:\Software\IntuneManaged\LocalAdmins

This way, we can follow up if the user is already added to the local administrators or not.

#restart script in 64 bit environment
If (!([Environment]::Is64BitProcess)) {
    if ([Environment]::Is64BitOperatingSystem) {
        Write-Output "Running 32 bit Powershell on 64 bit OS, restarting as 64 bit process..."
        $arguments = "-NoProfile -ExecutionPolicy ByPass -WindowStyle Hidden -File `"" + $myinvocation.mycommand.definition + "`""
        $path = (Join-Path $Env:SystemRoot -ChildPath "\sysnative\WindowsPowerShell\v1.0\powershell.exe")
        Start-Process $path -ArgumentList $arguments -wait
        Write-Output "finished x64 version of PS"
        Exit
    }
    else {
        Write-Output "Running 32 bit Powershell on 32 bit OS"
    }
}
$ErrorActionPreference = "Stop"

function LogMessage([string]$message) {
    $message = "$([DateTime]::Now) - $message"
    Write-Host $message
    $message | Out-File -FilePath $env:TEMP\LocalAdmin.log
}

#Script to make the user which enrolled the device to AAD a local admin
try {

    #Get local Administrators group
    $LocalAdminGroup = Get-LocalGroup -SID "S-1-5-32-544"
    $Localadmingroupname = $LocalAdminGroup.name

    #Get the UPN of the user who enrolled the computer to AAD
    $AADInfoPath = "HKLM:/SYSTEM/CurrentControlSet/Control/CloudDomainJoin/JoinInfo"
    $AADInfo = Get-Item $AADInfoPath
    $guid = ($AADInfo | Get-ChildItem | Where-Object { $_.Property -contains "UserEmail" }).PSChildName
    $UPN = (Get-Item "$AADInfoPath/$guid").GetValue("UserEmail")

    if (-not $UPN) {
        throw "Failed to find enrolled User email in registry."
    }

    #localadmin path for detection
    $localAdminsPath = "HKLM:\Software\IntuneManaged\LocalAdmins"
    $LocalAdminExists = (Get-ItemProperty $localAdminsPath -EA 0)."$UPN"

    if (!($LocalAdminExists -eq "1")) {
        Add-LocalGroupMember -Group $Localadmingroupname -Member "Azuread\$UPN" -EA 0
        LogMessage "Added AzureAD\$UPN as local administrator."
        #add registry key for detection
        & REG add "HKLM\Software\IntuneManaged\LocalAdmins" /v "$UPN" /t REG_DWORD /d 1 /f /reg:64 | Out-Null
    }
    else {
        LogMessage "AzureAD\$UPN is already a local administrator."
    }
}
catch {
    $errorMessage = $_.Exception.Message
    LogMessage "Error - $errorMessage"
}

Remove-LocalAdmin-AAD

This script will remove the enrolled user from the Administrators group. It will again collect the enrolled user on the registry path and remove it from the Administrators group.

#restart script in 64 bit environment
If (!([Environment]::Is64BitProcess)) {
    if ([Environment]::Is64BitOperatingSystem) {
        Write-Output "Running 32 bit Powershell on 64 bit OS, restarting as 64 bit process..."
        $arguments = "-NoProfile -ExecutionPolicy ByPass -WindowStyle Hidden -File `"" + $myinvocation.mycommand.definition + "`""
        $path = (Join-Path $Env:SystemRoot -ChildPath "\sysnative\WindowsPowerShell\v1.0\powershell.exe")
        Start-Process $path -ArgumentList $arguments -wait
        Write-Output "finished x64 version of PS"
        Exit
    }
    else {
        Write-Output "Running 32 bit Powershell on 32 bit OS"
    }
}

function LogMessage([string]$message){
    $message = "$([DateTime]::Now) - $message"
    Write-Host $message
    $message | Out-File -FilePath $env:TEMP\LocalAdmin.log
}

#Script to remove the user which enrolled the device to AAD from local admin
try {
    #Get the local administratotrs group
    $LocalAdminGroup = Get-LocalGroup -SID "S-1-5-32-544"
    $Localadmingroupname = $LocalAdminGroup.name

    #Get the UPN of the user that enrolled the computer to AAD
    $AADInfoPath = "HKLM:/SYSTEM/CurrentControlSet/Control/CloudDomainJoin/JoinInfo"
    $AADInfo = Get-Item $AADInfoPath
    $guid = ($AADInfo | Get-ChildItem | Where-Object { $_.Property -contains "UserEmail" }).PSChildName
    $UPN = (Get-Item "$AADInfoPath/$guid").GetValue("UserEmail")

    if (-not $UPN) {
        throw "Failed to find enrolled User email in registry."
    }

    # Detect if local admin needs to be removed
    $localAdminsPath = "HKLM:\Software\IntuneManaged\LocalAdmins"
    $LocalAdminExists = (Get-ItemProperty $localAdminsPath -EA 0)."$UPN"

    if ($LocalAdminExists -eq "1") {
        LogMessage "Removing AzureAD\$UPN as a local administrator."
        Remove-LocalGroupMember -Group $Localadmingroupname -member "Azuread\$UPN" -EA 0
        LogMessage "Removed AzureAD\$UPN as a local administrator."
        Remove-ItemProperty -Path $localAdminsPath -Name $UPN -ErrorAction Stop
    }
    else {
        LogMessage "AzureAD\$UPN is already removed as a local administrator."
    }
}
catch {
    $errorMessage = $_.Exception.Message
    LogMessage "Error - $errorMessage"
}

Detect-LocalAdmin

This detection script will be used to validate that the enrolled user has been added to the Local administrators group by using our registry location.

#Get the UPN of the user that enrolled the computer to AAD
$AADInfoPath = "HKLM:/SYSTEM/CurrentControlSet/Control/CloudDomainJoin/JoinInfo"
$AADInfo = Get-Item $AADInfoPath
$guid = ($AADInfo | Get-ChildItem | Where-Object { $_.Property -contains "UserEmail" }).PSChildName
$UPN = (Get-Item "$AADInfoPath/$guid").GetValue("UserEmail")

$localAdminsPath = "HKLM:\Software\IntuneManaged\LocalAdmins"
$LocalAdminExists = (Get-ItemProperty $localAdminsPath)."$UPN"

if($LocalAdminExists -eq "1"){
    Write-Host "Local Admin already added."
}else{
    Exit 1
}

Deploy as Win32 Application

You can find an already made .intunewin file in my github repository. If you need to make some changes then you can of course repackage it yourself. Once this is done deploy the script via Intune as a win32 application in system context.

Install command:

powershell.exe -ExecutionPolicy Bypass -File .\Add-LocalAdmin-AAD.ps1

Uninstall command:

powershell.exe -ExecutionPolicy Bypass -File .\Remove-LocalAdmin-AAD.ps1

For the detection method add the custom script above. (don’t forget to run it in 64 bit). When this is done, you can start assigning this app to the device groups you want to manage. This app can replace the Autopilot profile setting, if desired.

Let me know if everything works as expected in the comment and happy testing!