WPNinjas HeaderWPNinjas Header

Automatic environment cleanup with Intune Connector for AD Extender

In today’s environments one of the most important point is to keep them clean and tidy. Otherwise deployment statistics and security related reports are not correct. Therefore it’s important to continuously clean up your environment.

In this blog I will cover solution on how to automatically cleanup when you are using Autopilot in combination with Azure AD Hybrid Join (Intune Connector for Active Directory Extender). The cleanup is done for the following systems:

  • Active Directory: In case you build your device name by using for example the serial number, done by a custom script after the enrollment by Intune. Then you need a mechanism to delete the old object if the device was already enrolled. Otherwise the device cannot be renamed if a computer object already exists for the same name.
  • Intune: On each enrollment Intune creates a new object. Therefore, we should check if there are other devices with the same serial number and remove them.
  • ConfigMgr: If you are using Co-Management also ConfigMgr could have stale devices which can be removed. Part of next blog.

Important: All the above depends on unique device serial numbers. If your hardware vendor doesn’t provide them correctly, then you need another mechanism.

Important 2: In normal case I try to disable objects only, but this is in the above cases not possible. If the AD computer account for example is only disabled, then I can still not rename the reenrolled device. So, the scripts are deleting, test them well before enabling them.

Example 1 – Add AD computer object to AD group

Can be found in the initial blog about the Extender.

Example 2 – Remove old instances of device in Intune

If you would like to remove automatically old device entries in Intune during an Autopilot Enrollment. You can easily archive this by installing the Intune Connector for Active Directory Extender as explained in the Installation and Configuration section. After that we can start customizing the ODJ-Extender.ps1 script.

Nearly at the bottom you will find the Empty Main script section. At this position the script has already set the variable $DeviceName and $DeviceId which corresponds to the Intune device id.

#region Main Script
########################################################
 
#endregion

First of all, we need to initialize some variables which we can then use in the script. Important is a service account with Intune permissions to delete devices. The password can be saved as SecureString. You can get the string by executing the following command, which should be executed under the same account as the service is running (System). Therefore, you have to use “psexec -i -s powershell.exe” to generate it:

$sec = Read-Host -AsSecureString | ConvertFrom-SecureString

The variables in the script should then look like in this example:

#region Remove old Computer Account from AD based on Computername Pattern
$upn = "intune.svc@kurcontoso.ch"
$passWD = "01000000d08c9ddf00000000020000000…aad871d4baa91387bdb139503eec1c961c47d1c"

$maxDevicesToDelete = 3 # If more devices are returned, the script will not delete them.
$MaxRetries = 25
$RetryDelay = 5 # Seconds

Then we must load the Intune PowerShell Module and Connect to it:

try {
    #import the Intune Powershell module
    Write-Log "import Microsoft.Graph.Intune PSModule"
    Import-Module Microsoft.Graph.Intune -Force -ErrorAction Stop | Out-Null
} catch {
    Write-Log "Coul not load Microsoft.Graph.Intune module. Trying to install and then import it."
    #Install Intune PowerShell module and then import it
    Install-Module Microsoft.Graph.Intune -Force
    Import-Module Microsoft.Graph.Intune -Force -ErrorAction Stop | Out-Null
    if((Get-Module -Name Microsoft.Graph.Intune) -eq $null){
        Write-Log "Could not import Microsoft.Graph.Intnue module. Data collection will be aborted." -Type Error
        throw "Could not import Microsoft.Graph.Intnue module."
    }
}

try {
    #create the connection credentials
    Write-Log "Converting Password to securestring"
    $secPwd = ConvertTo-SecureString $passWD
    $credentials = New-Object System.Management.Automation.PSCredential($upn,$secPwd)
    Write-Log "Connecting to intune"
    #connect to Intune without Outputing to the console.
    Connect-MSGraph -PSCredential $credentials
} catch {
    Write-Log "Could not connet to Intune." -Type Error -Exception $_.Exception
    throw "Could not connect to Intune"
} 

Next Task is to get the serial number of the device with the $DeviceId. This can be accomplished by the following lines of code. Important is, that it sometimes takes a few seconds until the device information is available, because of that I added a retry mechanism:

try{
    Write-Log "Getting serialnumber for device id '$DeviceId'"
    $i = 0
    while(($intuneDevice.serialNumber.Length -lt 1) -and ($i -lt $MaxRetries)){
        $i++
        Write-Log "Start searching Intune by DeviceId (Try: '$i')"
        Start-Sleep -Seconds $RetryDelay
        $intuneDevice = Get-IntuneManagedDevice -managedDeviceId $DeviceId
        $DeviceSerial = $intuneDevice.serialNumber
    }
    
} catch {
    if($_.TargetObject.Response.HttpStatusCode -eq 404){
        Write-Log "Device not found in Intune continuing with the script"
    }else{
        Write-Log "Could not get new device name" -Type Error -Exception $_.Exception
    }
} 

Then we can already start searching for other devices with the same serial number and remove the one which are not our actual device with id equals $DeviceId:

if($null -ne $DeviceSerial)
{
   try{
        Write-Log "Getting all devices with same serialnumber '$DeviceSerial' like device id '$DeviceId'"
        
        $intuneOldDevices = Get-IntuneManagedDevice -Filter "serialNumber eq '$DeviceSerial'"
        if($intuneOldDevices.Count -lt ($maxDevicesToDelete + 1)){ # Add one to the Max because one device will be excluded 
            foreach($intuneOldDevice in $intuneOldDevices){
                if($intuneOldDevice.id -eq $DeviceId){
                    Write-Log "Identical device id '$DeviceId', do nothing with this object."
                } else {
                    Write-Log "Found device id '$($intuneOldDevice.id)', remove object."
                    Remove-IntuneManagedDevice -managedDeviceId $intuneOldDevice.id
                }
            }
        }
    } catch{
        if($_.TargetObject.Response.HttpStatusCode -eq 404){
            Write-Log "Device not found in Intune continuing with the script"
        }else{
            Write-Log "Could not get new device name" -Type Error -Exception $_.Exception
        }
    }
}else{
    Write-Log "Target devicename not set. Skipping device removal."
} 

Now we have already all code snippets together. To simplify it for you I have uploaded the complete script to Github.

Example 3 – Remove stale ad computer objects

This example is only working, if you rename your devices after enrollment by using some fix variables like serial number. The first parts we require are identical to example 2. We need to define some variables, load the Intune PowerShell Module and retrieve the serial number from Intune. Then we have to build the proposed future hostname. We can do this at this point because the renaming will happen at a later stage with the exact same algorithm:

#Building Devicename to search for it in AD
Write-Log "Building Target Devicename"
$TargetComputername = "KUR-$DeviceSerial"
Write-Log "Target ComputerName: '$TargetComputername'"
  
if ($TargetComputername.Length -ge 15) {
    Write-Log "Target ComputerName is longer ($($TargetComputername.Length)) than the allowed length of 15. It will be shorted."
    $TargetComputername = $TargetComputername.substring(0, 15)
    Write-Log "New Target ComputerName: '$TargetComputername' "
}

Now we can check if there is already such a computer account available in Active Directory. If yes the renaming process would fail and therefore we should immediately delete the computer account:

if(($intuneDevice) -and ($TargetComputername.Length -gt 4))
{
    Write-Log "Delete device from AD with devicename '$TargetComputername'"
    try{
        $devicesToDelete = @(Get-ADComputer -Identity $TargetComputername)
        if($devicesToDelete.Count -le $maxDevicesToDelete){
            Write-Log "Found '$($devicesToDelete.Count)' devices. This is below the configured value of '$maxDevicesToDelete'. Therefore deleting those devices."
            foreach($deviceToDelete in $devicesToDelete){
                Write-Log "Removing '$($deviceToDelete.DistinguishedName)'"
                try{
                    Remove-ADObject -Identity $deviceToDelete -Recursive -Confirm:$FALSE
                }catch{
                    Write-Log "Could not remove device" -Type Error -Exception $_.Exception
                }
            }
        }else{
            Write-Log "Found '$($devicesToDelete.Count)' devices. This is above the configured value of '$maxDevicesToDelete'. Therefore skipping those devices."
        }
    }catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] {
        Write-Log "AD object for '$TargetComputername' not found, skipping device removal"
    }catch{
        Write-Log "Error on deleting device." -Type Error -Exception $_.Exception
    }
}else{
    Write-Log "Target devicename not set. Skipping device removal."
} 

The complete script to automatically remove computer accounts can also be found on Github. If you combine it with the one from example 2 just remove the duplicated parts.

Summary

The above scripts help you to have a clean environment which also improves your deployment statistics. If you have any improvements, just commit them on Github.

Follow me

7 Comments

Rizwan Ayub · October 8, 2019 at 15:46

Hi Thomas

After renaming the devices,
Associated Intune Device Name = Changes to Correct
Active Directory = Changes to Correct Name
Hybrid Azure AD joined = Changes to Correct

Azure AD joined = Doesn’t Change – Stays the Same even after 24hours

COuld you please help with the resolve

    Thomas Kurth · October 9, 2019 at 14:08

    Hello Rizwan

    Have you renamed the device via SCCM? or how do you do this?
    Are you using Windows 1903? Then it should work:
    https://feedback.azure.com/forums/169401-azure-active-directory/suggestions/12980892-machine-rename-azure-ad

      Rizwan · October 16, 2019 at 16:56

      I have noticed that devi e idnis different in intune abd in azure. Some thing i am doing it wrong

      I am using the powowershell from intune to rename the device as sccm takes too long to work. Could tht be the cause. If it is please inform

      Best practices for base installation

        Rizwan · October 16, 2019 at 17:01

        1903 inuse
        Using the powershell from intune
        Sccm baseline configuration not running straight away. As device get build with incorrect random name

        I have added the asset Information on the Device and instead of serial number i am using the asset id

        During the script it changes the device name.

        But notice that id is different on intune and azure ad

          Thomas Kurth · October 17, 2019 at 11:44

          OK, that sounds like a strange issue if you have different device id’s in Azure AD and Intune. I suggest to open an MS Case for this.

          If you rename a device manually over the UI is it then updating in all systems. If it renames in Active Directory on-prem. Is it then not synced to Azure AD?

Rizwan · October 17, 2019 at 09:12

Hello Thomas

Rename is done through script in Intune during the device preparation process. Using SMbios to pick asset info.

If used SCCM to deploy baseline as suggested. The rename wont happen till late. Unless that is the only way this should be implemented.

Please advise

Dowst.Dev | PowerShell Weekly – June 28, 2019 · June 28, 2019 at 13:37

[…] Automatic environment cleanup with Intune Connector for AD Extender Thomas Kurth provides great examples on how to keep your environment clean, using automatic cleanup of Intune Devices and ActiveDirectory Computer Accounts with PowerShell. […]

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.