Skip to content
InvardiaInvardia
Why InvardiaProductsFeaturesPricingCommunity
Docs
All documentation
Product documentationPIM ManagerSecurityInsight
SettingsPIM Manager settingsSecurityInsight settingsEntra Policy Suite settings
ScriptsPIM Manager scriptsSecurityInsight scriptsEntra Policy Suite scriptsInvardia scripts
Error codesPIM Manager error codesSecurityInsight error codes
API and MCPPIM Manager APIPIM Manager MCP toolsSecurityInsight APISecurityInsight MCP tools
SecurityPIM Manager security packSecurityInsight security packEntra Policy Suite security pack
Network and designPIM Manager network guidesPIM Manager command wizardNetwork egressDesign your installationCalculate your cost
SupportSetup scriptsRemote support access
Search the docs
SupportAboutContactBook a demoCustomer portalDesign your installationFree Pro trial

PIM Manager scripts

Deploy-PimHybridWorker

PIM for Active Directory: deploy the hybrid worker (Azure VM or on-premises with Azure Arc)

Purpose

Deploys the PIM for Active Directory hybrid worker in the right order, step by step, and remembers where it got to so it can stop for the Active Directory step and continue later.

When to run it

Once per hybrid worker, when you start using PIM for Active Directory: -Target Azure builds a new Azure VM for it, -Target Arc uses your own on-premises Windows server that is already Azure Arc-enabled and domain-joined. Run it first without -Apply to see the plan, then with -Apply; it stops for the Active Directory step (and, when a new KDS root key was created, for the ~10 hours that key needs) and continues with -Resume -Apply.

Who may run it

KindRoleScopeWhy
azureRbacContributor (or Owner)-Target Azure: the subscription or the worker's resource group, and Network Contributor on the networks it peers with; -Target Arc: Reader on the Arc machine and the Azure Connected Machine Resource Administrator role (run-command) on itcreates the worker's network and VM (Azure), reads the Arc machine and runs the install on it through run-command
azureRbacUser Access Administrator (or Role Based Access Control Administrator)the source-store containergrants the worker's identity Storage Blob Data Reader on the container that holds the PIM code
entraRolePrivileged Role Administratorthe tenantgrants the worker's identity the Graph application roles Group.Read.All, User.Read.All and PrivilegedAssignmentSchedule.Read.AzureADGroup (read only)
otherMicrosoft Entra admin of the PIM SQL server (or a member of its admin group)the PIM databasecreates the worker's contained database user (db_datareader + db_datawriter). Run the script in Windows PowerShell 5.1 for this step.
otherActive Directory: an account that may create gMSAs, groups, GPOs and OU permissions (on a domain controller)the domain -- the AD step only, which this script PRINTS and the AD administrator runsthe worker writes AD only as group managed service accounts, which the AD step creates with their least-privilege rights

What it changes

WhereActionWhatPermission / roleScopeWhyUndo
Azure (-Target Azure)createresource group, VNet + subnet, deny-all-inbound NSG, NAT gateway egress, peerings to -PeerVnetId, the worker VM with a system-assigned identity and no public IP, a SQL VNet rule (New-PimHybridWorkerInfra.ps1)the worker's own isolated network and machinedelete the resource group and the peerings on the remote networks
PIM SQL server (-Target Arc with -SqlAllowedPublicIp)createone firewall rule per on-premises egress addresslets the on-premises worker reach a public SQL endpoint; not needed with a private endpointdelete the pimhybridwrk-arc-* firewall rules
the worker machineupdateInstall-PimHybridWorker.ps1 through run-command: domain join (Azure only), PowerShell 7, the gMSAs installed and tested, log on as a batch job for them, C:\PIM locked down, the PIM code, six scheduled tasks; on Arc the gMSAs join the local group 'Hybrid agent extension applications'the worker itselfdelete the scheduled tasks 'PIM Hybrid *' and C:\PIM; remove the gMSAs from the local group
Microsoft Graphgrantthe worker identity's application rolesGroup.Read.All, User.Read.All, PrivilegedAssignmentSchedule.Read.AzureADGroup (+ Mail.Send with -GrantMailSend)the tenantthe worker reads the PIM groups and who is active in them; it never writes to Entraremove the app role assignments from the identity's enterprise application
Azure RBACgrantthe worker identityStorage Blob Data Readerthe source-store container (-SourceContainerId)the worker updates itself with its identity -- no SAS, no PATremove the role assignment
PIM databasegranta contained user (-SqlUserName) created from the identitydb_datareader, db_datawriter (never db_ddladmin)the PIM database (-SqlDatabase)the worker reads its work and writes its state and auditDROP USER [<name>]
this computercreatethe state file $env:LOCALAPPDATA\pim\hybrid\deploy-<target>-<name>.json (no secrets)-Resume continues where the run stoppeddelete the file

What it only reads

  • the subscription (its tenant, checked against -TenantId) and, for -Target Arc, the Arc machine (status, OS, identity)
  • the state file of an earlier run (-Resume)
  • the run-command result (state, exit code, output) of each install phase

Parameters

ParameterRequiredDefaultWhat it does
-TargetyesAzure (a new Azure VM) or Arc (your own Azure Arc-enabled on-premises server). Not needed with -Resume.
-SubscriptionIdyesThe subscription of the worker (Azure) or of the Arc machine.
-TenantIdyesThe tenant. The REST session is pinned to it and every step refuses another.
-ResourceGroupnorg-pimhybridwrk-Target Azure: the worker's resource group.
-Locationnowesteurope-Target Azure: the region.
-VmNamenoPIMHYBRIDWRK-Target Azure: the VM and computer name (max 15 characters).
-VmSizenoStandard_B2s-Target Azure: the VM size.
-VnetNamenovnet-pimhybridwrk-Target Azure: the worker's VNet.
-AddressPrefixno10.221.16.0/24-Target Azure: the VNet address space.
-SubnetPrefixno10.221.16.0/27-Target Azure: the worker subnet.
-PeerVnetIdno-Target Azure (required there): the VNet resource ids to peer with -- the network with the domain controllers, optionally the PIM environment's.
-DnsServersno-Target Azure (required there): the domain controllers' addresses (the VNet DNS).
-EgressnoNatGateway-Target Azure: NatGateway, or None when your network already routes outbound. Never a public IP on the VM.
-UseRemoteGatewaysnofalse-Target Azure: the DCs are reached through the hub's VPN / ExpressRoute gateway (with -GatewayVnetId). Passed to the infra step.
-GatewayVnetIdno-Target Azure: the hub VNet with the gateway (one of -PeerVnetId).
-AllowForwardedTrafficnofalse-Target Azure: the worker-side peering(s) accept traffic the hub forwards.
-PrivateSqlDnsZoneIdnoA private-only PIM database: the existing privatelink.database.windows.net zone, linked to the worker VNet; the DCs' DNS forwarder is printed.
-PrivateDnsLinkVnetIdnoMore VNets to link the zone to (the DCs' VNet when they are Azure VMs; the DNS Private Resolver's VNet).
-CreatePrivateDnsZonenofalseCreate the standard privatelink.database.windows.net zone only when it is missing.
-PrivateDnsZoneResourceGroupnoWhere the standard zone lives, instead of -PrivateSqlDnsZoneId.
-PrivateSqlnofalsePrint the conditional forwarder for a private-only database (implied by the zone options).
-DnsForwarderIpnoThe address the printed forwarder points at (168.63.129.16 for DCs in Azure; a Private Resolver inbound endpoint for DCs on-premises).
-ArcMachineResourceIdno-Target Arc (required there): /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.HybridCompute/machines/<server>.
-SqlAllowedPublicIpno-Target Arc with a public SQL endpoint: your on-premises egress address(es); one firewall rule each. Leave empty with a private endpoint.
-SqlServerIdyesThe PIM SQL server's resource id.
-SqlDatabasenoPimPlatformThe PIM database.
-SqlUserNamenoPIMHYBRIDWRKThe worker's contained database user. Name it per worker when you run more than one.
-SourceContainerIdyesThe resource id of the blob container with the PIM code (pim-src-<version>.tar.gz + channel.json).
-RingnoThe update ring this environment follows (or -Version).
-VersionnoPin a version instead of following a ring.
-GrantMailSendnofalseAlso grant Graph Mail.Send, so new AD admin accounts get their initial password by mail.
-PlanOnlynofalseInstall the worker in plan-only mode: every run plans and logs, nothing is written to AD until Configure is re-run without it.
-AdDomainyesThe domain's NetBIOS name (the gMSAs are DOMAIN\name).
-WorkerComputerNameno-VmName / the Arc machine nameThe worker's computer name in AD.
-ComputerOuyesThe OU of the worker's computer account (printed into the AD command).
-GmsaNamenogMSA-PIM-L1-T0The Tier-0 worker identity.
-GmsaOuyesThe OU for the gMSAs and their groups.
-GroupsOuyesThe OU where PIM for AD creates its groups.
-AdminAccountsOunoThe OU(s) of the AD admin accounts PIM creates.
-ServerGmsaNamenoThe separate Tier-1 identity for server onboarding (e.g. gMSA-PIM-L2-T1); needs -ServerOu.
-ServerOunoThe servers OU(s) whose local Administrators get the server identity (a GPO). Keep the worker itself out of it.
-GrantProtectedGroupMembershipnofalseLet the worker change the members of protected groups (AdminSDHolder) -- Tier 0.
-CreateKdsRootKeynofalseLet the AD step create the forest's KDS root key when there is none; the run then waits ~10 hours before Configure.
-AdServernoA specific domain controller for the worker's AD calls.
-ApplynofalseRun the steps. Without it the script prints the plan only.
-ResumenofalseContinue from the state file; every value given on the first run is remembered.
-StatePathnothe newest $env:LOCALAPPDATA\pim\hybrid\deploy-*.jsonThe state file to use.
-KdsRootKeyCreatedUtcnoWhen the AD step created a new KDS root key (it prints the time): Configure waits until it is ~10 hours old.
-OdjBlobno-Target Azure: the offline domain-join blob the AD step printed (never stored in the state file).
-OdjBlobFileno-Target Azure: a file holding that blob.
-PrintOnlynofalseDo not use run-command: write the self-contained install script for the server administrator to run locally.
-JoinRebootWaitSecondsno240-Target Azure: how long to wait for the reboot after the domain join.

Preview with -WhatIf

Prints the plan: every step in order with what it would create or grant and the exact Active Directory command, plus the state file it would use. Nothing is changed, nothing is called, no state file is written. -Apply runs it.

Undo

Remove-PimHybridWorker.ps1 removes it all (plan first, -Apply). By hand: -Target Azure: delete the worker's resource group and the peerings on the remote networks. Both targets: remove the worker identity's Graph app roles, its Storage Blob Data Reader assignment and its database user (DROP USER); on the server delete the 'PIM Hybrid *' scheduled tasks and C:\PIM; in AD delete the gMSAs and their groups (Initialize-PimHybridWorkerAd.ps1 created them) and the servers GPO.

Network

It connects to: management.azure.com (ARM), graph.microsoft.com, login.microsoftonline.com, the PIM SQL server (1433) for the grant step, nothing to the worker machine directly: the install reaches it through Azure run-command (outbound from the machine's agent)

Download and run

Run these lines in PowerShell: the first downloads the script into the current folder, the second runs it.

Invoke-WebRequest https://invardia.com/support/pim/Deploy-PimHybridWorker.ps1 -OutFile Deploy-PimHybridWorker.ps1
.\Deploy-PimHybridWorker.ps1 -Target <Target> -SubscriptionId <SubscriptionId> -TenantId <TenantId> -SqlServerId <SqlServerId> -SourceContainerId <SourceContainerId> -AdDomain <AdDomain> -ComputerOu <ComputerOu> -GmsaOu <GmsaOu> -GroupsOu <GroupsOu>

To check the download first, compare its SHA-256 with the published one:

SHA-256 0af9f1e2f40032dc5db98114ca974c68588b8bac90bf82e4de4b124ee2e73c30

Checksums: SHA256SUMS.txt · Version 3.0.70

Before you run it, compare the file's SHA-256 with its line in SHA256SUMS.txt.

Every parameter: Get-Help .\Deploy-PimHybridWorker.ps1 -Full · Source: Deploy-PimHybridWorker.ps1

Every script, identity and permission for your security review: PIM Manager

InvardiaInvardia

See the risk. Control the access.

Products

PIM ManagerSecurityInsightEntra Policy SuiteAll featuresPricingFree 60-day Pro trialBook a demoWhy Invardia

Docs

DocumentationSearch the docsPIM Manager settingsSecurityInsight settingsPIM network guidesCommand wizardNetwork egressPIM Manager design configuratorSecurityInsight design configuratorDesign your installationCalculate your cost

Company

AboutContactCustomer portalSupportHow support worksHow updates reach youSupport in numbersSetup scriptsRemote support accessContact: info@invardia.com

Legal

Terms of saleLicence termsData processingPrivacyCookiesCompany information
© 2026 Invardia – a brand of 2LINKIT, founded and owned by Morten Knudsen · Strandvejen 21A, 6000 Kolding, Denmark · VAT DK39208032 · Contact: info@invardia.com