#Requires -Version 5.1 # PIM Manager 3.0.70 -- Initialize-PimHybridWorkerAd.ps1, standalone (built by tools/setup/Build-PimSupportScripts.ps1; helpers inlined: ..\setup\_pimscriptdoc.ps1) <# .SYNOPSIS §80.2 PIMHYBRIDWRK -- the Active Directory half of the hybrid worker: its gMSA identities, the rights they need, the servers GPO, and (optionally) an offline domain-join blob for the worker VM. .DESCRIPTION Prepares Active Directory for the PIM for Active Directory hybrid worker: its group managed service accounts, their least-privilege rights, the servers GPO and, for an Azure VM, the offline domain-join blob. Run on a domain controller, or on any domain-joined host, as an account with rights to create gMSAs, groups, GPOs and OU permissions. No ActiveDirectory PowerShell module: directory reads/writes are LDAP via .NET (System.DirectoryServices); dsacls.exe sets the OU rights. Two in-box modules remain, each behind one rare step (REQ 100.42, both under the owner's exception of 2026-10-09 for on-prem AD / GroupPolicy on the hybrid worker): GroupPolicy only to CREATE the servers GPO the first time, and Kds only behind the opt-in -CreateKdsRootKey. Every step is read-before-write and idempotent; -WhatIf prints the plan and changes nothing. IDENTITY DESIGN (operator 2026-09-30 -- the pattern the domain's other automation identities already follow): every identity is THREE objects in -GmsaOu the gMSA, named gMSA--L-T -PermissionGroup the gMSA is its only member; EVERY right is granted to this group, never to the account -PrincipalsAllowedAccess the computers allowed to retrieve the gMSA's password (the worker VM) and ONE identity per privilege tier: -GmsaName (default gMSA-PIM-L1-T0) AD groups + just-in-time membership + admin accounts. Tier 0: protected groups (Domain / Enterprise / Schema Admins nesting) are reached through AdminSDHolder. -ServerGmsaName (e.g. gMSA-PIM-L2-T1) server onboarding: its PermissionGroup is put into the servers' local Administrators by the -ServerOu GPO, and the worker sets each server's local Administrators as it. 1. KDS root key -- required for any gMSA. Refused when missing unless -CreateKdsRootKey (a forest-wide object). 2. Worker computer -- -ProvisionOdj: `djoin /provision` creates the computer account in -ComputerOu and prints the one-time join blob between the markers ODJ-BLOB-BEGIN / ODJ-BLOB-END. 3. Identities -- the three objects above, for -GmsaName and (when given) -ServerGmsaName. AES256 only. 4. Rights -- on -PermissionGroup, least privilege per OU: -GroupsOu create groups; write member / displayName / description on its groups -AllowGroupCleanup: also delete group objects in -GroupsOu -- needed only for the reviewed clean-up of old PIM groups (a SuperAdmin approves the exact list in PIM Manager; without this right an approved deletion is reported as refused). -AdminAccountsOu create users; full control of the user objects BELOW that OU -GrantProtectedGroupMembership: write 'member' on AdminSDHolder (adminCount=1 groups: SDProp replaces their ACL hourly, so an OU grant never reaches them). ⚠️ Whoever controls that gMSA is then TIER 0. Treat the worker VM as a DC. 5. Servers GPO -- -ServerOu: a GPO (-ServerAdminGpoName) with Restricted Groups "member of": the server identity's PermissionGroup joins BUILTIN\Administrators on every computer below the OU -- ADDED, nothing removed. Linked to each -ServerOu. What it deliberately does NOT do: * enable the AD Privileged Access Management feature -- irreversible for the forest. It is DETECTED and reported. * put an identity into a PIM just-in-time group: those groups' members are the people with an active elevation, and the PIM-for-AD sync removes anyone else (it removed the first worker gMSA from the shared server-admins group). * grant anything on protected USER accounts (adminCount=1). .EXAMPLE .\Initialize-PimHybridWorkerAd.ps1 -WorkerComputerName PIMHYBRIDWRK -ComputerOu 'OU=Servers,DC=corp,DC=local' ` -GmsaOu 'OU=Automation,OU=Service Accounts,DC=corp,DC=local' -GroupsOu 'OU=PIM Groups,DC=corp,DC=local' ` -AdminAccountsOu 'OU=Admin Accounts,DC=corp,DC=local' -GrantProtectedGroupMembership ` -ServerGmsaName gMSA-PIM-L2-T1 -ServerOu 'OU=Servers,DC=corp,DC=local' -WhatIf .NOTES Requirements: PowerShell: Windows PowerShell 5.1 (powershell.exe) on a domain controller or a domain-joined Windows server -- one of PIM's three exceptions to PowerShell 7. Why: it uses the Windows GroupPolicy module (to create the servers GPO) and Add-KdsRootKey (with -CreateKdsRootKey), which are Windows PowerShell modules. Role: Domain Admins (Active Directory); Enterprise Admins only with -CreateKdsRootKey. No Microsoft Entra or Azure role. Hosts: the domain controllers only (LDAP, SYSVOL); no internet. PERMISSIONS AND CHANGES (from Initialize-PimHybridWorkerAd.ps1 manifest, PIM Manager 3.0.70; full page: https://invardia.com/docs/pim/scripts/Initialize-PimHybridWorkerAd/) The person running it needs: - Domain Admins [other, the domain] -- creates gMSAs, groups and the servers GPO, and delegates OU rights (dsacls) - Enterprise Admins (only with -CreateKdsRootKey) [other, the forest] -- creates the forest's KDS root key What it creates, changes or grants: - create per identity: the gMSA (AES256), -PermissionGroup (the gMSA its only member) and -PrincipalsAllowedAccess (the worker computer) (Active Directory (-GmsaOu)) -- AD is written only by gMSAs, one per privilege tier; every right goes to the PermissionGroup Undo: delete the gMSAs and their two groups - update ACEs for -PermissionGroup: -GroupsOu read + create groups + write member/displayName/description (+ delete groups only with -AllowGroupCleanup); each -AdminAccountsOu create users + full control below; AdminSDHolder write member only with -GrantProtectedGroupMembership (Tier 0) (Active Directory OUs) -- least privilege per OU Undo: dsacls /R \-PermissionGroup - create a GPO (Restricted Groups: -PermissionGroup member of BUILTIN\Administrators, adds only) linked to each -ServerOu (Group Policy (only with -ServerGmsaName + -ServerOu)) -- server onboarding by the Tier-1 identity Undo: unlink and delete the GPO - create the worker's computer account in -ComputerOu and the offline domain-join blob (printed) (Active Directory (-ProvisionOdj, Azure VM)) -- joins the Azure VM without line of sight; an Azure Arc server is already joined Undo: delete the computer account - create a KDS root key (Add-KdsRootKey), usable about 10 hours later (the forest (-CreateKdsRootKey)) -- no gMSA exists without one Undo: none (forest-wide; leave it) -WhatIf: Prints every object, right, GPO setting and link it would create; creates nothing. Undo: Unlink and delete the servers GPO, remove the ACEs (dsacls /R \-PermissionGroup) on -GroupsOu, each -AdminAccountsOu and AdminSDHolder, then delete the gMSAs, their groups and (for an Azure VM) the computer account. .LINK https://invardia.com/docs/pim/scripts/Initialize-PimHybridWorkerAd/ #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)][ValidatePattern('^[A-Za-z0-9-]{1,15}$')][string]$WorkerComputerName, [Parameter(Mandatory)][string]$ComputerOu, [ValidatePattern('^[A-Za-z0-9-]{1,15}$')][string]$GmsaName = 'gMSA-PIM-L1-T0', [Parameter(Mandatory)][string]$GmsaOu, [Parameter(Mandatory)][string]$GroupsOu, [string[]]$AdminAccountsOu = @(), [switch]$GrantProtectedGroupMembership, # PIM 100.123: the reviewed clean-up of old PIM groups -- the worker may DELETE group objects in -GroupsOu (opt-in) [switch]$AllowGroupCleanup, # server onboarding, tier-split: its own identity + the GPO that makes its PermissionGroup local admin on -ServerOu [ValidatePattern('^$|^[A-Za-z0-9-]{1,15}$')][string]$ServerGmsaName = '', [string[]]$ServerOu = @(), [string]$ServerAdminGpoName = '', [string]$UsedBy = 'PIM Manager hybrid worker', [switch]$ProvisionOdj, [switch]$ReuseComputer, [switch]$CreateKdsRootKey, [switch]$TriggerSdProp ) $ErrorActionPreference = 'Stop' # 12.7 run frame: "