了解Microsoft Entra Connect 1.4.xx.x 和设备消失

随着 Microsoft Entra Connect 版本 1.4.xx.x 的实现,客户可能会看到其部分或全部 Windows 设备从Microsoft Entra ID消失。 这不是令人担心的原因,因为条件访问授权期间,Microsoft Entra ID不会使用这些设备标识。 此更改不会删除任何已正确注册到 Microsoft Entra ID Microsoft Entra 混合联接的 Windows 设备。

如果在 Microsoft Entra ID中看到删除设备对象超过导出删除阈值,请允许删除操作完成。 如何:允许删除内容在超过删除阈值时流动

背景

注册为Microsoft Entra混合联接的 Windows 设备在 Microsoft Entra ID 中表示为设备对象,它们可用于条件访问。 Windows 10设备通过 Microsoft Entra Connect 同步到云,而下层 Windows 设备则直接使用 Active Directory 联合身份验证服务 (AD FS) 或无缝单一登录进行注册。

Windows 10 设备

只有Microsoft Entra混合联接配置的具有特定 userCertificate 属性值Windows 10设备应通过 Microsoft Entra Connect 同步到云。 在以前版本的 Microsoft Entra Connect 中,此要求未严格执行,并且向Microsoft Entra ID添加了不必要的设备对象。 Microsoft Entra ID中的此类设备始终保持“挂起”状态,因为这些设备不打算向Microsoft Entra ID注册。

此版本的 Microsoft Entra Connect 将仅同步正确配置为Microsoft Entra混合联接Windows 10设备。 Windows 10没有Microsoft Entra联接特定 userCertificate 的设备对象将从Microsoft Entra ID中删除。

Down-Level Windows 设备

Microsoft Entra Connect 绝不应同步下层 Windows 设备。 Microsoft Entra ID先前同步错误的任何设备都将从Microsoft Entra ID中删除。 如果 Microsoft Entra Connect 尝试删除下层 Windows 设备,则设备不是由 Microsoft Workplace Join 为非Windows 10计算机 MSI 创建的设备,它不能由任何其他Microsoft Entra功能使用。

某些客户可能需要重新访问操作方法:规划Microsoft Entra混合加入实现,以便正确注册其 Windows 设备,并确保这些设备可以参与基于设备的条件访问。

如何验证此更新删除了哪些设备?

若要验证已删除哪些设备,请使用 PowerShell 证书报告脚本中的 PowerShell 脚本

此脚本生成有关存储在 Active Directory 计算机对象中的证书的报告,特别是Microsoft Entra混合联接功能颁发的证书。

该脚本还会检查 AD 中 Computer 对象的 UserCertificate 属性中存在的证书。 对于存在的每个未过期证书,脚本会验证是否为Microsoft Entra混合联接功能颁发了证书;例如。 Subject Name matches CN={ObjectGUID}

在此更新之前,Microsoft Entra Connect 将同步到包含至少一个有效证书的任何计算机Microsoft Entra。 从 Microsoft Entra Connect 版本 1.4 开始,同步引擎标识Microsoft Entra混合加入证书,并使用 cloudfilter 筛选器阻止计算机对象同步到Microsoft Entra ID,除非存在有效的Microsoft Entra混合加入证书。

Microsoft Entra之前已同步到 AD 但没有有效Microsoft Entra混合加入证书的设备,同步引擎将使用筛选器 CloudFiltered=TRUE删除。

PowerShell 证书报告脚本

<#

Filename:    Export-ADSyncToolsHybridAzureADjoinCertificateReport.ps1.

DISCLAIMER:
Copyright (c) Microsoft Corporation. All rights reserved. This script is made available to you without any express, implied or statutory warranty, not even the implied warranty of  merchantability or fitness for a particular purpose, or the warranty of title or non-infringement. The entire risk of the use or the results from the use of this script remains with you.
.Synopsis
This script generates a report about certificates stored in Active Directory Computer objects, specifically, 
certificates issued by the Microsoft Entra hybrid join feature.
.DESCRIPTION
It checks the certificates present in the UserCertificate property of a Computer object in AD and, for each 
non-expired certificate present, validates if the certificate was issued for the Microsoft Entra hybrid join feature 
(i.e. Subject Name matches CN={ObjectGUID}).
Before, Microsoft Entra Connect would synchronize to Microsoft Entra ID any Computer that contained at least one valid 
certificate but starting on Microsoft Entra Connect version 1.4, the sync engine can identify Hybrid 
Microsoft Entra join certificates and will 'cloudfilter' the computer object from synchronizing to Microsoft Entra ID unless 
there's a valid Microsoft Entra hybrid join certificate.
Microsoft Entra Device objects that were already synchronized to AD but do not have a valid Microsoft Entra hybrid join 
certificate will be deleted (CloudFiltered=TRUE) by the sync engine.
.EXAMPLE
.\Export-ADSyncToolsHybridAzureADjoinCertificateReport.ps1 -DN 'CN=Computer1,OU=SYNC,DC=Fabrikam,DC=com'
.EXAMPLE
.\Export-ADSyncToolsHybridAzureADjoinCertificateReport.ps1 -OU 'OU=SYNC,DC=Fabrikam,DC=com' -Filename "MyHybridAzureADjoinReport.csv" -Verbose

#>
   [CmdletBinding()]
   Param
   (
       # Computer DistinguishedName
       [Parameter(ParameterSetName='SingleObject',
               Mandatory=$true,
               ValueFromPipelineByPropertyName=$true,
               Position=0)]
       [String]
       $DN,

       # AD OrganizationalUnit
       [Parameter(ParameterSetName='MultipleObjects',
               Mandatory=$true,
               ValueFromPipelineByPropertyName=$true,
               Position=0)]
       [String]
       $OU,

       # Output CSV filename (optional)
       [Parameter(Mandatory=$false,
               ValueFromPipelineByPropertyName=$false,
               Position=1)]
       [String]
       $Filename

   )

   # Generate Output filename if not provided
   If ($Filename -eq "")
   {
       $Filename = [string] "$([string] $(Get-Date -Format yyyyMMddHHmmss))_ADSyncAADHybridJoinCertificateReport.csv"
   }
   Write-Verbose "Output filename: '$Filename'"
   
   # Read AD object(s)
   If ($PSCmdlet.ParameterSetName -eq 'SingleObject')
   {
       $directoryObjs = @(Get-ADObject $DN -Properties UserCertificate)
       Write-Verbose "Starting report for a single object '$DN'"
   }
   Else
   {
       $directoryObjs = Get-ADObject -Filter { ObjectClass -like 'computer' } -SearchBase $OU -Properties UserCertificate
       Write-Verbose "Starting report for $($directoryObjs.Count) computer objects in OU '$OU'"
   }

   Write-Host "Processing $($directoryObjs.Count) directory object(s). Please wait..."
   # Check Certificates on each AD Object
   $results = @()
   ForEach ($obj in $directoryObjs)
   {
       # Read UserCertificate multi-value property
       $objDN = [string] $obj.DistinguishedName
       $objectGuid = [string] ($obj.ObjectGUID).Guid
       $userCertificateList = @($obj.UserCertificate)
       $validEntries = @()
       $totalEntriesCount = $userCertificateList.Count
       Write-verbose "'$objDN' ObjectGUID: $objectGuid"
       Write-verbose "'$objDN' has $totalEntriesCount entries in UserCertificate property."
       If ($totalEntriesCount -eq 0)
       {
           Write-verbose "'$objDN' has no Certificates - Skipped."
           Continue
       }

       # Check each UserCertificate entry and build array of valid certs
       ForEach($entry in $userCertificateList)
       {
           Try
           {
               $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2] $entry
           }
           Catch
           {
               Write-verbose "'$objDN' has an invalid Certificate!"
               Continue
           }
           Write-verbose "'$objDN' has a Certificate with Subject: $($cert.Subject); Thumbprint:$($cert.Thumbprint)."
           $validEntries += $cert

       }
       
       $validEntriesCount = $validEntries.Count
       Write-verbose "'$objDN' has a total of $validEntriesCount certificates (shown above)."
       
       # Get non-expired Certs (Valid Certificates)
       $validCerts = @($validEntries | Where-Object {$_.NotAfter -ge (Get-Date)})
       $validCertsCount = $validCerts.Count
       Write-verbose "'$objDN' has $validCertsCount valid certificates (not-expired)."

       # Check for Microsoft Entra hybrid join Certificates
       $hybridJoinCerts = @()
       $hybridJoinCertsThumbprints = [string] "|"
       ForEach ($cert in $validCerts)
       {
           $certSubjectName = $cert.Subject
           If ($certSubjectName.StartsWith($("CN=$objectGuid")) -or $certSubjectName.StartsWith($("CN={$objectGuid}")))
           {
               $hybridJoinCerts += $cert
               $hybridJoinCertsThumbprints += [string] $($cert.Thumbprint) + '|'
           }
       }

       $hybridJoinCertsCount = $hybridJoinCerts.Count
       if ($hybridJoinCertsCount -gt 0)
       {
           $cloudFiltered = 'FALSE'
           Write-verbose "'$objDN' has $hybridJoinCertsCount Microsoft Entra hybrid join Certificates with Thumbprints: $hybridJoinCertsThumbprints (cloudFiltered=FALSE)"
       }
       Else
       {
           $cloudFiltered = 'TRUE'
           Write-verbose "'$objDN' has no Microsoft Entra hybrid join Certificates (cloudFiltered=TRUE)."
       }
       
       # Save results
       $r = "" | Select ObjectDN, ObjectGUID, TotalEntriesCount, CertsCount, ValidCertsCount, HybridJoinCertsCount, CloudFiltered
       $r.ObjectDN = $objDN
       $r.ObjectGUID = $objectGuid
       $r.TotalEntriesCount = $totalEntriesCount
       $r.CertsCount = $validEntriesCount
       $r.ValidCertsCount = $validCertsCount
       $r.HybridJoinCertsCount = $hybridJoinCertsCount
       $r.CloudFiltered = $cloudFiltered
       $results += $r
   }

   # Export results to CSV
   Try
   {        
       $results | Export-Csv $Filename -NoTypeInformation -Delimiter ';'
       Write-Host "Exported Hybrid Microsoft Entra Domain Join Certificate Report to '$Filename'.`n"
   }
   Catch
   {
       Throw "There was an error saving the file '$Filename': $($_.Exception.Message)"
   }

后续步骤

联系我们寻求帮助

如果你有任何疑问或需要帮助,请创建支持请求联系 Azure 社区支持。 还可以向 Azure 反馈社区提交产品反馈。