Security review pack
PIM Manager -- Security review pack
| Product | PIM Manager |
|---|---|
| Version | 3.0.70 |
| Date | |
| Published at | invardia.com/products/pim-manager/security/ |
| Questions | info@invardia.com |
This pack is for the CISO and the security team who must approve PIM Manager before it is installed. It describes the product and this version, not one customer's environment. It sets out PIM Manager's security design: architecture, identities and every permission, data, vendor access, supply chain, change control, the threat model, the compliance mapping, exit and the scripts a person runs.
1. Architecture
PIM Manager keeps privileged access in Microsoft Entra ID and Azure in line with a desired state that your administrators manage. It runs entirely in your own Azure subscription, in a resource group you choose (default name rg-pim). Invardia does not host the product, your data or its runtime.
Components (all in your subscription)
- Engine job
ca-pim-tick-- an Azure Container Apps job on a schedule. It reads the desired state from SQL and applies it to Entra ID, PIM for Groups, Azure RBAC, Intune and Defender XDR role management through REST calls with its managed identity. - Manager
ca-pim-manager-- the web GUI (Container App). Administrators sign in with Entra ID through the product's sign-in front (OpenID Connect code flow with PKCE, no client secret); the Manager itself listens only on the container's loopback address, behind it. Its Microsoft Graph rights are read-only; changes are queued in SQL and applied by the engine. - Updater job
ca-pim-update-- builds the new version from source inside your own container registry and rolls the Manager and jobs (chapter 6). - Azure SQL Database -- the desired state, settings, audit log and commit journal. Entra-only authentication. The installer creates it on the Standard tier, S0 at minimum (never Basic, never serverless), with a 250 GB maximum size; a higher tier you set is kept, and a
pim-sql-tier-pintag stops the product changing its tier. - Azure Container Registry -- holds the images built in your subscription (Premium for private network setups, Basic otherwise).
- Log Analytics workspace -- receives the Container Apps logs.
- Key Vault -- only when a feature needs a secret (SMTP relay password, emergency passphrase, MSP signing key). A plain install creates none.
- Optional: PIM Activator browser extension with its own app registration (chapter 2), the access-request (RFA) broker
ca-pim-rfa, an MCP endpoint on the Manager, and a hybrid worker VM for on-premises Active Directory. - MSP installs add a managing-tenant side (a signed baseline bundle published to storage, pulled by each managed tenant).
What Invardia hosts
- invardia.com: the download of standalone setup scripts, licences, the optional update channel for Pro, and the receiver for the telemetry uplink (chapter 4). None of these is needed for the product to keep running; the engine runs without any call to Invardia.
- Invardia never hosts your directory data, your SQL database or your runtime.
Network exposure options
- Default: the Container Apps environment is external. A new Manager is created closed (a deny-all ingress rule) and is opened only after Entra sign-in is configured and verified. Worker jobs have no ingress at all.
- IP-restricted: ingress IP allow-rules can be added; the update path keeps them.
- Private: an internal-only Container Apps environment and a SQL private endpoint with public network access disabled are supported install options (opt-in).
- SQL: Entra-only authentication. Setup sets the SQL server's minimum TLS version to 1.2. A public install uses the Azure rule "Allow Azure services"; private networking (a VNet rule or a private endpoint) is a setup option.
Data flow summary
- Engine and Manager -> Microsoft Graph / Azure Resource Manager / Defender / Power BI / Exchange Online REST: HTTPS, managed identity tokens.
- Engine and Manager -> Azure SQL: TLS (Encrypt=True, certificate validated), managed identity.
- Administrators' browsers -> Manager: HTTPS, Entra sign-in.
- Product -> invardia.com: HTTPS, outbound only (telemetry, licence, optional updates). Nothing from Invardia connects in to your environment.
2. Identities
Every identity the product creates or uses, with its purpose and lifetime. Runtime identities are managed identities -- no secret or certificate to steal or rotate. The default resource names are shown; an installation may prefix them.
| Identity | Kind | Purpose | Credential | Lifetime |
|---|---|---|---|---|
| ca-pim-tick (engine) | System-assigned managed identity of the engine job | Reads the tenant and applies the desired state | None (managed identity) | Lives as long as the job |
| ca-pim-manager (Manager) | System-assigned managed identity of the Manager app | Reads the tenant for the GUI, writes SQL, starts the engine on Run now | None (managed identity) | Lives as long as the app |
| ca-pim-update (updater) | System-assigned managed identity of the update job | Builds the new version in your registry and rolls the apps; applies schema; keeps the database job identity in the SQL admin group (PIM for Groups) | None (managed identity) | Lives as long as the job |
| id-pim-<token> | User-assigned managed identity | Pulls images from your registry; attached to the Manager and jobs. No database access | None (managed identity) | Kept until the resource group is removed |
| id-pim-sql-<token> | User-assigned managed identity (private SQL only) | SQL administrator for the in-cloud schema bootstrap job | None (managed identity) | Kept until removed |
| Downlink / baseline-publish / RFA broker jobs | System-assigned managed identities (MSP and access-request options only) | Pull or publish the MSP bundle; serve access requests | None (managed identity) | Lives as long as the job/app |
| Manager sign-in app registration | App registration (sign-in front) | Entra sign-in to the Manager (OpenID Connect code flow + PKCE, 8 h fixed session); app assignment required | None -- the web app's managed identity is a federated credential on the registration (no secret, no certificate) | Until the Manager is removed |
| Manager users group (members, no guests) | Dynamic security group (optional) | Lets all member accounts sign in, never guests | n/a | Until removed |
| Access-request API app registration | App registration (RFA option) | Token audience for the access-request broker; no API permissions | None | Until removed |
| Engine app registration (certificate) | App registration + service principal (classic deploy path only) | Engine identity for installs that do not run on managed identity | Self-signed certificate, 2 years, on the deploy host | Removed when the installation runs on managed identity |
| Deploy app registration | App registration (optional, unattended deploys) | Runs deploys without a person signed in | Certificate on the deploy host | Until removed |
| grp-pim-sql-admins | Role-assignable security group | The SQL server's Entra administrator. A new installation does not make the Invardia Support app a member (its standing database right is a read-only user, chapter 5). No runtime identity of the web app or the engine is a member; the updater is never a member: it has its own contained database user with schema rights only. People get in just-in-time through PIM for Groups | n/a | Until removed |
| PIM Activator app registration | App registration (optional) | The browser extension's sign-in; users activate their own eligible roles and groups | None (public client, PKCE) | Until removed |
| Mail sender | Shared mailbox + Exchange RBAC for Applications scope (optional) | Sends TAP codes, approvals and alerts from one mailbox | None (send right on that one mailbox) | Until removed |
| Invardia Support app | Multi-purpose vendor app registration created in YOUR tenant by Invardia's setup script | Setup and support by Invardia, with your consent (chapter 5) | Client secret (90 days for customers), held in Invardia's support Key Vault | Until you remove it |
| Hybrid worker gMSAs (optional) | Group managed service accounts in on-premises AD | Create/maintain admin accounts and groups in AD | Managed by AD | Until removed |
| Break-glass accounts | Your own emergency accounts (not created by the product) | Listed in Settings; the engine never removes, disables or revokes them | Yours | Yours |
3. Permissions with justification
Every permission the product grants or requires, per identity, read from the install and grant code of this version. Optional means the grant is made only when you choose that feature or switch. The engine needs broad write rights because managing privileged access is its job; chapter 8 explains the controls around that.
> The engine identity's Graph permissions are tier-0 equivalent: RoleManagement.ReadWrite.Directory can assign any directory role and AppRoleAssignment.ReadWrite.All can grant any application permission. The engine identity is monitored as a tier-0 asset, and the most privileged directory roles (Global Administrator, Privileged Role Administrator) are refused as engine targets.
Least-privilege choices made in code
- The Manager's Graph rights are read-only; writes are queued and applied by the engine.
- Mail.Send is never granted tenant-wide to the engine or Manager; mail uses Exchange RBAC for Applications scoped to ONE mailbox, and the mail setup removes a tenant-wide Mail.Send if it finds one.
- Exchange Administrator for mail setup is activated time-bound through PIM (default 4 hours), not assigned permanently.
- User Access Administrator at the tenant root is opt-in; the default is Reader.
- Workload identities may only be given Reader, User Access Administrator or Role Based Access Control Administrator by the reachability planner; Owner and Contributor are refused there.
- The baseline-publish job has no fixed SQL role: SELECT on named objects only, and db_owner / db_datawriter / db_ddladmin / db_datareader are revoked.
- Storage keys are disabled where the product creates storage; access is Azure RBAC.
- One identity per job in SQL: every component that uses the database has its own contained database user, mapped from its own managed identity. The image-pull identity has no database access, and the web app holds no db_ddladmin (from 2.4.631): it cannot change the schema.
- SQL admin group = the database job identity only: its standing member is the database job identity (id-pim-dbinit); people get in just-in-time through PIM for Groups. No runtime identity of the web app or the engine is a member, the updater is never a member, and a new installation does not make the Invardia Support app a member (chapter 5).
- One custom database role per component (pim_web, pim_engine, pim_updater, pim_asbuilt, pim_publish, pim_downlink, pim_hybrid), object- or schema-level, never db_owner. Grants change after a release ONLY through one certificate-signed procedure (pim.usp_ApplyAccess) under fixed rules: a pim_ role, SELECT / INSERT / UPDATE / DELETE / EXECUTE, PIMs own schemas, never itself, never a fixed role. Its certificate lives in the database, expires 2099-12-31 and has no private key (removed after signing); altering the procedure drops the signature. The updater may only EXECUTE it and is refused when it grants directly; the engine cannot run it (proven on a live installation). Every update applies schema and grants with the updaters own database user alone, so the SQL admin group may stay empty for years.
- The web app cannot change the engine: start-only rights on the named engine job (Jobs Operator), no registry push, no SQL admin.
Least privilege by component
- Access reviews use AccessReview.ReadWrite.All, the narrowest Graph permission that creates and completes reviews.
- Every component holds only its own custom database role (pim_web, pim_engine, pim_updater, pim_asbuilt, pim_publish, pim_downlink, pim_hybrid); per-component views separate the generic settings and rows tables. Rights change only through the certificate-signed access procedure.
- The updater holds Contributor on its own resource group only, and is a contained database user with schema rights only; it is never in the SQL admin group. In Microsoft Graph it holds three PIM-for-Groups permissions, GroupMember.Read.All and Application.Read.All (both read only) and Application.ReadWrite.OwnedBy (changes only the app registrations it owns), and nothing else (owner decisions 2026-11-05 and 2026-11-07): it makes the database job identity an active member of the SQL admin group -- a role-assignable group, through PIM for Groups, permanent where the group policy allows -- reads that membership back before the database job or the support job starts, and renews a time-limited membership before it ends. It holds no directory role; the permissions are tenant-wide in Microsoft Graph, and the updater's code uses them on the SQL admin group only.
- The optional deploy app registration holds its rights only for the length of an install.
- The standalone Grant-PimEnginePermissions script grants only the roles and scopes on the product's allow-list.
| Identity | Type | Permission | Scope | Why it is needed | What breaks without it | Optional |
|---|---|---|---|---|---|---|
| Engine (ca-pim-tick) | Graph application | Directory.Read.All | Tenant | Read users, groups, roles and directory objects to compare with the desired state | Everything -- the engine cannot read the tenant | No |
| Engine (ca-pim-tick) | Graph application | User.ReadWrite.All | Tenant | Create and maintain the dedicated admin accounts | Admin account lifecycle (create, update, disable) | No |
| Engine (ca-pim-tick) | Graph application | Group.ReadWrite.All | Tenant | Create and maintain PIM groups and their membership | Group-based delegation | No |
| Engine (ca-pim-tick) | Graph application | RoleManagement.ReadWrite.Directory | Tenant | Create role-assignable groups and assign directory roles to them | Role-assignable groups and Entra role delegation | No |
| Engine (ca-pim-tick) | Graph application | RoleManagement.Read.All | Tenant | Read role definitions and assignments | Role reporting and drift detection | No |
| Engine (ca-pim-tick) | Graph application | RoleEligibilitySchedule.ReadWrite.Directory | Tenant | Create eligible Entra role assignments | Eligible Entra role delegation | No |
| Engine (ca-pim-tick) | Graph application | RoleEligibilitySchedule.Remove.Directory | Tenant | Remove eligible Entra role assignments on revoke | Revoke of Entra role eligibility | No |
| Engine (ca-pim-tick) | Graph application | RoleAssignmentSchedule.ReadWrite.Directory | Tenant | Create active (time-bound) Entra role assignments | Active role assignments | No |
| Engine (ca-pim-tick) | Graph application | RoleAssignmentSchedule.Remove.Directory | Tenant | Remove active Entra role assignments on revoke | Revoke of active roles | No |
| Engine (ca-pim-tick) | Graph application | RoleManagementPolicy.Read.Directory | Tenant | Read Entra role PIM policies | Policy drift reporting | No |
| Engine (ca-pim-tick) | Graph application | RoleManagementPolicy.ReadWrite.Directory | Tenant | Apply Entra role PIM policies (approval, MFA, duration) | PIM policy management for Entra roles | No |
| Engine (ca-pim-tick) | Graph application | RoleManagementPolicy.Read.AzureADGroup | Tenant | Read PIM-for-Groups policies | Group policy reporting | No |
| Engine (ca-pim-tick) | Graph application | RoleManagementPolicy.ReadWrite.AzureADGroup | Tenant | Apply PIM-for-Groups policies | PIM policy management for groups | No |
| Engine (ca-pim-tick) | Graph application | PrivilegedAccess.ReadWrite.AzureADGroup | Tenant | Manage PIM for Groups | PIM-for-Groups delegation | No |
| Engine (ca-pim-tick) | Graph application | PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup | Tenant | Create eligible group memberships | Eligible group membership | No |
| Engine (ca-pim-tick) | Graph application | PrivilegedEligibilitySchedule.Remove.AzureADGroup | Tenant | Remove eligible group memberships on revoke | Revoke of group eligibility | No |
| Engine (ca-pim-tick) | Graph application | PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup | Tenant | Create active group memberships | Active group membership | No |
| Engine (ca-pim-tick) | Graph application | PrivilegedAssignmentSchedule.Remove.AzureADGroup | Tenant | Remove active group memberships on revoke | Revoke of group membership | No |
| Engine (ca-pim-tick) | Graph application | AdministrativeUnit.ReadWrite.All | Tenant | Create and use administrative units as delegation scopes | AU-scoped delegation | No |
| Engine (ca-pim-tick) | Graph application | AppRoleAssignment.ReadWrite.All | Tenant | Manage application role assignments (Entra app-role provider) | App-role delegation | No |
| Engine (ca-pim-tick) | Graph application | Application.Read.All | Tenant | Resolve applications and service principals | App-role provider, reporting | No |
| Engine (ca-pim-tick) | Graph application | UserAuthenticationMethod.ReadWrite.All | Tenant | Issue a Temporary Access Pass to a new admin account | Onboarding of new admin accounts (TAP) | No |
| Engine (ca-pim-tick) | Graph application | AccessReview.Read.All | Tenant | Read access reviews | Access review reporting | No |
| Engine (ca-pim-tick) | Graph application | AccessReview.ReadWrite.All | Tenant | Create and run access reviews (broader than needed; no narrower permission exists) | Access reviews | No |
| Engine (ca-pim-tick) | Graph application | RoleManagement.ReadWrite.Defender | Tenant (Defender XDR) | Manage Defender XDR (unified RBAC) roles | Defender XDR provider | No (used only when Defender is managed) |
| Engine (ca-pim-tick) | Graph application | DeviceManagementRBAC.ReadWrite.All | Tenant (Intune) | Manage Intune RBAC roles | Intune provider | No (used only when Intune is managed) |
| Engine (ca-pim-tick) | Graph application | Domain.Read.All | Tenant | Read verified domains for admin account naming | Admin naming | No |
| Engine (ca-pim-tick) | Graph application | Policy.Read.All | Tenant | Read authentication and authorization policies used in checks | Policy checks | No |
| Engine (ca-pim-tick) | Azure RBAC | Reader | Tenant root management group | Discovery of management groups and subscriptions; Azure RBAC reporting | Azure discovery and reporting | Default on; can be skipped |
| Engine (ca-pim-tick) | Azure RBAC | Reader | The hosting subscription (and optionally a management group) | Read Azure resources and role assignments | Azure reporting | Default on; can be skipped |
| Engine (ca-pim-tick) | Azure RBAC | User Access Administrator | Tenant root management group, or the delegated scopes | Write Azure role assignments and PIM for Azure resources | Azure RBAC delegation (read-only without it) | Yes (opt-in switch) |
| Engine (ca-pim-tick) | Azure RBAC | Reader | The ca-pim-tick job resource | Read its own execution status | Run status in the GUI | No |
| Engine (ca-pim-tick) | Azure RBAC | Storage Table Data Contributor | The access-request storage account | Store access-request state | Access requests (RFA) | Yes (RFA option) |
| Engine (ca-pim-tick) | Azure RBAC (custom role) | Microsoft.Storage/storageAccounts/read + write | The one MSP bundle storage account | Maintain the bundle store's network rules (MSP managing tenant, public-signed mode) | MSP bundle publication | Yes (MSP only) |
| Engine (ca-pim-tick) | SQL | Role pim_engine (read/write the pim schema, read the tenant registry); db_datareader, db_datawriter, db_ddladmin only until the second cut-over run | The PIM database | Read and write the desired state, audit and journal | Everything | No |
| Engine (ca-pim-tick) | Exchange RBAC for Applications | Application Mail.Send | A management scope containing ONE sender mailbox | Send TAP codes, approvals and alerts | Mail (the GUI shows codes instead) | Yes (mail option) |
| Engine (ca-pim-tick) | Key Vault RBAC | Key Vault Secrets User | The one SMTP relay secret | Read the SMTP relay password | Mail through an SMTP relay | Yes (SMTP option) |
| Engine (ca-pim-tick) | Other | Member of a Power BI security group + the Fabric tenant setting for read-only admin APIs | Power BI / Fabric | Read Power BI workspaces for discovery | Power BI provider | Yes (Power BI workload) |
| Manager (ca-pim-manager) | Graph application (read-only) | User.ReadBasic.All, GroupMember.Read.All | Tenant | The people and group pickers; every other directory fact is read by the engine | GUI views and pickers | No |
| Manager (ca-pim-manager) | Azure RBAC | Reader | The hosting subscription | Show Azure scopes and roles | Azure views | No |
| Manager (ca-pim-manager) | Azure RBAC | Reader | The PIM resource group only | Read the installation's own architecture (apps, jobs, registry, SQL, Key Vault, network) for the Environment report | Environment report (the architecture section shows "not readable") | No |
| Manager (ca-pim-manager) | Azure RBAC | Container Apps Jobs Operator | The ca-pim-tick job only | Start the engine on Run now / commit | Run now (the engine still runs on its schedule) | Default on; can be skipped |
| Manager (ca-pim-manager) | Azure RBAC | AcrPull | Your container registry (legacy path; normally the pull identity) | Pull its image | Start-up | No |
| Manager (ca-pim-manager) | SQL | Role pim_web (read; write staged changes, settings and audit; no schema right since 2.4.631); db_datareader, db_datawriter only until the second cut-over run | The PIM database | Read and stage changes, settings and audit | GUI | No |
| Manager (ca-pim-manager) | Key Vault RBAC | Key Vault Secrets User | The one emergency-passphrase secret | Emergency sign-in check | Emergency access | Yes |
| Manager (ca-pim-manager) | Exchange RBAC for Applications | Application Mail.Send | The one sender mailbox scope | Send mail from the GUI (test mail, approvals) | GUI mail | Yes (mail option) |
| Updater (ca-pim-update) | Azure RBAC | Contributor | The environment's resource group (and the registry when it is in another group) | Update container apps and jobs; schedule image builds | Updates | Can be skipped (then updates are manual) |
| Updater (ca-pim-update) | Azure RBAC | AcrPull | Your container registry | Pull built images | Updates | No |
| Updater (ca-pim-update) | Graph application | PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup | Tenant (used on the SQL admin group only) | Make the database job identity an active member of the SQL admin group (PIM for Groups, permanent where the group policy allows) and renew a time-limited membership before it ends (owner decision 2026-11-05) | Database job membership | No |
| Updater (ca-pim-update) | Graph application | PrivilegedAssignmentSchedule.Read.AzureADGroup | Tenant (used on the SQL admin group only) | Read the membership back before the database job or the support job starts | Database job membership | No |
| Updater (ca-pim-update) | Graph application | RoleManagementPolicy.Read.AzureADGroup | Tenant (used on the SQL admin group only) | Read the SQL admin group's PIM policy maximum, so a time-limited membership asks for exactly that length | Database job membership | No |
| Updater (ca-pim-update) | Graph application | GroupMember.Read.All | Tenant (used on the SQL admin group only) | Read the SQL admin group and the database job identity's group memberships (read only), so the membership is read back and the setup step reports it | Database job membership | No |
| Updater (ca-pim-update) | Graph application | Application.Read.All | Tenant (used on the database job identity only) | Read the database job identity's own group memberships (read only; reading a service principal's memberships needs it besides GroupMember.Read.All), so the membership is read back | Database job membership | No |
| Updater (ca-pim-update) | Graph application | Application.ReadWrite.OwnedBy | Only the app registrations the updater owns (the product's own: PIM Manager, and on Pro also PIM Manager Engine, PIM Activator, PIM Manager Deploy, PIM access request API) | Check and prove its ownership of the product's app registrations (one harmless change it reads back); later changes to them are made by the product itself instead of with a tenant-wide right (3.0.54) | App registration ownership | No |
| Updater (ca-pim-update) | SQL | Its own database user: role pim_updater + db_ddladmin + EXECUTE on the signed grant procedure only (no security right of its own); leaves grp-pim-sql-admins in the second cut-over run | The PIM database | Apply schema changes during an update | Schema updates | No |
| Pull identity (id-pim-<token>) | Azure RBAC | AcrPull | Your container registry | Pull images for the Manager and jobs | Start-up | No |
| Pull identity (id-pim-<token>) | SQL | None -- removed from grp-pim-sql-admins (2026-10-14); an image-pull identity has no database access | n/a | Nothing: every component that uses the database has its own database user | Nothing | n/a |
| SQL bootstrap identity (id-pim-sql-<token>) | SQL | SQL Entra administrator (or group member) | The SQL server (private SQL only) | Create the database users from inside the private network | Private SQL installs | Yes (private SQL) |
| grp-pim-sql-admins | SQL | SQL server Entra administrator | The SQL server | One managed group instead of a person as SQL admin; people get in just-in-time through PIM for Groups. A new installation does not make the Invardia Support app a member | Schema changes, recovery | No |
| Downlink job (MSP managed tenant) | Graph application | The engine permission set above | The managed tenant | Apply the bundle pulled from the managing tenant | MSP managed tenant | Yes (MSP only) |
| Downlink job (MSP managed tenant) | Azure RBAC + SQL | AcrPull; member of grp-pim-sql-admins (fallback: the three db roles) | Registry; SQL server | Pull image; write the store | MSP managed tenant | Yes (MSP only) |
| Baseline-publish job (MSP managing tenant) | Azure RBAC | Storage Blob Data Contributor | The bundle container only | Publish the signed bundle | MSP publication | Yes (MSP only) |
| Baseline-publish job (MSP managing tenant) | Key Vault RBAC | Key Vault Crypto User | The signing key only (sign/verify) | Sign the bundle with a non-exportable key | MSP publication | Yes (MSP only) |
| Baseline-publish job (MSP managing tenant) | SQL | SELECT on named objects; INSERT/UPDATE on its own last-run view; all fixed db roles revoked | The PIM database | Read the central admin set | MSP publication | Yes (MSP only) |
| RFA broker (ca-pim-rfa) | Azure RBAC | Storage Table Data Contributor | The access-request storage account (shared keys disabled) | Store access requests | Access requests | Yes (RFA option) |
| RFA broker (ca-pim-rfa) | Exchange RBAC for Applications | Application Mail.Send | The one sender mailbox scope | Mail access-request decisions | RFA mail | Yes |
| Manager sign-in app registration | Graph delegated | openid, profile, email, offline_access, User.Read (admin-consented) | Signed-in user only | Sign the administrator in | Sign-in | No |
| Manager sign-in app registration | Delegated scope (MCP option) | mcp.access (Azure CLI pre-authorised) | Signed-in user, bounded by the Manager role | MCP clients call the Manager as the user | MCP endpoint | Yes (MCP, Pro) |
| PIM Activator app registration | Graph delegated | PrivilegedAccess.ReadWrite.AzureADGroup, Group.Read.All, User.Read, RoleManagement.Read.Directory, RoleManagement.ReadWrite.Directory, AdministrativeUnit.Read.All, Application.Read.All; Azure Service Management user_impersonation | Signed-in user only -- bounded by that user's own eligibility | Users activate and deactivate their OWN eligible groups and roles | Activation from the extension | Yes (Activator option); tenant-wide admin consent by default |
| Deploy app registration (optional) | Azure RBAC | Owner (optional: Network Contributor on a hub VNet) | The hosting subscription | Unattended deploys (resources and role assignments) | Unattended deploys | Yes |
| Deploy app registration (optional) | Graph application | Directory.Read.All, AppRoleAssignment.ReadWrite.All, Application.Read.All, Group.Create, GroupMember.ReadWrite.All, DelegatedPermissionGrant.ReadWrite.All, RoleManagement.ReadWrite.Directory | Tenant | Grant the runtime identities and create the product's groups without a person | Unattended deploys | Yes (-GrantGraph) |
| Deploy app registration (optional) | Key Vault RBAC | Key Vault Reader on the MSP signing key (not granted when it already holds Key Vault Crypto User, Key Vault Crypto Officer or Key Vault Administrator there); may self-grant Key Vault Secrets Officer on the vault it writes | One key / one vault | Read the signing key's public part; write the SMTP secret | MSP build, SMTP setup | Yes |
| Engine app registration (classic path) | Graph application | The engine permission set above | Tenant | Engine identity where managed identity is not used | That install type | Yes |
| Engine app registration (classic path) | Exchange | Exchange.ManageAsApp (standing) + Exchange Administrator activated time-bound through PIM | Tenant | Mail sender setup by the engine identity | That mail setup path | Yes (-IncludeExchange) |
| Engine app registration (classic path) | SQL | db_datareader, db_datawriter, db_ddladmin (db_owner and dbmanager revoked) | The PIM database | Engine store access | That install type | Yes |
| Engine app registration (classic path) | Azure RBAC | User Access Administrator (optional); Storage Blob Data Contributor (legacy MSP host publisher) | Tenant root; bundle storage account | Azure delegation; legacy bundle publish | Those options | Yes |
| Setup admin app (mail setup, optional) | Exchange + Entra role | Exchange.ManageAsApp (standing), RoleManagement.ReadWrite.Directory, Exchange Administrator activated time-bound through PIM (default 4 h) | Tenant | Create the shared mailbox and its scoped send right without a person | Unattended mail setup | Yes (browser sign-in needs none of these) |
| Person running the setup scripts | Graph delegated + Azure | AppRoleAssignment.ReadWrite.All, Application.Read.All (Grant-PimEnginePermissions); Azure user_impersonation | Signed-in person only | Grant the engine its missing rights | That script | n/a (chapter 11 lists rights per script) |
| Hybrid worker VM identity | Graph application | Group.Read.All, User.Read.All, PrivilegedAssignmentSchedule.Read.AzureADGroup (mail goes through the send right scoped to one mailbox, never tenant-wide Mail.Send) | Tenant | Read which admins need AD accounts | Hybrid AD | Yes (hybrid worker) |
| Hybrid worker VM identity | Azure RBAC + SQL | Storage Blob Data Reader on the source container; db_datareader, db_datawriter (never db_ddladmin) | One container; the PIM database | Fetch the worker code; record results | Hybrid AD | Yes |
| Hybrid worker gMSA (AD) | AD delegation | Create/modify groups in the groups OU; create users + full control on users in the admin-accounts OU; optional: AdminSDHolder member write (tier 0) | The OUs you name | Create and maintain admin accounts and groups on-premises | Hybrid AD | Yes |
| Hybrid worker server gMSA (AD) | AD / GPO | Local Administrators on servers in the server OU (Restricted Groups GPO) | The server OU you name | Just-in-time server admin access | Server JIT | Yes |
| Invardia Support app (read-only database access, every level) | SQL + Entra | Its own database user, created from the application's client id, in the read role pim_support_read only (SELECT on the product schemas). It is not a member of grp-pim-sql-admins and not a database owner. It stays until you switch the Support app off or run Grant-PimSupportAccess.ps1 -Remove | The PIM database (read only) | Read the store when you ask for support | Assisted setup and support | Yes (your choice: only when you name a Support app) |
| Invardia Support app (setup level: support session) | SQL | db_owner on the same database user ONLY while a support session is open (at most 8 hours), opened and closed by the installation's own support job; every session is recorded. At troubleshoot level never | The PIM database | Install and repair on your behalf (create database users, apply the schema) | Assisted setup and repair | Yes (your choice) |
| Invardia Support app (tenant rights) | Graph + Azure RBAC | Granted by Invardia's own setup script, not by PIM Manager -- see chapter 5 | As listed there | Vendor setup and support | Assisted setup / support | Yes (your choice) |
4. Data
Data read from your tenant
- Users (names, UPN, mail, enabled state, last sign-in time), groups, owners and members, Entra roles and PIM schedules and policies, administrative units, domains, subscribed SKUs, applications and service principals, access reviews.
- Azure management groups, subscriptions, role definitions, role assignments and PIM-for-Azure schedules (Azure Resource Graph).
- Intune and Defender XDR role definitions and assignments; Power BI workspaces (when those workloads are managed).
- Authentication methods of the admin accounts it manages (to issue a Temporary Access Pass).
- On-premises AD users and groups (hybrid worker only).
- Not read: sign-in logs, audit logs, risky users, Conditional Access policies, mailbox content, files.
Data stored (your Azure SQL database, in your subscription)
- Desired state and definitions (admins, groups, roles, departments, workloads) -- includes admin names, UPNs and manager e-mail addresses.
- Settings, a tenant cache of what was read, the managed-object ledger (what the engine owns).
- The change queue and approvals.
- Audit log (
pim.AuditEvents: who, what, before, after) and commit journal (pim.CommitJournal: before/after of every commit, initiator, approver) -- both append-only by trigger. - Configuration backups and pre-commit snapshots.
- MSP managing tenants: a registry of managed tenants (app ids and certificate thumbprints only, secrets as Key Vault pointers).
- Not stored: TAP codes and generated passwords (shown once, never written). API keys are stored as SHA-256 hashes only. The SMTP password and emergency passphrase are in Key Vault, not SQL.
Retention
AuditRetentionMonths-- default 0 = keep forever; when set, 13 to 1200 months (1-12 refused); a daily job purges and the purge itself is audited.- Configuration backups --
ConfigBackupRetentionDaysdefault 90 (1-3650); pinned and newest kept. - Pre-commit snapshots -- 10 per entity. Job run history -- 10 per job.
- Commit journal, applied-commit log and change queue -- purged with the audit retention; the purge itself is audited.
- Log Analytics keeps the workspace default retention (30 days) unless you change it.
Data sent to Invardia
All outbound, HTTPS, to invardia.com. Nothing is sent about users, groups or roles by design; the exact fields are below.
- Telemetry uplink (run reports hourly, a heartbeat every 4 hours; feature gate
telemetry.uplink, on by default, switch off in Settings > Features; switching off sends one final opt-out record and then nothing). Two modes: anonymous (no licence install key: a random install id, bucketed counts, no tenant, host or text) and identified (with an install key: adds tenant id, host name and redacted error text). The redaction removes tokens, keys, SAS signatures and PEM blocks; it also removes e-mail addresses, UPNs and object names from error text. The identified heartbeat also carries the environment name your administrators gave the installation (the name shown in the Manager header) and the guard mode (normal, orstrictwith its end time). - Licence request (every 30 minutes until a licence is installed; gate
licence.autoRequest, on by default): product, version, tenant id, install id, current licence id and expiry. No contact details. When a licence is installed, the request also proves it: it sends the SHA-256 of the installed licence file and, with an install key, the key in a request header, so only the installation that holds the licence can ask for its renewal. - Install-key claim and update manifest (gate
updates.invardia): Pro sends product, tenant id, licence, ring; Community asks the public release channel for its ring and sends nothing else. - Install tracking (only when an install is started from an Invardia install token): the step names and outcomes.
- Licence validation itself is offline: a signature check with no network call.
Encryption and residency
- At rest: Azure SQL Transparent Data Encryption with service-managed keys, or customer-managed keys as an option. Key Vault for secrets.
- In transit: HTTPS to every API; SQL connections with Encrypt=True and certificate validation. Setup sets the SQL server's minimum TLS version to 1.2.
- Residency: every resource is created in your subscription in the region you choose. The installer's region list is West Europe, Sweden Central and Denmark East. Invardia receives only the uplink fields above.
Deletion on uninstall
See chapter 10. Your SQL database (and so all stored data) remains until you delete the resource group or the database.
| Record | Fields | Mode |
|---|---|---|
| Every record | Schema, Kind, Product (pim-manager), Version, Ring, LastSeenUtc | Both |
| Heartbeat (every hour) | Edition (community / pro / trial), Hosting (container), RuntimeIdentity (managed identity / certificate), LicenceState | Both |
| Run report (per job, per cycle) | Job name, Outcome, DurationMs, ErrorClass, run count | Both |
| Guard record | GuardId, GuardOutcome, Severity, Area, Job, measured and threshold numbers, HeldCount, TripCount, FirstSeenUtc | Both |
| Anonymous mode adds | InstallId (random, stored in settings); counts bucketed | Anonymous |
| Identified mode adds | ClaimedTenantId, Host, ErrorText (redacted, up to 8000 characters), raw counts; guard ActionText (500 characters) and Link | Identified |
| Opt-out | One final optout record, then nothing | Both |
5. Access by the vendor
Invardia has no access to a PIM Manager environment unless you create the Invardia Support app in your tenant. You decide whether it exists, at which level, and for how long. When you name it to the installation, it gets one standing right on the PIM database: a read-only user (next section). Admin rights on the database exist only for an open support session of at most 8 hours, at setup level.
Database access (when a Support app is named)
- What: the Support app has its own database user in the PIM database, in the read role pim_support_read (read access to the product's own tables, nothing else). The user is created from the application's client id; no directory lookup is involved. It is not a member of the SQL admin group (
grp-pim-sql-admins) and not a database owner. - Support sessions (setup level only): admin rights on the database (db_owner) are given to the same user only for an open support session -- at most 8 hours after it opened -- and are taken back when it ends. Every session is recorded. At troubleshoot level no session gives admin rights.
- What it reaches: the one PIM database -- the desired state, settings, audit log and run history described in chapter 4, read only outside a support session. It does not reach other databases, and it is not a right in Entra ID or Azure.
- When it is given: by the installation, at every support level, when you name a Support app (
Grant-PimSupportAccess.ps1). With no Support app named, nothing is created. - How it is checked: the end-of-install check has a line for it. It says "in place" only when it read a database user with the Support app's id in pim_support_read from the database; the same user also in db_owner is a warning, never "in place"; otherwise it says it could not be checked, or that it is not in place, with the next step.
- How you end it: switch the Support app off or delete it in Entra ID (the access ends at once, because the database user can no longer get a token), or run
Grant-PimSupportAccess.ps1 -Remove(drops the database user). - Installations made before this: an earlier version gave the Support app a standing db_owner and a membership of the SQL admin group. A new run of
Grant-PimSupportAccess.ps1does not add them again and says when they are still there;-Removetakes them back. - What this means for you: whoever holds the Support app's secret can read the PIM database for as long as the app is enabled, and change it only during an open support session. The secret is held as described under Credential and conditions below; every action is in your Entra sign-in log and in PIM Manager's own audit log.
What the Support app can do
The app's tenant rights are created by Invardia's own setup script (published at invardia.com/support), not by PIM Manager. In that script:
- Troubleshoot level: read-only Graph (directory, applications, users, groups, roles, PIM policies and schedules, PIM for Groups read) plus Application.ReadWrite.OwnedBy (to renew its own secret); Azure Reader and Log Analytics Reader on the resource groups you name; Key Vault Reader.
- Setup level: adds Application.ReadWrite.All, AppRoleAssignment.ReadWrite.All, DelegatedPermissionGrant.ReadWrite.All, Group.Create and RoleManagement.ReadWrite.Directory in Graph, and Contributor + User Access Administrator on the subscriptions you name (optionally at the tenant root), Key Vault Secrets Officer, Network Contributor on a hub VNet. Setup level is tier-0 equivalent -- grant it for an install or repair, then lower it.
- PIM Manager's own grant script (
Grant-PimSupportAccess.ps1) gives, at every level, the read-only database user described above -- and nothing in Entra ID: no group membership, no ownership of the product's app registrations or groups. - As-built document (level `asbuilt`, also part of troubleshoot and setup): the Support app may start the one as-built job (
caj-pim-asbuilt) and read its executions, and may read the one storage containerasbuilt-- nothing else. The job writes a PDF describing the installation's configuration (no secrets, people, user names or object ids) to that container. The storage account accepts only Entra tokens (no shared key, no anonymous access), so the PDF is readable only by the Support app's identity after you grant it, and it is deleted after 24 hours. Your admins download the same PDF from PIM Manager without any of this.
Security changes to an existing installation
- Infrastructure changes to an installation that is already running (for example tightening database rights, turning on SQL auditing or shortening the sign-in session) are never made by the updater. They are made by Invardia through the Support app, one environment at a time, with a script that shows a plan first, reads every change back and writes a rollback record. Every SQL statement goes through Invardia's support SQL route, which records the statement and its reason before it runs.
- Order: Invardia's own environment first, then the test environments, then each customer environment in batches, with a check of the engine runs between batches. Customers are told beforehand.
Credential and conditions
- The Support app uses a client secret (this is the only identity in the product allowed one, and only for setup and support, never for the runtime). For customers it expires after 90 days; old secrets are removed when a new one is made. Invardia keeps it in its support Key Vault.
- Invardia's sign-in tool checks that the token's tenant and app match the environment, refuses a production environment without an explicit production switch, and stops when you have disabled the environment.
- An optional Conditional Access policy can restrict the app to Invardia's support IP address; it is created on wherever the tenant has Workload Identities Premium.
How you remove it
Grant-PimSupportAccess.ps1 -Remove-- takes back the SQL user, a membership of the SQL admin group or ownerships an earlier version gave, and the as-built job and container access.- Invardia's
New-InvardiaSupportApp.ps1 -Action Disable(sign-in blocked, grants kept) or-Action Remove(deletes the app, its Azure roles and the Conditional Access policy). - Or simply delete the app registration / service principal in Entra ID.
Audit trail
- What the Support app does is visible in your Entra sign-in and audit logs and the Azure Activity Log.
- PIM Manager's own audit log records every action the Support app makes against Graph, Azure or SQL, and the Review active assignments page shows the Support app's own assignments.
6. Supply chain
How code reaches your environment
- Every update builds the product from source inside your own container registry and rolls the Manager and jobs. No pre-built vendor image is pulled. The updater job
ca-pim-updatedoes this on its schedule; an installation that turns it off updates by command (below). - The signed Invardia update channel: the update manifest is signed (RS256, RSA 4096) and verified against a public key embedded in the product -- never fetched at run time. The manifest must name your ring, a version, a SHA-256, a size and a sequence number (replays are refused); the download must be HTTPS; the archive's SHA-256 and size are checked before unpacking, and the version inside must match the manifest.
- Source-archive channel (self-hosted updates): the archive is fetched from a storage container the update job is configured with, then built in your registry, rolled and health-checked like any other update.
- No storage token in the updater: Pro installations fetch the source archive from invardia.com for the version their signed manifest names; the update job no longer keeps a storage SAS URL in its settings. The container registry's admin user is off.
- Updating by command:
Update-PimCommunity.ps1 -Applyreads the same signed release and checks it the same way, downloads the archive, checks its SHA-256 and size, and deploys it with the parameters your last deploy saved. Without-Applyit shows the version it would move to and the deploy plan. The deploy upgrades the database first, runs a health check and rolls PIM Manager back when the check fails. - Licences: signed (RSA-SHA256) and verified offline against embedded public certificates, both before storing and after reading back.
Rings, who releases, and your control
- Rings 0-3: 0 development, 1 test, 2 design partners, 3 broad. Ring 2 is never advanced automatically.
- A release is built only from a tagged source version and published by a dedicated publisher identity. Each release carries a fingerprint of the engine code and says whether the engine changed since the previous release.
- Release control: Invardia refuses a ring 2 or ring 3 release, or an early wave, of a version the release owner has not marked APPROVED (with a reason, audited, append-only). A wave serves a version to named installations inside a ring only after that version was released to a lower ring; stopping a wave never moves an installation back. After a release that changed engine code, installations report more often for the first hours, and each release collects evidence (guard trips, the engine's own changes, run results) for the owner's decision. Rings 0 and 1 are never held. A publish whose answer is lost (a server error) is read back before anything is retried, so a release is never published twice.
- Strict guards after an engine change: for 24 hours after an update that changed engine code, every numbered safety limit is halved (chapter 7).
- Invardia holds the update-signing key. Your controls: the update hold freezes the environment at its version; downgrades are refused; a minimum-from version prevents skipping a required step; updates run on a schedule you can change (default 03:00 UTC daily); the update job can be removed for fully manual updates.
Source availability
- The source is published in a public GitHub repository (linked from invardia.com), so the code you run can be read and compared with what is built. The Community edition is licensed under the PolyForm Shield License 1.0.0 (free to use and change, not to build a competing product); Pro is delivered in the Pro package under a commercial licence and is not in the public repository.
Dependency policy
- No PowerShell modules at runtime: the engine, Manager, updater and the published setup scripts use REST and .NET only, with browser sign-in.
- The container base images are pinned by digest; the container runs as a non-root user.
- The one NuGet package (Microsoft.Data.SqlClient) is pinned by version and by hash.
- Exceptions, outside the runtime: the hybrid worker for on-premises AD uses the Windows ActiveDirectory and GroupPolicy modules (RSAT) on its worker VM (an Azure VM the setup builds, domain-joined, in its own VNet peered to your domain controllers); some local-only operator modes of the Manager can use Microsoft Graph / Az modules when already installed.
7. Change control and audit
Every change is staged, then committed
- Changes made in the Manager are staged and only reach the tenant when committed. The engine applies only what is defined in the database: an object the product does not own is reported, never removed (the managed-object ledger). An unreadable ledger prunes nothing.
- Commit journal: every commit records before and after, who initiated it and who approved it, in the same transaction as the change -- if the journal row fails, the change fails. Append-only by trigger.
- Undo: a commit can be undone by planning its inverse and committing it through the same gates (SuperAdmin: any commit; Admin: their own).
- Backup and restore: a snapshot before every apply; configuration backups on a schedule; an environment backup can be imported with a plan first and the engine paused, never overwriting what exists.
Approvals
- Second approver (off by default): on Pending changes, a SuperAdmin can require that a different administrator commits each sensitive change, or every change. Pro adds maker/checker (off by default): when it is on, changes classified as sensitive (privileged roles, Tier 0/1, guests, offboarding) need a second administrator to approve them, and the maker cannot approve their own request unless a SuperAdmin switches on Allow an administrator to approve their own requests (off by default). Community has no maker/checker.
- Always on: changing the break-glass list needs a second SuperAdmin, with no self-approve switch.
Guards (always on)
- Never disable accounts when the desired admin set is empty or could not be read; account disable is opt-in.
- Limits are counts. No guard uses a share of a list or of the scanned accounts. Three guards have a limit that a SuperAdmin sets on the Guards page, inside a fixed range: the commit removal check (default 25 rows of one list in one commit; range 5 to 200), the removal budget (default 5 removals per scope per run; range 1 to 25) and the mass-disable breaker (default 3 accounts per run; range 1 to 25). The removal budget is one number for every way the engine removes: removals in a list, a prune, a reconcile, offboarding, group deletion, a queued group delete and a retraction on a managed tenant. A stored value outside its range, or one that cannot be read, is ignored and the default applies. An environment setting can lower a limit and can never raise it. No guard can be switched off.
- Commit removal check: a commit that takes more rows than the limit out of one list, or keeps none of the rows the list has now (also when new rows are added in the same commit), or would leave 2 rows or fewer of a list that has more than 5 rows, is not saved until a SuperAdmin approves exactly those rows in the commit dialog, with a reason. The server decides who may approve; an Admin cannot.
- Removal budget per scope: a run that would remove more than the limit removes nothing in that scope and holds the list. A SuperAdmin approves the exact list when it is committed (the run then applies exactly those items, each once, whatever their number), or releases a list a run already holds. Deleting groups goes through the same approval. Anything that is not in the approved list is still held; an approval ends by itself after 48 hours.
- Mass-disable breaker: a run that would disable more accounts than the limit disables none and holds the list; a SuperAdmin releases exactly that list of accounts for one run.
- An approval or a release is given only by a SuperAdmin of the tenant signed in to the Manager, is bound to the exact list (a changed list is held again), needs a reason and is audited (who, when, why and every item). A release lasts one run or at most 24 hours. Approvals, releases, held lists and limits are never restored from a configuration backup and never copied by an environment import or a settings copy, so a used or revoked approval cannot come back; a record whose own times do not add up (no start time, a start in the future, an end later than its lifetime allows) counts as ended. The break-glass exclusion, account deletion by a prune or reconcile, shared workload assignments, objects the product does not own and the last Manager SuperAdmin are locked: they have no limit and can never be approved, exempted or released.
- Account deletion -- one operator-controlled path. The product never deletes an account it does not manage, and a prune or reconcile never deletes anything: an undefined account is only reported. The only delete is an operator's Delete account on a PIM-managed admin account (a SuperAdmin, an Admin, or a delegated operator for admins at or below its level, typing DELETE; that confirmation is the approval). The engine then deletes it once -- sessions revoked first, never a break-glass account, never an enabled account the disable circuit breaker did not allow, at most 5 per run, and never on a managed tenant on the managing tenant's word (there it is disabled). Entra keeps a deleted user restorable for 30 days. Turn the path off per environment with
PIM_ADMIN_ACCOUNT_DELETE=0. - Strict mode after an engine change. For 24 hours after an update that changed engine code, every numbered limit is halved from the value the SuperAdmin configured: effective = max(1, floor(configured / 2)), so a limit of 1 stays 1. It covers the commit removal check, the removal budget, the mass-disable breaker, bulk revoke, account deletion, the policy brake counts and the hybrid server batch. The Guards page shows configured and effective limits and when Strict ends; the header shows "Guard mode: Strict" to SuperAdmins. A SuperAdmin can end Strict early with a reason, which is audited. A strict trip is held like any other trip. On the first version that brings Strict to an installation, it only records the engine fingerprint, so the switch itself never starts it.
- Every guard trip is mailed, audited and reported. Every mail subject names the environment and, when it matters, a severity word:
[<Environment>] Failed | Warning | Action needed: <what happened> [<ticket>] [PIM Manager], at most 120 characters. - Break-glass accounts in Settings are never removed, disabled or revoked; if the list cannot be read, every account is treated as protected.
- The engine has a dry-run (-WhatIf) mode; scheduled jobs can be paused one by one or all at once.
Manager roles
- None, Reader, Delegated, Admin, SuperAdmin. Hosted with no authenticated principal = no access (401). The access model refuses to be left without a SuperAdmin.
Audit
pim.AuditEventsrecords actor, source, action, target, before, after and dry-run flag; append-only by trigger; purged only by the retention job (minimum 13 months; default keep forever).- Logs of the Container Apps go to the Log Analytics workspace in your subscription.
- SQL auditing is on: the SQL server sends its security audit events to the installation's own Log Analytics workspace, kept 90 days, so every statement by any identity -- including the Invardia Support app -- can be reviewed there.
- Only the updater holds a schema right; any schema change and any direct SQL write is recorded by the SQL audit in your workspace, outside the database.
8. Threat model and hardening
The top risks for a privileged-access product and the controls that answer each one. Every control below is part of the design: it is built into the product, applied by setup and kept in place by every update, so no customer has to configure it. The checklist after it lists what you can add in your own tenant.
| Threat | Controls | Hardening by design |
|---|---|---|
| Privilege escalation through the engine identity (it can assign any directory role and grant any app permission) | Managed identity (no credential to steal); Manager is read-only in Graph; engine applies only DB-defined objects; guards; break-glass protection; every change audited and journaled | The most privileged directory roles (Global Administrator, Privileged Role Administrator) are refused as engine targets; the engine is monitored as tier 0 |
| Compromised Manager administrator | Entra sign-in with app assignment required, no guests by default; roles Reader/Admin/SuperAdmin; sign-in front with no client secret and an 8 h fixed session; every request to the Manager carries the user's verified, signed ID token; security headers (CSP, HSTS, frame-ancestors none, nosniff, same-origin referrer); staged commits; guards (halved for 24 h after an engine change); audit and journal; undo | MFA through your Conditional Access on the sign-in app; a second person for sensitive changes when you switch it on (checklist item 4); self-approval off by default |
| Update tampering | Invardia channel: signed manifest, embedded key, hash + size + version + ring + replay checks; builds in your registry; HOLD; no automatic ring-2 advance | Every update signature-checked -- the signed manifest, then the archive's SHA-256 and size; the hybrid worker's download too |
| Script tampering (a privileged person runs a modified setup script) | Scripts are single self-contained files with a published SHA256SUMS.txt; no pipe-to-execute in the product; no second-stage code download | The shown command keeps a SHA-256 verify step for whoever checks; download and run stay two lines |
| Vendor (Invardia) access misuse or compromise | No access without the Support app, which is yours to create, lower, switch off and remove; secret expiry; tenant/app/production checks in Invardia's sign-in tool | Support levels are scoped and the Conditional Access lock is on; every Support app action is in PIM Manager's own audit trail |
| Tampering with the audit trail | Append-only triggers on the audit log and journal; retention minimum 13 months | Only the updater holds a schema right; every schema change is in the SQL audit, outside the database |
| Lateral movement between product identities | Separate identities per component; one database user per component; the image-pull identity has no database access; the SQL admin group holds only the database job identity (people just-in-time); the web app has no db_ddladmin and only start rights on the engine job; publish job without fixed SQL roles | Each component holds only its own custom role; the updater is never in the SQL admin group; no engine secret reaches the Manager |
| Data leaving the tenant | No directory data in telemetry by design; anonymous mode without an install key; opt-out | Names and UPNs are removed from error text before it leaves; the licence request sends only what licensing needs |
| Network exposure | Manager created closed until Entra sign-in is verified; workers have no ingress; Entra-only SQL; private options | Private networking is a setup option; setup sets SQL minimum TLS 1.2 and keeps the install in the regions you choose |
| Secrets at rest | Managed identities everywhere at runtime; no sign-in secret (federated credential); no storage SAS in the updater; registry admin user off; Key Vault for secrets with purge protection on the product's own vaults; API keys hashed | The install key and licence token are held as secrets; the emergency passphrase hash is salted |
| # | Action | Why |
|---|---|---|
| 1 | List your break-glass accounts in Settings (Get Started step) -- the list is empty until you do | The engine then never touches them |
| 2 | Require MFA and compliant devices for the Manager sign-in app with Conditional Access | The product does not enforce MFA itself |
| 3 | Keep the Manager's sign-in limited to named people and groups (assignment required) | The sign-in front verifies every request's signed token; assignment narrows who can get one |
| 4 | Set Second approver to Sensitive on Pending changes; on Pro, also switch on maker/checker. Keep self-approval off | A second person for sensitive changes |
| 5 | Use the private network options: internal Container Apps environment and SQL private endpoint; or add IP allow-rules | Removes public exposure and the 'Allow Azure services' SQL rule |
| 6 | Set the SQL server's minimum TLS to 1.2, and set alerts on the SQL security audit table in your workspace | TLS is not set by the installer; SQL auditing is on (90 days) and alerts are yours to choose |
| 7 | Keep User Access Administrator at the tenant root off unless you manage Azure RBAC with the product | Least privilege |
| 8 | Grant the Invardia Support app only when needed, at troubleshoot level, and remove it afterwards; enable its Conditional Access lock | Vendor access only on demand |
| 9 | Monitor the engine and Manager managed identities with Entra workload identity alerts; treat them as tier 0 | They hold tier-0-equivalent rights |
| 10 | Set AuditRetentionMonths to your policy and Log Analytics retention to match | Defaults keep the audit forever and logs 30 days |
| 11 | Decide on telemetry: keep anonymous, use identified for Pro support, or switch telemetry.uplink off | Data leaving the tenant |
| 12 | Before running any setup script (optional, for whoever verifies): compare Get-FileHash with SHA256SUMS.txt and read it; the command PIM Manager shows stays two lines, download then run | The hash shows that the script is the published one |
| 13 | Use the update hold for change windows; review release notes before lifting it | You control when code changes |
9. Compliance mapping
How PIM Manager's controls can support your own controls. This is not a certification and does not make your organisation compliant; you remain responsible for your controls and their evidence.
| Framework | Control | How PIM Manager supports it |
|---|---|---|
| ISO/IEC 27001:2022 Annex A | 5.15 Access control / 5.18 Access rights | Desired-state delegation through groups and PIM, reviewed and applied consistently; drift reported |
| ISO/IEC 27001:2022 Annex A | 8.2 Privileged access rights | Dedicated admin accounts, eligible (just-in-time) roles, PIM policies with approval and duration |
| ISO/IEC 27001:2022 Annex A | 5.16 Identity management / 5.11 Return of assets (access) | Admin account lifecycle, auto-disable date, offboarding removes memberships and eligibilities |
| ISO/IEC 27001:2022 Annex A | 5.17 Authentication information | Temporary Access Pass onboarding; no passwords stored |
| ISO/IEC 27001:2022 Annex A | 8.15 Logging / 8.16 Monitoring | Append-only audit log and commit journal in your SQL; container logs in your workspace; guard alerts |
| ISO/IEC 27001:2022 Annex A | 8.32 Change management | Staged commits, a second approver for sensitive changes (Pro adds maker/checker), undo, snapshots, release rings and update hold |
| ISO/IEC 27001:2022 Annex A | 5.19-5.22 Supplier relationships | No vendor access without the Support app, which is under your control; its standing database right is listed in chapters 3 and 5; this pack |
| NIS2 (Article 21) | 21(2)(i) Access control policies and asset management | Least-privilege, just-in-time delegation managed as desired state |
| NIS2 (Article 21) | 21(2)(j) Multi-factor authentication | PIM policies can require MFA on activation; the Manager relies on your Conditional Access |
| NIS2 (Article 21) | 21(2)(d) Supply chain security | Builds from source in your registry; signed updates; ring control; this pack |
| NIS2 (Article 21) | 21(2)(f) Effectiveness assessment | Access reviews, drift and coverage reports, audit export |
| CIS Critical Security Controls v8 | 5.4 Restrict administrator privileges to dedicated admin accounts | Dedicated admin accounts per person |
| CIS Critical Security Controls v8 | 6.1-6.2 Establish access granting and revoking processes | Commit-based grant and revoke with audit |
| CIS Critical Security Controls v8 | 6.8 Define and maintain role-based access control | Role and department definitions applied by the engine |
| CIS Critical Security Controls v8 | 5.3 Disable dormant accounts | Inactivity sweep (guarded, opt-in disable) |
| CIS Critical Security Controls v8 | 8.2 Collect audit logs | Audit log and journal |
10. Uninstall and exit
Removing the product
- Fastest complete removal of the Azure side: delete the resource group the product was installed in. That removes the Container Apps, jobs, SQL server and database (all stored data), registry, Log Analytics workspace, Key Vault (soft-deleted for 90 days, then purged) and user-assigned identities.
Remove-PimContainerStack.ps1removes only the container apps, jobs and Container Apps environment and their role assignments at subscription scope, and deliberately keeps SQL, registry, Key Vault, storage, network and identities -- use it to rebuild, not to exit.
What remains after deleting the resource group (remove by hand)
- Role assignments made at the tenant root management group or on other subscriptions (Reader, optional User Access Administrator).
- App registrations: the Manager sign-in app, the access-request app, the engine and deploy app registrations (when created), the PIM Activator app.
- Groups:
grp-pim-sql-admins, the Manager users group, the Power BI admin-API group. - The mail sender's shared mailbox and its Exchange management scope and role assignment.
- The Invardia Support app (chapter 5).
- Everything the engine created in your tenant on purpose: admin accounts, PIM groups, administrative units, role eligibilities and assignments, PIM policies. These are your access model -- they keep working without the product. Remove or keep them as part of your exit plan; the Manager's reports and the managed-object ledger list them before you uninstall.
- On-premises: hybrid worker gMSAs, AD delegations and the server GPO.
Exit
- Export your configuration (Settings > backups) before removal; it is JSON you keep.
- One uninstall script removes the installation and lists what remains for you to remove by hand.
11. Scripts
Scripts are run by highly privileged people, so they are listed here one by one with the rights needed and the changes made. Every published script is: listed in SHA256SUMS.txt; a shown command of two lines, download then run, with SHA256SUMS.txt published for whoever verifies (never pipe-to-execute); no second-stage downloads (one stated exception, the installation launcher, below); -WhatIf preview; a transcript; browser sign-in, no secrets in or out.
How to run a script
PIM Manager shows every script command as two lines -- line 1 downloads the file from Invardia, line 2 runs it (more run lines only when a flow needs them); the documentation page is the link next to the command:
- Download it:
Invoke-WebRequest https://invardia.com/support/pim/<Script>.ps1 -OutFile <Script>.ps1 - Run it, with
-WhatIf(or-PlanOnlywhere the table says so) first:.\<Script>.ps1 -WhatIf
Optional, for whoever verifies before running (never part of the shown command): compare Get-FileHash .\<Script>.ps1 -Algorithm SHA256 with the line in SHA256SUMS.txt published next to it, and Read it -- each script is one self-contained file; the source is also in the public repository.
Facts that hold for every published script
- Listed in SHA256SUMS.txt, published next to the scripts.
- No PowerShell modules; REST and .NET only; browser sign-in (no device code).
- No pipe-to-execute anywhere in the product; scripts do not download and run further code -- with one stated exception: Start-PimManagerInstall.ps1, whose job is to download the public PIM Manager release from GitHub into a new folder, compare its SHA-256 with the one the release publishes (when it publishes one), and run the installer of that release.
- A transcript of every run is written; some scripts also write a result file with -OutFile.
- Every script has its documentation page and an entry in the documentation manifest (framework 12.7).
| Script | Purpose | Rights needed to run it | Changes it makes | Preview |
|---|---|---|---|---|
| Start-PimManagerInstall.ps1 | Install PIM Manager with one command: download the public release into a new folder, compare its SHA-256 with the one the release publishes (when it does), and run its guided installer (Install-PimManager) with the same parameters | What Install-PimManager needs (below); the launcher itself reads only public release data and needs no sign-in | A new folder in the temp folder with the release, and a note with its path for -Resume; everything else is made by Install-PimManager (below) | -WhatIf (honoured; the release is unpacked in the temp folder and the installer runs with -WhatIf) |
| Grant-PimEnginePermissions.ps1 | Give the engine identity its missing Graph permissions and Azure roles (the command the Manager shows) | Global Administrator or Privileged Role Administrator (app permissions); Owner or User Access Administrator at the scope (Azure roles) | Graph app-role assignments and Azure role assignments for the engine, exactly as listed in the command; only roles and scopes on the product's allow-list | -PlanOnly (no -WhatIf) |
| Initialize-PimSqlAdminGroup.ps1 | Make grp-pim-sql-admins the SQL server's Entra admin with the product's identities as members | Privileged Role Administrator (role-assignable group) + Owner/Contributor on the SQL server | Creates the group; sets the SQL Entra admin; adds the product identities and you (never the Invardia Support app) | -PlanOnly (no -WhatIf) |
| Initialize-PimWorkloadPrereqs.ps1 | Fix a workload prerequisite the product cannot fix itself (Power BI group, Fabric setting, Sentinel, Azure rights) | AppRoleAssignment.ReadWrite.All + Group.ReadWrite.All (delegated); Fabric administrator; User Access Administrator at the scope | Power BI security group + engine membership; Fabric tenant setting; engine Graph roles; optional Sentinel workspace (billed) and User Access Administrator; product settings | -WhatIf (honoured) |
| Initialize-PimMailSender.ps1 | Create the sender mailbox and its send right scoped to that one mailbox | Exchange Administrator or Global Administrator (browser); or the Support app (activates Exchange Administrator time-bound) | Shared mailbox; management scope; Application Mail.Send role assignment for the product identities; removes tenant-wide Graph Mail.Send; product settings | -WhatIf (honoured; stops before any Exchange call) |
| Set-PimSmtpRelayPassword.ps1 | Store the SMTP relay password in the environment's Key Vault | Key Vault secret write (it can grant itself Key Vault Secrets Officer on that vault if you may) | Optional vault; the secret; Key Vault Secrets User on that one secret for the product identities | -WhatIf (honoured) |
| Set-PimSqlTier.ps1 | Set the product SQL database to its Standard tier (S0 minimum, never Basic) with a 250 GB maximum size; optionally pin the tier | SQL DB Contributor (or Contributor) on the SQL server | The database tier (Basic -> S0, or the Standard tier you choose), its maximum size (raised to 250 GB, never lowered) and, with -Pin, its pim-sql-tier-pin tag; nothing else | -WhatIf (honoured) |
| New-PimHubPrepareScript.ps1 | Private install: write the script the hub network owner runs (the hub side of the peering, optional rights for the deploy identity) | None to run it (it only writes a file); the hub owner who runs the written file needs Network Contributor on the hub VNet, and Owner or User Access Administrator there for the optional grants | This script: one local file (prepare-hub-<hub-vnet>.ps1). The written file, when the hub owner runs it: the hub-side peering, optionally Network Contributor on the hub VNet and Private DNS Zone Contributor on the DNS resource group for the deploy identity; it never deletes anything | -WhatIf (honoured) |
| Deploy-PimActivatorBackend.ps1 | Create or update the PIM Activator app registration | Application Administrator or Cloud Application Administrator (active); Privileged Role Administrator or Global Administrator for consent | App registration, service principal, redirect URIs, delegated permissions (chapter 3), tenant-wide admin consent (default on), group assignment | -WhatIf (honoured) |
| Publish-PimActivatorRemediation.ps1 | Build the Intune Remediation (detect + remediate) for the Activator and upload it | Intune Administrator (DeviceManagementScripts.ReadWrite.All, delegated) | Writes the two scripts locally; creates/updates an Intune remediation that runs as SYSTEM; assigns only to the group you name | -WhatIf (honoured) |
| Deploy-PimActivatorClient.ps1 | Install the Activator extension and settings on a machine without Intune | Local administrator (machine scope); none (user scope) | Browser policy registry keys (force-install list, allowed sources, extension settings); the browser then fetches the extension from its update URL | -WhatIf (honoured) |
| Initialize-PimHybridWorkerAd.ps1 | PIM for Active Directory: prepare AD for the hybrid worker (its gMSAs, their least-privilege OU rights, the servers GPO, the Azure VM's offline-join blob) | Domain Admins on a domain controller; Enterprise Admins only with -CreateKdsRootKey | gMSAs + their PermissionGroup / PrincipalsAllowedAccess groups; OU delegations to the PermissionGroup (AdminSDHolder only with -GrantProtectedGroupMembership); optional servers GPO; optional computer account + join blob; optional KDS root key. Modules: the owner-approved GroupPolicy module and Add-KdsRootKey only | -WhatIf (honoured) |
| Install-PimHybridWorker.ps1 | PIM for Active Directory: install the hybrid worker on the worker machine (Azure VM or Azure Arc-enabled server): gMSAs, the PIM code for its ring, the scheduled tasks | SYSTEM / local administrator on the worker (normally through Azure run-command) | PowerShell 7; the gMSAs installed and tested; batch-logon right for them; C:\PIM locked down; six scheduled tasks; on Arc the gMSAs join 'Hybrid agent extension applications'. Modules: the owner-approved in-box ScheduledTasks and CimCmdlets only | -WhatIf (prints the plan) |
| Deploy-PimHybridWorker.ps1 | PIM for Active Directory: deploy the hybrid worker end to end (Azure VM or Azure Arc-enabled server), step by step, and continue later with -Resume | Contributor (or Owner) for the worker's Azure resources; User Access Administrator on the source container; Privileged Role Administrator for the worker identity's Graph read roles; the Microsoft Entra admin of the PIM SQL server. The Active Directory step is printed for the AD administrator | The worker's network and VM (Azure) or nothing in Azure (Arc); the worker identity's Graph read roles, Storage Blob Data Reader on the source container and its database user; the install on the worker through run-command; a state file without secrets. One file: the worker's other scripts travel inside it, each checked against its SHA-256 before anything runs, and run from a private temp folder that is removed afterwards | Plan first (without -Apply nothing is changed) |
| Set-PimLicense.ps1 | Register an issued licence file in the environment's store (the two lines Settings > Licence shows); optionally store the install key or queue its claim | Member of the environment's SQL admin group, signed in through the browser (no command-line tool, no PowerShell module, no certificate, no secret) | The License setting in the product database (the signed document, verified before it is written and read back); with the install-key options the install key and its claim state; nothing in Entra or Azure | -WhatIf (honoured) |
| Grant-PimSupportSqlAccess.ps1 | For an installation made before the read-only support access only: gives the Invardia Support app the same read-only database user a new installation gives (chapter 5) | A member of the environment's SQL admin group (or Invardia support in the Support app's session) with SQL Server Contributor on the SQL server. Browser sign-in or the Support session; no command-line tool, no PowerShell module, no secret | The support access step: the Support app's database user in the read role pim_support_read only, the consent level and the signed procedures of the support session. No database owner role and no SQL admin group membership is given; one an earlier version gave is shown as a warning and left as found. For the run only: the firewall rule AllowSetupHost (removed again and read back), and -- only in the Support app's own session when the database refuses it -- the SQL server's administrator, put back exactly as it was read and read back, also after a failed step | -WhatIf (honoured; reads only, no database connection) |
| Invoke-PimSupportSqlAccessJob.ps1 | Give the Invardia Support app its read-only database user on an installation whose database is private (public network access off), from inside: a one-time job in the installation's own environment runs the support access step, the result is read back, and the job is removed; run once, by the customer | Contributor (or Owner) on the installation's resource group; optionally Log Analytics Reader on the environment's workspace to show the job's log lines. Browser sign-in or the Support session; no command-line tool, no PowerShell module, no secret | The Support app's database user in the read role pim_support_read only (never db_owner; with -SupportHours a support session adds db_owner until its end, at most 8 hours). For the run only: the one-time job, running as the identity the installation's own database setup job already uses -- removed again and read back, also after a failed step. It never gives any identity a role, a group membership or a permission, never opens a firewall rule or a network path, and never changes the SQL server or the installation's own jobs; when no existing identity can be used it stops and changes nothing | -WhatIf (honoured; reads only, creates no job) |
| Set-PimSigninFrontSqlState.ps1 | Private installation moved onto the sign-in front: give the front's managed identity its place in the product database, from a machine inside the network; run once | A member of the environment's SQL admin group (or the SQL server's Entra administrator), signed in through the browser or the Support session; no command-line tool, no PowerShell module, no secret | The front identity's database user (from its client id), the schema signin owned by it, and CREATE TABLE; never a role, a firewall rule or anything outside the database | -WhatIf (honoured; prints the statements, changes nothing) |
| Import-PimV1Data.ps1 | Move from PIM version 1: import its data folder (the CSV files and the naming conventions) into the installation, by key; check + preview by default, -Apply writes | A member of the environment's SQL admin group (or a database user that can read the store for the preview; the database owner role for -Apply); Reader on the subscription to find the installation; SQL Server Contributor on the SQL server only when this machine needs a temporary firewall rule. Browser sign-in or the Support session; no command-line tool, no PowerShell module, no secret | Only with -Apply: the rows the product database does not have yet, added by their key (never a delete; a conflicting row stops the run before anything is written unless the person chooses -OnKeyConflict), and settings from the folder that are still empty (the changed naming conventions). For the run only: a firewall rule for this machine's address when none allows it -- removed again and read back, also after a failed step. A private installation is never opened: the run stops and says to run it from inside the network. The naming conventions file is parsed first and refused when it holds commands | Preview by default (writes no data); -WhatIf (honoured; adds no firewall rule either) |
| Script | Purpose | Rights needed to run it | Changes it makes | Preview |
|---|---|---|---|---|
| Install-PimManager.ps1 | The guided install (started by Start-PimManagerInstall.ps1 (the two install lines: from invardia.com for Pro and trial, from the GitHub release for Community), or run directly); the answers are parameters (only the tenant and the subscription are needed), the wizard's answers file is optional; without a licence or an enrollment key it installs Community | Azure Owner, or Contributor + User Access Administrator, on the subscription; Entra Privileged Role Administrator or Global Administrator (active) for the directory steps | Everything in chapters 1-3 for the chosen options; licence; optional Support app access | -PreflightOnly (rights + plan check) |
| Invoke-PimDeployAll.ps1 | Full deploy: identities, infrastructure, schema, image, verify, rollback | As Install-PimManager | As above | Plan by default; -Apply to run |
| Confirm-PimInstall.ps1 | End-of-install check; also repairs some lines (access model, update job, root Reader, firewall rule) | Reader for the check; the repair's own rights | Repairs plan first (-WhatIf) | -WhatIf (honoured) |
| Grant-PimSupportAccess.ps1 | Give or take back the Invardia Support app's access (troubleshoot / setup / asbuilt / -Remove); every level gives a read-only database user, admin rights only inside an open support session at setup level | SQL admin (a member of the SQL admin group); Privileged Role Administrator only for -Remove of an earlier membership | Chapter 5 | -WhatIf (honoured) |
| Invoke-PimMspBuild.ps1 | MSP managing / managed tenant build | As Install-PimManager, per tenant | MSP components (chapter 3) | Plan by default; -Apply |
| Set-PimManagerAccess.ps1, Set-PimBreakGlassAccounts.ps1, Set-PimEmergencyPassphrase.ps1, Copy-PimSettings.ps1, Import-PimPermissionTemplate.ps1, Register-PimManagedTenant.ps1, Deploy-PimUpdateJob.ps1 | Settings and component scripts the GUI names | SQL admin / Owner on the resource as each states | Product settings; the named component | -WhatIf (honoured) |
| Set-PimManagerMcpAuth.ps1, Set-PimRfaBrokerApiAuth.ps1, Upgrade-PimToPro.ps1 | MCP sign-in, access-request API sign-in, edition upgrade | Application Administrator; Owner on the app | App registration settings; edition | -Apply switch (plan otherwise) |
| Import-PimEnvironmentBackup.ps1, Update-PimCommunity.ps1, Initialize-PimTenantStore.ps1 | Restore a backup; manual update; store init | SQL admin; repository write | As named | Import plans first (-Apply); others -WhatIf |
| Hybrid worker scripts (Initialize-PimHybridWorkerAd, Install-PimHybridWorker, New-PimHybridWorkerInfra, Grant-PimHybridWorkerAccess, Set-PimHybridWorkerEgress) | On-premises AD worker | Domain Admin (AD delegation, GPO); Owner on the worker resources | gMSAs, AD delegations, server GPO, VM, identity grants (chapter 3) | -WhatIf in all except Install-PimHybridWorker, which writes a transcript and verifies the PowerShell installer's signature |
Published scripts and their checksums
Every PIM Manager script Invardia publishes at invardia.com/support/pim/, with its documentation page (what it does, the rights it needs, every change it makes, -WhatIf and undo) and the SHA-256 of the exact published file, computed when this page was built.
Always check the SHA-256 before you run a script.
| Script | Version | SHA-256 | Documentation |
|---|---|---|---|
| Deploy-PimActivatorBackend | 3.0.70 | 0b105a62f44d33a5ca6443c942c6c54727276e215560fd55672440f26996f9c3 | Current |
| Deploy-PimActivatorClient | 3.0.70 | 094dab2d43e03c05292b03efd63bfb2f13864be9eb0dc187c1d6f334f038b903 | Current |
| Deploy-PimHybridWorker | 3.0.70 | 0af9f1e2f40032dc5db98114ca974c68588b8bac90bf82e4de4b124ee2e73c30 | Current |
| Grant-PimEnginePermissions | 3.0.70 | 8d3832e924b73355d63e6cd0a19c40460c0158be1909ef8f2be2b689ec4a430f | Current |
| Grant-PimSupportSqlAccess | 3.0.70 | c174e1f10afca8d8d7e1d08ce0e61f361719dc3d7b4683f931103636cd29ac63 | Current |
| Import-PimV1Data | 3.0.70 | 5e88f699e1340eedede3937c87ffc28fee7fe4996769155e0c7acd41a672b424 | Current |
| Initialize-PimHybridWorkerAd | 3.0.70 | bf9d009f1fcf1d22c60dd6c0ee38cc2663f3b8d5f48a736c31d6f355d341e525 | Current |
| Initialize-PimMailSender | 3.0.70 | 7e8d17a5b1f0737584ef7c149664c8ced97ec5c9da7ed4d9beeeca94ee7bdef1 | Current |
| Initialize-PimSqlAdminGroup | 3.0.70 | 440410cb3be56bc5e61151ddba7988a1db7fab917fe5b3ec8499cc84a1557ba7 | Current |
| Initialize-PimWorkloadPrereqs | 3.0.70 | e3df9140b17c2274a42fe74cb3a557a1d54fcd54b5760cb11bd76a4a872cd696 | Current |
| Install-PimHybridWorker | 3.0.70 | 056ad3124e6c82876424222679fa49fc05b0b1c34a2c59b176e69bc5e2292a6c | Current |
| Invoke-PimSupportSqlAccessJob | 3.0.70 | d1b58b76afa6869d7f202705883652fb444589eeca4f9892b32c4542c7920765 | Current |
| New-PimHubPrepareScript | 3.0.70 | fb69f87006f2059cb43884402d03415d7a422bc87d13f67a870dffb639fcf272 | Current |
| Publish-PimActivatorRemediation | 3.0.70 | 575832f63a8c3011704b0c6362a181d9da2b0b39506eecf10f6fe53b39494207 | Current |
| Set-PimLicense | 3.0.70 | 436ee1d75fd9e5af2df3533e8effcbe6d1b153c3a969b9d1c47d3ed023210daf | Current |
| Set-PimSigninFrontSqlState | 3.0.70 | 89f6f395eb7636babcb480286617a1614f19b7bd8ef1598c9878fadb0ae89660 | Current |
| Set-PimSmtpRelayPassword | 3.0.70 | d4c3cf438d00af14d53f7f95af08299e7609c4f5789415f09a14fe3a86aba6b2 | Current |
| Set-PimSqlTier | 3.0.70 | 0d43d2757d5c66b56765780f9a95dbb58fe4e42227c9c8fbc0616a1c16f39812 | Current |
| Start-PimManagerInstall | 3.0.70 | f2d532d36411bb5cfecef829c97913c55b267bfbebb330f5a39e2572dff47c94 | Current |
Download, read, run
Never pipe a script into Invoke-Expression. Download it to a file (line 1), read it, preview with -WhatIf (line 2), then run the same line without -WhatIf:
Invoke-WebRequest https://invardia.com/support/pim/<Script>.ps1 -OutFile <Script>.ps1
.\<Script>.ps1 -WhatIfTo check a download, compare its SHA-256 (Get-FileHash) with the publishedSHA256SUMS.txt or the table above.
Each script's page shows these commands with its own name. All scripts: PIM Manager scripts · Every setting explained: PIM Manager settings