Convert-PimToPrivate
Convert a public PIM Manager environment to private with one command
Part of the PIM Manager release - not a standalone download; it runs via the product's own install command or the updater.
Purpose
Converts a public (external) PIM Manager environment to private (internal-only) in one command. It runs the conversion guide's steps in order by calling the existing setup scripts (safety copy, private registry, remove and redeploy or rebuild, verify from inside the network, registry public access off, optional custom name, optional private SQL with its public access off), checks each step before the next, records progress per tenant and resource group so -Resume continues after a stop or a failure, and stops with exit code 10 where your network team must act. Data is kept. It only prints the plan unless -Apply is given.
When to run it
Once, to move a public PIM Manager environment to private, in a maintenance window of about 1-2 hours (the PIM Manager and the engine are unavailable from the removal until the redeploy completes; active privileged access stays active). Read network-options.md first. Run it from the PIM Manager release package folder (Pro / trial: the signed package Install-Invardia downloaded for your installation; Community: the public repository at the release tag), on the machine that ran the original install when possible (its deploy profile holds the install's parameters). It stops at two points: when -SkipPeering is given (the hub owner creates the hub side of the peering) and before any public endpoint is closed (verify from inside the network); resume with -Resume -Apply and -HubSideDone or -ConfirmedFromInside.
Who may run it
| Kind | Role | Scope | Why |
|---|---|---|---|
| azureRbac | Owner, or Contributor + User Access Administrator | the PIM subscription | The steps it runs remove and recreate the Container Apps environment, the PIM Manager and the jobs, upgrade the registry and add private endpoints, and grant the new managed identities their Azure roles (AcrPull, Reader, Contributor for the updater). |
| azureRbac | Network Contributor | the hub VNet (optional) | Only when this run creates the peering and links the private DNS zone to the hub. With -SkipPeering the hub owner does it with the script New-PimHubPrepareScript.ps1 writes, and this run needs no right on the hub. |
| entraRole | Privileged Role Administrator | tenant | The redeploy grants the new identities their Microsoft Graph application permissions and adds them to the role-assignable SQL admin group. |
| entraRole | Application Administrator | tenant | Sign-in (Easy Auth) is attached to the new private address: the existing sign-in app registration is reused and its reply address moved. |
| other | One REST session for -TenantId: the Invardia Support app session for that tenant, or your own browser sign-in | the target tenant + subscription | Every step runs in this process and reuses the one session; a session of another tenant is refused. No Azure CLI, no PowerShell modules. |
What it changes
| Where | Action | What | Permission / role | Scope | Why | Undo |
|---|---|---|---|---|---|---|
| Local machine | create | the conversion state %LOCALAPPDATA%\pim\convert\<tenant>-<resource group>.json (parameters without secrets, the completed steps, the restore point) and the safety-copy capture folder of the same name | the current Windows user | So -Resume continues after a stop or a failure, and so the live app definitions are kept before anything is removed. | Delete the file and the folder after the conversion is complete. | |
| Azure (the PIM resource group) | update | the container registry: Premium, a private endpoint, the privatelink.azurecr.io zone and a build pool (New-PimHostingPrerequisites.ps1) | the existing registry and VNet | A private environment pulls images and builds updates over the private endpoint. | The registry stays Premium (never downgraded); delete the private endpoint and the build pool in the portal if you go back to public. | |
| Azure (the PIM resource group) | remove | the Container Apps jobs, the PIM Manager app and the Container Apps environment, and the role assignments of their system identities (Remove-PimContainerStack.ps1; route Redeploy) | the resource group given | The internal/external setting of a Container Apps environment cannot be changed. | The next step recreates them; to go back to public, run Invoke-PimDeployAll.ps1 with the original deploy profile and -Apply. | |
| Azure (the PIM resource group) | create | the internal-only Container Apps environment, the PIM Manager, the engine, bootstrap and updater jobs, the peering to the hub and the private DNS zone for the new address (Invoke-PimDeployAll.ps1 -Exposure internal, or Rebuild-PimEnvInternal.ps1 on route Rebuild) | the resource group given (the peering: the PIM VNet and, with the right, the hub VNet) | The private environment, on the same subnet, SQL database and registry. | Rebuild-PimEnvExternal.ps1 -Apply converts back to public (the address changes again). | |
| Microsoft Entra ID | grant | the new managed identities' Microsoft Graph application permissions, Azure roles and database users | the engine and PIM Manager permission sets of Invoke-PimDeployAll.ps1 (see its documentation page) | the tenant / the PIM resource group / the PIM database | Recreated apps get new managed identities; the grants of the old ones no longer match. | Removed with the identities when the stack is removed again. |
| Azure (the PIM resource group) | update | optional: a custom host name with your certificate and its DNS record (Set-PimManagerCustomHost.ps1, with -HostName) | the PIM Manager app and an existing private DNS zone | One stable address that survives future rebuilds. | Remove the custom domain from the app and the record from the zone. | |
| Azure (the PIM resource group) | create | optional: the SQL private endpoint and the privatelink.database.windows.net zone (New-PimHostingPrerequisites.ps1 -SqlPrivateEndpoint, with -SqlPrivate), then one deploy that saves the private values in the deploy profile | the SQL server and the PIM VNet | Step 7 of the guide, done last, after the private PIM Manager is verified from inside. | Delete the SQL private endpoint (turn the server's public network access back on first). | |
| Azure (the PIM resource group) | update | the container registry's public network access OFF, after the check from inside (route Redeploy; the same change as Rebuild-PimEnvInternal.ps1 -LockRegistry on route Rebuild), read back. Refused unless the registry is Premium with an Approved private endpoint, the build pool is Succeeded in the VNet and the updater job carries PIM_ACR_AGENT_POOL | the existing registry | A private environment pulls images and builds updates over the private endpoint and the build pool; the public endpoint is no longer needed. | Turn the registry's public network access back on (portal). | |
| Azure (the PIM resource group) | update | optional, the very last change: the SQL server's public network access OFF (Set-PimSqlPublicAccess.ps1 -Disable, with -SqlPrivate), refused unless the server has an Approved private endpoint | the PIM SQL server | Step 7 of the guide: the database is reached through its private endpoint only. | Set-PimSqlPublicAccess.ps1 -Enable -Apply. |
What it only reads
- the deploy profile and the conversion state on this machine
- the subscription (visible, and in -TenantId)
- the Container Apps environment and the PIM Manager (exposure, static IP, address)
- the SQL database's point-in-time restore window
- the registry (SKU, public access, private endpoint approval), its build pool and the updater job's PIM_ACR_AGENT_POOL (the registry lock)
- whether this machine reaches the PIM Manager's private address (name resolution and TCP 443 only)
Parameters
| Parameter | Required | Default | What it does |
|---|---|---|---|
| -TenantId | yes | The PIM tenant. The REST session is pinned to it; a session or subscription of another tenant is refused. | |
| -SubscriptionId | yes | The PIM subscription. | |
| -ResourceGroup | yes | The PIM resource group (the conversion state is kept per tenant and resource group). | |
| -Route | no | Redeploy | Redeploy (guide Route B, default: remove the Container Apps stack and deploy it again internal-only from the install's parameters; grants everything the new identities need in one session) or Rebuild (guide Route A: capture, recreate and restore the live apps; keeps hand-made app changes, Windows only, the database users need a certificate identity afterwards). |
| -DeployProfilePath | no | %LOCALAPPDATA%\pim\deploy-profiles\<tenant>-<resource group>.json | The original install's saved parameters (written by Invoke-PimDeployAll.ps1 -Apply), or the file Invardia's wizard regenerated from your install answers. Values given on the command line win. |
| -Tag | no | the profile's PrereqToken, else 'pim' | A short label: the hosting prerequisites token and the capture file names. |
| -Location | no | the deploy profile | The Azure region of the environment. |
| -VnetName | no | the deploy profile | The existing PIM VNet. |
| -VnetResourceGroup | no | -ResourceGroup | The VNet's resource group. This command supports the VNet in the PIM resource group only (otherwise follow the guide's manual steps). |
| -SubnetName | no | the deploy profile | The existing Container Apps subnet. |
| -VnetAddressPrefix | no | the deploy profile | The existing VNet range (the prerequisites script never invents an address plan). |
| -SubnetAddressPrefix | no | the deploy profile | The existing Container Apps subnet range. |
| -AcrName | no | the deploy profile | The existing container registry. |
| -LogAnalyticsName | no | the deploy profile | The existing Log Analytics workspace. |
| -SqlServerFqdn | no | the deploy profile | The existing SQL server, e.g. <server>.database.windows.net. |
| -SqlDatabase | no | PimPlatform | The PIM database. |
| -EnvName | no | cae-pim | The Container Apps environment. |
| -ManagerApp | no | ca-pim-manager | The PIM Manager app. |
| -PrivateEndpointSubnetName | no | pim-endpoints | The private-endpoint subnet inside the PIM VNet (found or created). |
| -PrivateEndpointSubnetAddressPrefix | no | the deploy profile | A free range for that subnet inside the PIM VNet, e.g. 10.50.1.0/26. Required. |
| -AcrAgentPoolName | no | pimbuild | The registry build pool (private builds; the updater job gets PIM_ACR_AGENT_POOL). |
| -HubVnetId | no | The hub VNet resource id. Route Redeploy peers to it and links the private DNS zone; route Rebuild links the zone to each one given. Without it only the PIM VNet resolves the PIM Manager. | |
| -SkipPeering | no | false | The hub owner creates the hub side of the peering. The run STOPS at step 1 (exit 10) and prints the New-PimHubPrepareScript.ps1 command that writes the hub owner's script. |
| -DeployPrincipalObjectId | no | Passed to New-PimHubPrepareScript.ps1: the object id of whoever runs the conversion, so the hub owner's script grants it its rights on the hub. | |
| -PrivateDnsResourceGroup | no | the PIM resource group | Where the private DNS zones go (same subscription). |
| -SkipPrivateDns | no | false | Route Redeploy: do not create the private DNS zone for the new address (your own DNS answers for it). |
| -EasyAuthAllowedPrincipals | no | Who may sign in to the PIM Manager (groups / users). Default: the existing assignments are kept. | |
| -EasyAuthAllowAllTenantUsers | no | false | Every member account in the tenant may sign in (never guests). |
| -HostName | no | Optional stable custom name for the PIM Manager (step 6), e.g. pim.contoso.local. Needs your certificate. | |
| -KeyVaultName | no | With -HostName: the Key Vault holding the certificate. | |
| -KeyVaultCertName | no | With -HostName: the certificate's name in that Key Vault. | |
| -PfxPath | no | With -HostName: a PFX file instead of Key Vault. | |
| -PfxPassword | no | The PFX password (secure string; never saved in the state, pass it again on -Resume). | |
| -HostDns | no | Auto | With -HostName: Auto, PrivateDnsZone, AdDns (prints the record for you to add) or None. |
| -HostDnsResourceGroup | no | -PrivateDnsResourceGroup | With -HostName: the resource group of your existing private DNS zone for that name. |
| -SqlPrivate | no | false | Step 7, last: add the SQL private endpoint, save the private values in the deploy profile, then turn the SQL server's public network access off (Set-PimSqlPublicAccess.ps1; refused unless its private endpoint is Approved). Can be added later with -Resume -Apply -SqlPrivate. |
| -HubSideDone | no | false | On -Resume after stop point 1: the hub owner has run the script. |
| -ConfirmedFromInside | no | false | On -Resume after stop point 2: the private PIM Manager was verified from inside the network (Confirm-PimInstall.ps1 run there). |
| -Reporter | no | Optional scriptblock called with one event per step: { step = { id; title }; state = started|ok|failed|waiting|skipped; message }. | |
| -InvardiaInstallToken | no | Optional: posts each step to Invardia's tracked installation (best effort; never fails the run). | |
| -Resume | no | false | Continue the recorded conversion after its last completed step (the first run's parameters fill everything not given again). |
| -Apply | no | false | Run the steps. Without it (and always with -WhatIf) the script prints the full plan with each child command, signs in to nothing and changes nothing. |
Preview with -WhatIf
Prints the resolved parameters (from the deploy profile and the command line), anything missing, and every step in the guide's order with the exact child command it would run (New-PimHubPrepareScript.ps1 for the hub owner, the capture, New-PimHostingPrerequisites.ps1, Remove-PimContainerStack.ps1, Invoke-PimDeployAll.ps1, Confirm-PimInstall.ps1, the registry lock with its refusal conditions, Set-PimManagerCustomHost.ps1, Set-PimSqlPublicAccess.ps1 -Disable), the two stop points, and 'PLAN ONLY -- nothing was signed in to and nothing was changed'. -WhatIf wins over -Apply.
Undo
Before -Apply nothing changes. After a stop or a failure: -Resume -Apply continues, or the printed rollback applies (route Redeploy: Invoke-PimDeployAll.ps1 with the original profile brings the public environment back; route Rebuild: Rebuild-PimEnvExternal.ps1 -Apply). The data is never touched; the point-in-time restore point is recorded in the state file.
Network
It connects to: login.microsoftonline.com (sign-in), management.azure.com (Azure Resource Manager), graph.microsoft.com (the steps that grant the new identities), <server>.database.windows.net:1433 (the steps that write database users and the profile deploy), the PIM Manager's private address on TCP 443 (the inside check), invardia.com (only with -InvardiaInstallToken)
How it runs
Part of the PIM Manager release - not a standalone download; it runs via the product's own install command or the updater.
Release 3.0.70
Every script, identity and permission for your security review: PIM Manager