配置 Active Directory 以使虚拟机自动加入网域

Last reviewed 2024-10-31 UTC

本文档介绍了如何配置 Active Directory 和 Compute Engine,以便 Windows 虚拟机 (VM) 实例可以自动加入 Active Directory 域。

自动执行将 Windows 虚拟机加入 Active Directory 的过程有助于简化 Windows 服务器的预配过程。此方法还可以让您利用自动扩缩,而不会影响使用 Active Directory 管理访问权限和配置的优势。

本文档面向系统管理员,并假定您熟悉 Active Directory 和 Google Cloud 网络。

您按照本文档中的过程创建的配置可以是您在 Google Cloud 中使用 Windows Server 执行的其他工作的基础。例如,完成此过程后,您可以在 Windows 容器中部署具有 Windows 身份验证的 ASP.NET 应用。

如果您使用的是托管式 Microsoft AD,并且不需要自动清理过时计算机账号,请考虑使用自动域加入功能来加入 Windows 虚拟机。如需了解详情,请参阅将 Windows 虚拟机自动加入网域

目标

  • 部署 Cloud Run 应用,以使选定项目中的虚拟机实例自动加入您的 Active Directory 域。
  • 创建一个 Cloud Scheduler 作业,用于定期扫描 Active Directory 域以查找过时的计算机账号,并移除这些账号。
  • 通过创建已加入网域的虚拟机实例的自动扩缩托管式实例组 (MIG),测试设置。

费用

在本文档中,您将使用 Google Cloud 的以下收费组件:

本文档中的说明旨在将您的资源使用量保持在 Google Cloud 的始终免费层级的限制范围内。 您可使用价格计算器根据您的预计使用情况来估算费用。 Google Cloud 新用户可能有资格申请免费试用

完成本文档后,您可以删除所创建的资源以避免继续计费。如需了解详情,请参阅清理

准备工作

本文档假定您已通过使用 Managed Service for Microsoft Active Directory (Managed Microsoft AD) 或通过在 Google Cloud 上部署自行管理的域控制器,在 Google Cloud 上部署了 Active Directory。

为了完成这些过程,请确保您拥有以下各项:

  • 对您的 Active Directory 域的管理员权限,包括创建用户、群组和组织单元 (OU) 的权限。
  • VPC 中未使用的 /28 CIDR IP 地址范围,您的 Active Directory 域控制器将部署到该范围内。此 IP 地址范围用于配置无服务器 VPC 访问通道。
  • 要在其中部署 Windows 实例的子网。该子网必须配置为使用专用 Google 访问通道

如果您使用的是自托管网域控制器,则您还需要以下资源:

实现此方法

在本地环境中,您可以依靠应答文件 (unattend.xml) 和 JoinDomain 自定义设置自动将新计算机加入域。虽然您可以在 Google Cloud 中使用相同的过程,但此方法存在一些限制:

  • 使用自定义 unattend.xml 文件时,您需要维护一个自定义 Compute Engine 映像。使用 Windows 更新来使自定义映像保持最新状态时,您需要通过持续维护或初始工作来设置自动化。除非您出于其他原因而需要维护自定义映像,否则这种额外的操作可能是不合理的。
  • 由于必须在 unattend.xml 中指定域名,因此,使用 JoinDomain 自定义会将映像与单个 Active Directory 域相关联。如果您维护了多个 Active Directory 域或林(例如,对于单独的测试和生产环境),则可能需要为每个网域维护多个自定义映像。
  • 将 Windows 计算机加入网域需要拥有有权在目录中创建计算机对象的用户凭据。如果您在 unattend.xml 中使用 JoinDomain 自定义,则必须在 unattend.xml 中以明文形式嵌入这些凭据。这些嵌入的凭据会将映像变为攻击者的潜在目标。您可以通过设置适当的身份和访问权限管理 (IAM) 权限来控制对映像的访问权限,但管理对自定义映像的访问权限会增加不必要的复杂性。

本文档中的方法未使用应答文件,因此不需要专门准备的映像。而是在创建虚拟机实例时使用以下 sysprep 专用 scriptlet

iex((New-Object System.Net.WebClient).DownloadString('https://DOMAIN'))

此 sysprep 专用 scriptlet 会启动下图所示的过程。

sysprep 专用 scriptlet 启动的过程。

该过程的工作原理如下:

  1. 虚拟机实例创建完毕后,Windows 首次启动。作为专用化配置过程的一部分,Windows 会运行 sysprep 专用化 scriptlet。专用化 scriptlet 会调用 register-computer Cloud Run 应用,并下载用于控制网域加入过程的 PowerShell 脚本。
  2. Windows 会调用已下载的 PowerShell 脚本。
  3. PowerShell 脚本调用元数据服务器,以获取安全地标识虚拟机实例的 ID 令牌。
  4. 该脚本再次调用 register-computer 应用,传递 ID 令牌以进行身份验证。
  5. 应用验证 ID 令牌,并提取虚拟机实例的名称、可用区和 Google Cloud 项目 ID。
  6. 该应用验证 Active Directory 域是否已配置为允许指定项目中的虚拟机实例加入网域。为完成此验证,应用会找到并连接到 Active Directory 域控制器,以查找名称与 ID 令牌中的 Google Cloud 项目 ID 匹配的组织单元 (OU)。如果找到匹配的组织单元,则项目的虚拟机实例将有权加入指定组织单元中的 Active Directory 域。
  7. 应用验证 Google Cloud 项目是否已配置为允许虚拟机实例加入 Active Directory。为完成此验证,应用会使用 Compute Engine API 检查其是否可以访问虚拟机实例。
  8. 如果所有检查都成功通过,则应用将在 Active Directory 中预演计算机账号。应用会将虚拟机实例的名称、可用区和 ID 保存为计算机账号对象中的特性,以便它可以与虚拟机实例关联。
  9. 该应用使用 Kerberos 设置密码协议为计算机账号分配一个随机密码。
  10. 计算机名称和密码通过 TLS 加密通道返回到 Windows 实例。
  11. PowerShell 脚本使用预演的计算机账号将计算机加入网域。
  12. 专用配置阶段完毕后,机器会自动重新启动。

本过程的其余部分逐步介绍了设置自动域加入所需的步骤。

准备 Active Directory 域

首先,请准备您的 Active Directory 域。为完成此步骤,您需要一台对 Active Directory 域拥有管理员权限的机器。

可选:限制哪些用户可将计算机加入网域

您可能需要限制谁可以将计算机加入网域。默认情况下,默认域控制器政策的组策略对象 (GPO) 配置会向所有经过身份验证的用户授予 Add workstations to domain 用户权限。拥有该用户权限的任何人都可以将计算机加入网域。由于您要自动执行将计算机加入 Active Directory 域的过程,因此,广泛地授予此级别的访问权限会带来不必要的安全风险。

如需限制谁可以将计算机加入您的 Active Directory 域,请更改“默认网域控制器政策”GPO 的默认配置:

  1. 使用 RDP 客户端登录对 Active Directory 域拥有管理员权限的机器。
  2. 打开组策略管理控制台 (GPMC)。
  3. 依次点击 Forest > Domains > domain-name > Group Policy Objects,其中 domain-name 是 Active Directory 域的名称。
  4. 右键点击默认域控制器策略 (Default Domain Controller Policy),然后点击修改
  5. 在组策略管理编辑器控制台中,转到计算机配置 > 策略 > Windows 设置 > 安全设置 > 本地策略 > 用户权限分配
  6. 双击将工作站添加到域
  7. 属性中,从列表中移除 Authenticated Users
  8. 如需让管理员手动加入网域(可选),请点击添加用户或组,然后向列表添加管理组。
  9. 点击确定

您现在可以关闭组策略管理编辑器控制台和 GPMC。

初始化目录结构

现在,您可以创建一个组织单元,作为所有项目专属组织单元的容器:

  1. 使用 RDP 客户端登录对 Active Directory 域拥有管理员权限的机器。
  2. 打开提升权限的 PowerShell 会话。
  3. 创建新的组织单元:

    $ParentOrgUnitPath = (Get-ADDomain).ComputersContainer
    $ProjectsOrgUnitPath = New-ADOrganizationalUnit `
      -Name 'Projects' `
      -Path $ParentOrgUnitPath `
      -PassThru
    

创建 Active Directory 用户账号

如需访问 Active Directory 和预演计算机账号,register-computer 应用需要 Active Directory 用户账号:

  1. 创建一个名为 register-computer 的 Active Directory 用户账号,为其分配一个随机密码,然后将其放入 Projects 组织单元:

    # Generate a random password
    $Password = [Guid]::NewGuid().ToString()+"-"+[Guid]::NewGuid().ToString()
    
    # Create user
    $UpnSuffix = (Get-ADDomain).DNSRoot
    $RegisterComputerUser = New-ADUser `
        -Name "register-computer Cloud Run app" `
        -GivenName "Register" `
        -Surname "Computer" `
        -Path $ProjectsOrgUnitPath `
        -SamAccountName "register-computer" `
        -UserPrincipalName "register-computer@$UpnSuffix" `
        -AccountPassword (ConvertTo-SecureString "$Password" -AsPlainText -Force) `
        -PasswordNeverExpires $True `
        -Enabled $True `
        -PassThru
    
  2. register-computer 账号授予在 Projects 组织单元和子组织单元中管理计算机账号和群组所需的最低权限集:

    $AcesForContainerAndDescendents = @(
        "CCDC;Computer",               # Create/delete computers
        "CCDC;Group"                   # Create/delete users
    )
    
    $AcesForDescendents = @(
        "LC;;Computer" ,               # List child objects
        "RC;;Computer" ,               # Read security information
        "WD;;Computer" ,               # Change security information
        "WP;;Computer" ,               # Write properties
        "RP;;Computer" ,               # Read properties
        "CA;Reset Password;Computer",  # ...
        "CA;Change Password;Computer", # ...
        "WS;Validated write to service principal name;Computer",
        "WS;Validated write to DNS host name;Computer",
    
        "LC;;Group",                   # List child objects
        "RC;;Group",                   # Read security information
        "WD;;Group",                   # Change security information
        "WP;;Group",                   # Write properties
        "RP;;Group"                    # Read properties
    )
    
    $AcesForContainerAndDescendents | % { dsacls.exe $ProjectsOrgUnitPath /G "${RegisterComputerUser}:${_}" /I:T | Out-Null }
    $AcesForDescendents | % { dsacls.exe $ProjectsOrgUnitPath /G "${RegisterComputerUser}:${_}" /I:S | Out-Null }
    

    此命令可能需要几分钟时间才能完成。

  3. register-computer 账号授予删除 DNS 记录的权限:

    托管式 Microsoft AD

    Add-ADGroupMember -Identity "Cloud Service DNS Administrators" -Members ${RegisterComputerUser}
    

    自有网域

    $DnsPartition=(Get-ADDomain).SubordinateReferences | Where-Object {$_.StartsWith('DC=DomainDnsZones')}
    $DnsContainer="DC=$((Get-ADDomain).DNSRoot),CN=MicrosoftDNS,$DnsPartition"
    
    dsacls $DnsContainer /G "${RegisterComputerUser}:SD" /I:S
    
  4. 显示 Projects 组织目录路径以及 register-computer Active Directory 用户账号的生成密码。请记下这些值,因为稍后您将用到这些值。

    Write-Host "Password: $Password"
    Write-Host "Projects OU: $ProjectsOrgUnitPath"
    

准备 Google Cloud 项目

现在,您可以配置您的网域项目:

  • 如果您使用的是 Managed Microsoft AD,则您的网域项目就是部署了 Managed Microsoft AD 的项目。
  • 如果您使用的是自托管 Active Directory,则您的网域项目就是运行 Active Directory 域控制器的项目。如果是共享 VPC,则此项目必须是 VPC 宿主项目。

您可以使用此网域项目执行以下操作:

  • 创建包含 register-computer Active Directory 用户账号密码的 Secret Manager Secret。
  • 部署 register-computer 应用。
  • 配置 Cloud Scheduler,使其触发清理过时计算机账号的过程。

我们建议您授予对网域项目的最小权限。

创建 Secret Manager Secret

  1. 在 Google Cloud 控制台中,打开 Cloud Shell。

    打开 Cloud Shell

  2. 启动 PowerShell:

    pwsh
    
  3. 初始化以下变量,将 domain-project-id 替换为您的网域项目的 ID:

    $DomainProjectId = "domain-project-id"
    
  4. 将网域项目设置为默认项目:

    & gcloud config set project $DomainProjectId
    
  5. 启用 Secret Manager API:

    & gcloud services enable secretmanager.googleapis.com
    
  6. 输入 register-computer Active Directory 用户账号的密码,并将其存储在 Secret Manager Secret 中:

    $RegisterComputerCredential = (Get-Credential -Credential 'register-computer')
    
    $TempFile = New-TemporaryFile
    Set-Content $TempFile $($RegisterComputerCredential.GetNetworkCredential().Password) -NoNewLine
    
    & gcloud secrets create ad-password --data-file $TempFile
    
    Remove-Item $TempFile
    

授予对 Kerberos 和 LDAP 的访问权限

为了管理网域关联,register-computer 应用会使用以下协议访问您的网域控制器:

  • LDAP (TCP/389) 或 LDAPS (TCP/636)
  • Kerberos(UDP/88、TCP/88)
  • Kerberos 密码更改(UDP/464、TCP/464)

托管式 Microsoft AD

您无需配置任何防火墙规则。

自有网域

创建允许访问网域控制器的防火墙规则。

您可以根据已分配给域控制器的网络标记来应用规则,也可以使用服务账号来应用规则。

通过网络标记

& gcloud compute firewall-rules create allow-adkrb-from-serverless-to-dc `
    --direction INGRESS `
    --action allow `
    --rules udp:88,tcp:88,tcp:389,tcp:636,udp:464,tcp:464 `
    --source-ranges $ServerlessIpRange `
    --target-tags dc-tag `
    --network $VpcName `
    --project vpc-project-id `
    --priority 10000

替换以下内容:

  • dc-tag:分配给您的网域控制器虚拟机的网络标记。
  • vpc-project-id:在其中定义了 VPC 的项目的 ID。如果您使用了共享 VPC,则使用 VPC 宿主项目的 ID;否则,请使用网域项目的 ID。

通过服务账号

& gcloud compute firewall-rules create allow-adkrb-from-serverless-to-dc `
    --direction INGRESS `
    --action allow `
    --rules udp:88,tcp:88,tcp:389,tcp:636,udp:464,tcp:464 `
    --source-ranges $ServerlessIpRange `
    --target-service-accounts dc-sa `
    --network $VpcName `
    --project vpc-project-id `
    --priority 10000

替换以下内容:

  • dc-sa:您的网域控制器虚拟机所用的服务账号的电子邮件地址。
  • vpc-project-id:在其中定义了 VPC 的项目的 ID。如果您使用了共享 VPC,则使用 VPC 宿主项目的 ID;否则,请使用网域项目的 ID。

部署 Cloud Run 应用

现在,您可以设置 Cloud Build 以将 register-computer 应用部署到 Cloud Run:

  1. 在 Cloud Shell 中,克隆 GitHub 代码库:

    & git clone https://github.com/GoogleCloudPlatform/gce-automated-ad-join.git
    cd gce-automated-ad-join/ad-joining
    
  2. 初始化以下变量:

    $ServerlessRegion = "serverless-region"
    $VpcName = "vpc-name"
    $VpcSubnet = "subnet-name"
    $AdDomain = "dns-domain-name"
    $AdNetbiosDomain = "netbios-domain-name"
    $ProjectsOrgUnitPath = "projects-ou-distinguished-name"
    

    替换以下内容:

    • serverless-region:要在其中部署 register-computer 应用的区域。该地区不一定得是您计划在其中部署虚拟机实例的地区。
    • vpc-name:包含您的 Active Directory 网域控制器的 VPC 网络的名称。
    • subnet-name:用于直接 VPC 访问vpc-name 子网。子网必须与 serverless-region 位于同一区域。
    • dns-domain-name:您的 Active Directory 域的 DNS 域名。
    • netbios-domain-name:您的 Active Directory 域的 NetBIOS 名称。
    • projects-ou-distinguished-name:您的 Projects 组织单元的标识名。
  3. 启用 Cloud Run 和 Cloud Build API。

    & gcloud services enable run.googleapis.com cloudbuild.googleapis.com
    
  4. 为 Cloud Run 应用创建服务账号 register-computer-app

    & gcloud iam service-accounts create register-computer-app `
      --display-name="register computer Cloud Run app"
    
  5. 创建一个用于运行 Cloud Build 触发器的服务账号 build-service

    & gcloud iam service-accounts create build-service `
      --display-name="Cloud Build build agent"
    
  6. 允许 Cloud Run 服务账号读取包含 Active Directory 密码的 Secret:

    & gcloud secrets add-iam-policy-binding ad-password `
      --member "serviceAccount:register-computer-app@$DomainProjectId.iam.gserviceaccount.com" `
      --role "roles/secretmanager.secretAccessor"
    
  7. 向 Cloud Build 授予部署到 Cloud Run 的必要权限

    $DomainProjectNumber = (gcloud projects describe $DomainProjectId --format='value(projectNumber)')
    & gcloud iam service-accounts add-iam-policy-binding register-computer-app@$DomainProjectId.iam.gserviceaccount.com `
      --member "serviceAccount:build-service@$DomainProjectId.iam.gserviceaccount.com" `
      --role "roles/iam.serviceAccountUser"
    
    & gcloud projects add-iam-policy-binding $DomainProjectId `
      --member "serviceAccount:build-service@$DomainProjectId.iam.gserviceaccount.com" `
      --role roles/cloudbuild.builds.builder
    
    & gcloud projects add-iam-policy-binding $DomainProjectId `
      --member "serviceAccount:build-service@$DomainProjectId.iam.gserviceaccount.com" `
      --role roles/run.admin
    
  8. 使用文件 cloudbuild.yaml 作为模板,创建与您的环境相匹配的自定义 Cloud Run 构建配置:

    $Build = (Get-Content cloudbuild.yaml)
    $Build = $Build.Replace('__SERVERLESS_REGION__', "$ServerlessRegion")
    $Build = $Build.Replace('__PROJECTS_DN__', "$ProjectsOrgUnitPath")
    $Build = $Build.Replace('__AD_DOMAIN__', "$AdDomain")
    $Build = $Build.Replace('__AD_NETBIOS_DOMAIN__', "$AdNetbiosDomain")
    $Build = $Build.Replace('__SERVICE_ACCOUNT_EMAIL__', "register-computer-app@$DomainProjectId.iam.gserviceaccount.com")
    $Build = $Build.Replace('__SERVERLESS_NETWORK__', "$VpcName")
    $Build = $Build.Replace('__SERVERLESS_SUBNET__', "$VpcSubnet")
    $Build | Set-Content .\cloudbuild.hydrated.yaml
    
  9. 构建应用并将其部署到 Cloud Run:

    & gcloud builds submit . `
      --config cloudbuild.hydrated.yaml `
      --substitutions _IMAGE_TAG=$(git rev-parse --short HEAD) `
      --service-account "projects/$DomainProjectId/serviceAccounts/build-service@$DomainProjectId.iam.gserviceaccount.com" `
      --default-buckets-behavior regional-user-owned-bucket
    

    部署过程可能需要几分钟才能完成。

  10. 确定 Cloud Run 应用的网址:

    $RegisterUrl = (gcloud run services describe register-computer `
      --platform managed `
      --region $ServerlessRegion `
      --format=value`(status.url`))
    Write-Host $RegisterUrl
    

    记下该网址。每次创建应加入 Active Directory 的虚拟机实例时,您都需要它。

  11. 调用 Cloud Run 应用以验证部署是否有效:

    Invoke-RestMethod $RegisterUrl
    

    此时会显示一个 PowerShell 脚本。虚拟机将在加入网域的专用阶段运行此脚本。

为项目启用自动网域加入功能

register-computer 应用不允许虚拟机实例加入 Active Directory 域,除非已为虚拟机的项目启用自动网域加入功能。此安全措施有助于防止连接到未授权项目的虚拟机访问您的网域。

如需为项目启用自动网域加入功能,您必须执行以下操作:

  • 在 Active Directory 中创建一个名称与您的 Google Cloud 项目 ID 匹配的组织单元。
  • register-computer 应用授予对 Google Cloud 项目的访问权限。

首先,创建组织单元:

  1. 使用 RDP 客户端登录对 Active Directory 域拥有管理员权限的机器。
  2. 在“Active Directory 用户和计算机”MMC 管理单元中,转到 Projects 组织单元。
  3. 右键点击组织单元,然后依次选择新建 > 组织单位
  4. 新建对象对话框中,输入要在其中部署虚拟机的 Google Cloud 项目的 ID。
  5. 点击确定

接下来,向 register-computer 应用授予对 Google Cloud 项目的访问权限:

  1. 在 Cloud Shell 中,启动 PowerShell:

    pwsh
    
  2. 初始化以下变量:

    $ProjectId = "project-id"
    $DomainProjectId = "domain-project-id"
    

    替换

    • project-id 替换为要在其中部署虚拟机的 Google Cloud 项目的 ID
    • domain-project-id 替换为网域项目的 ID。
  3. register-computer-app 服务账号授予项目的 Compute Viewer 角色:

    & gcloud projects add-iam-policy-binding $ProjectId `
        --member "serviceAccount:register-computer-app@$DomainProjectId.iam.gserviceaccount.com" `
        --role "roles/compute.viewer"
    

现在,您的项目已准备好支持自动网域加入功能。

测试网域加入

您现在可以通过以下方式验证设置是否有效:

  • 创建可自动加入 Active Directory 域的虚拟机实例
  • 创建一个可自动加入 Active Directory 域的虚拟机实例的托管式实例组

创建和加入单个虚拟机实例

创建可自动加入 Active Directory 域的虚拟机实例:

  1. 返回 Cloud Shell 中的 PowerShell 会话并初始化以下变量:

    $Region = "vpc-region-to-deploy-vm"
    $Zone = "zone-to-deploy-vm"
    $Subnet = "vpc-subnet-to-deploy-vm"
    $ServerlessRegion = "serverless-region"
    

    请替换以下内容:

    • vpc-region-to-deploy-vm:要在其中部署虚拟机实例的地区。
    • vpc-subnet-to-deploy-vm:要在其中部署虚拟机实例的子网。
    • zone-to-deploy-vm:要在其中部署虚拟机实例的区域。
    • serverless-region:在其中部署了 Cloud Run 应用的区域。
  2. 设置默认项目和可用区:

    & gcloud config set project $ProjectId
    & gcloud config set compute/zone $Zone
    
  3. 再次查找 Cloud Run 应用的网址:

    $RegisterUrl = (gcloud run services describe register-computer `
      --platform managed `
      --region $ServerlessRegion `
      --format value`(status.url`) `
      --project $DomainProjectId)
    
  4. 通过传递将虚拟机加入网域的专用 scriptlet 来创建实例:

    共享 VPC

    $VpchostProjectId = (gcloud compute shared-vpc get-host-project $ProjectId --format=value`(name`))
    & gcloud compute instances create join-01 `
        --image-family windows-2019-core `
        --image-project windows-cloud `
        --machine-type n1-standard-2 `
        --no-address `
        --subnet projects/$VpchostProjectId/regions/$Region/subnetworks/$Subnet `
        --metadata "sysprep-specialize-script-ps1=iex((New-Object System.Net.WebClient).DownloadString('$RegisterUrl'))"
    

    独立 VPC

    & gcloud compute instances create join-01 `
        --image-family=windows-2019-core `
        --image-project=windows-cloud `
        --machine-type=n1-standard-2 `
        --no-address `
        --subnet $Subnet `
        --metadata "sysprep-specialize-script-ps1=iex((New-Object System.Net.WebClient).DownloadString('$RegisterUrl'))"
    

    如果要使用自定义主机名,请在命令中添加 --hostname 参数。

    如果您使用的是 Windows Server 2019 之前的 Windows Server 版本,则 TLS 1.2 可能会默认处于停用状态,这可能导致专用化 scriptlet 失败。如需启用 TLS 1.2,请改用以下 scriptlet:

    [Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12;iex((New-Object System.Net.WebClient).DownloadString('$RegisterUrl'))
    
  5. 监控启动过程:

    & gcloud compute instances tail-serial-port-output join-01
    

    大约一分钟后,虚拟机将加入您的 Active Directory 域。输出内容类似如下:

    Domain           : corp.example.com
    DomainController : dc-01.corp.example.com.
    OrgUnitPath      : OU=test-project-123,OU=Projects,DC=corp,DC=example,DC=com
    
    WARNING: The changes will take effect after you restart the computer
    
    Computer successfully joined to domain
    

    如需停止观察启动过程,请按 CTRL+C

验证虚拟机是否已加入 Active Directory

  1. 使用 RDP 客户端登录对 Active Directory 域拥有管理员权限的机器。
  2. 打开“Active Directory 用户和计算机”MMC 管理单元。
  3. 在菜单中,确保已选择查看 > 高级功能
  4. 前往以在其中创建了虚拟机实例的 Google Cloud 项目的 ID 命名的组织单元。
  5. 双击 join-01 账号。
  6. 属性对话框中,点击特性编辑器标签页。

    计算机账号使用其他 LDAP 特性进行注释。这些特性可让您跟踪计算机对象与 Compute Engine 实例之间的关联。

    验证列表中是否包含以下 LDAP 特性和值。

    LDAP 属性
    msDS-cloudExtensionAttribute1 Google Cloud 项目 ID
    msDS-cloudExtensionAttribute2 Compute Engine 区域
    msDS-cloudExtensionAttribute3 Compute Engine 实例名称

    msDS-cloudExtensionAttribute 属性为通用属性,Active Directory 本身不会使用这些属性。

诊断错误

如果您的虚拟机实例无法加入网域,请检查 register-computer 应用的日志:

  1. 在 Google Cloud 控制台中,转到 Cloud Run。

    转到 Cloud Run

  2. 点击 register-computer 应用。

  3. 点击菜单中的日志

删除实例

确认虚拟机实例已加入 Active Directory 域后,删除实例。

  • 删除实例:

    & gcloud compute instances delete join-01 --quiet
    

创建并加入托管式实例组

您还可以验证 MIG 中的实例是否可以自动加入您的网域。

  1. 通过传递将虚拟机加入网域的专用脚本来创建实例模板:

    共享 VPC

    $VpchostProjectId = (gcloud compute shared-vpc get-host-project $ProjectId --format=value`(name`))
    & gcloud compute instance-templates create ad-2019core-n1-std-2 `
        --image-family windows-2019-core `
        --image-project windows-cloud `
        --no-address `
        --machine-type n1-standard-2 `
        --subnet projects/$VpchostProjectId/regions/$Region/subnetworks/$Subnet `
        --metadata "sysprep-specialize-script-ps1=iex((New-Object System.Net.WebClient).DownloadString('$RegisterUrl'))"
    

    独立 VPC

    & gcloud compute instance-templates create ad-2019core-n1-std-2 `
        --image-family windows-2019-core `
        --image-project windows-cloud `
        --no-address `
        --machine-type n1-standard-2 `
        --subnet projects/$ProjectId/regions/$Region/subnetworks/$Subnet `
        --metadata "sysprep-specialize-script-ps1=iex((New-Object System.Net.WebClient).DownloadString('$RegisterUrl'))"
    
  2. 创建一个使用实例模板的托管式实例组:

    & gcloud compute instance-groups managed create group-01 `
        --template ad-2019core-n1-std-2 `
        --size=3
    

等待几分钟,然后使用“Active Directory 用户和计算机”MMC 管理单元验证是否已在 Active Directory 中创建了四个新对象:

  • 对应于托管式实例组的 3 个虚拟机实例的 3 个计算机账号。
  • 1 个名为 group-01 的群组,其中包含 3 个计算机账号。如果您计划使用群组托管式服务账号 (gMSA),则可以使用此群组授予对 gMSA 的访问权限。

确认 MIG 中的虚拟机实例可以加入您的 Active Directory 域后,您可以按照以下步骤删除托管组和实例模板:

  1. 在 Cloud Shell 中,删除实例组:

    & gcloud compute instance-groups managed delete group-01 --quiet
    
  2. 删除实例模板:

    & gcloud compute instance-templates delete ad-2019core-n1-std-2 --quiet
    

安排清理过时的计算机账号

自动执行将计算机加入域的过程可以减少设置新服务器的工作量,可让您在托管式实例组中使用已加入域的服务器。但是,随着时间的推移,过时的计算机账号会在网域中积聚。

为了防止这种积聚,我们建议您设置 register-computer Cloud Functions 函数,以定期扫描 Active Directory 网域,找到并自动移除过时的账号及其关联的 DNS 记录。

register-computer 应用可以使用计算机账号的 msDS-cloudExtensionAttribute 特性来识别哪些计算机账号是过时的。这些特性包含 Compute Engine 中相应虚拟机实例的项目、区域和实例名称。对于每个计算机账号,该应用都可以检查相应的虚拟机实例是否仍然可用。如果不可用,则该计算机账号会被视为过时,然后被移除。

如需触发计算机账号清理,请调用 Cloud Run 应用的 /cleanup 端点。为防止未经授权的用户触发清理,必须使用 register-computer-app 服务账号对此请求进行身份验证。

配置 Cloud Scheduler

以下步骤介绍了如何将 Cloud SchedulerPub/Sub 同时设置为每 24 小时自动触发一次清理:

  1. 在 Cloud Shell 中,在您的网域项目中启用 Cloud Scheduler API:

    & gcloud services enable cloudscheduler.googleapis.com
    
  2. AppEngineLocation 设置为要在其中部署 Cloud Scheduler 的有效 App Engine 位置

    $AppEngineLocation = "location"
    

    location 替换为您为 VPC 资源选择的 App Engine 地区,例如 us-central。如果该地区不能作为 App Engine 位置,请选择在地理位置上与您接近的位置。如需了解详情,请参阅地区和区域

  3. 初始化 App Engine:

    & gcloud app create --region $AppEngineLocation --project $DomainProjectId
    
  4. 创建 Cloud Scheduler 作业:

    & gcloud scheduler jobs create http cleanup-computer-accounts `
        --schedule "every 24 hours" `
        --uri "$RegisterUrl/cleanup" `
        --oidc-service-account-email register-computer-app@$DomainProjectId.iam.gserviceaccount.com `
        --oidc-token-audience "$RegisterUrl/" `
        --project $DomainProjectId
    

    该作业每 24 小时调用一次 register-computer 应用,并使用 register-computer-app 服务账号进行身份验证。

触发清理过程

如需验证清理过时计算机账号的配置,您可以手动触发 Cloud Scheduler 作业。

  1. 在 Google Cloud 控制台中,转到 Cloud Scheduler。

    转到 Cloud Scheduler

  2. 对于您创建的 cleanup-computer-accounts 作业,请点击立即运行

    几秒钟后,结果列将显示成功,表示清理已成功完成。如果结果列未在几秒内自动更新,请点击刷新按钮。

如需详细了解哪些账号已被清理,请查看 register-computer 应用的日志。

  1. 在 Google Cloud 控制台中,转到 Cloud Run。

    转到 Cloud Run

  2. 点击 register-computer 应用。

  3. 点击菜单中的日志

    日志条目表明您用于测试网域加入结果的虚拟机实例的计算机账号已标识为过时并已移除。

清理

如果您将本文档用作其他参考架构和部署的基准,请参阅其他文档,了解何时运行清理步骤。

如果您不想保留本文档中使用的 Google Cloud 设置,可以通过执行以下操作来还原此设置:

  1. 在 Cloud Shell 中,删除 Cloud Scheduler 作业:

    & gcloud scheduler jobs delete cleanup-computer-accounts `
      --project $DomainProjectId
    
  2. 删除 Cloud Run 应用:

    & gcloud run services delete register-computer `
      --platform managed `
      --project $DomainProjectId `
      --region $ServerlessRegion
    
  3. 删除 Secret Manager Secret:

    gcloud secrets delete ad-password --project $DomainProjectId
    
  4. 删除 LDAP 和 Kerberos 访问权限的防火墙规则:

    gcloud compute firewall-rules delete allow-adkrb-from-serverless-to-dc --project=vpc-project-id
    

    vpc-project-id 替换为在其中定义了 VPC 的项目的 ID。如果您使用了共享 VPC,则使用 VPC 宿主项目的 ID;否则,请使用网域项目的 ID。

还原 Active Directory 更改

  1. 使用 RDP 客户端登录对 Active Directory 域拥有管理员权限的机器。
  2. 在“Active Directory 用户和计算机”MMC 管理单元中,转到 Projects 组织单元。
  3. 删除 register-computer Active Directory 用户账号。
  4. 删除您为测试自动域名加入功能而创建的组织单元。

后续步骤