#Requires -Version 7.0 # PIM Manager 3.0.70 -- Grant-PimSupportSqlAccess.ps1, standalone (built by tools/setup/Build-PimSupportScripts.ps1; helpers inlined: _pimscriptdoc.ps1, ..\..\engine\_shared\pim-rest.ps1, pim-loopbackanswer.ps1, ..\..\engine\_shared\pim-sqlstore.ps1, _pimsignedin.ps1, _pimsupportsqlaccess.ps1, ..\..\engine\_shared\pim-supportjit.ps1) <# .SYNOPSIS Gives the Invardia Support app its read-only access to the database of an existing PIM Manager installation: its own database user (created from the application's client id) in the read role pim_support_read, and the support access step that gives admin rights only inside an open support session. Run once per installation; -WhatIf shows it first. .DESCRIPTION PIM REQUIREMENTS 100.116 (framework 4.1b, SECAUDIT-1a). A new installation does this by itself when a Support app is named. This script brings an EXISTING installation to the same state. It changes nothing else, and it leaves the SQL server's administrator and its firewall exactly as it found them. What it does, in order: 1. Reads and keeps the SQL server's Microsoft Entra administrator and its Entra-only setting, and reads the setup firewall rule 'AllowSetupHost'. Prints them ("before"). 2. Reads whether the Invardia Support app is a member of the SQL admin group (grp-pim-sql-admins). It never adds it. A membership an earlier version gave is shown as a WARNING and left as found. 3. Opens the firewall rule 'AllowSetupHost' for this machine's public address, when it is not there. A rule that is already there for another address stops the run (another setup may be using it); nothing is changed. 4. Signs in to the database as you. When the database refuses AND this window is the Invardia Support app's session, the Support app is made the server's administrator FOR THIS STEP, and the script waits until a database sign-in answers. 5. Installs the support access step with the consent level (-ConsentLevel; without it the level already recorded, else troubleshoot): the database user from the Support app's client id when no user has that id (an existing user of the Support app is reused whatever its name), in pim_support_read only. Reads it back. A database owner role an earlier version gave is shown as a WARNING and left as found; it is never added. 6. ALWAYS, also after a failed step: puts the server's administrator back exactly as read and reads it back; removes the firewall rule it opened and reads that back. 7. Proof: in a Support session, a new database sign-in as the Support app. Otherwise it says "not checked" and why; the evidence is then the user and its role, read back. Prints "before" and "after", and what it restored. Admin rights: consent 'setup' lets Invardia support open a support session (at most 8 hours) that adds the database owner role until its end; consent 'troubleshoot' is read-only. Outside a session the Support app reads only. Sign-in: the Invardia Support app's session open in this window, otherwise your own browser sign-in. No Azure CLI, no PowerShell module, no secret on the command line. Every token is pinned to -TenantId. Exit codes: 0 done (warnings allowed); 1 not done (the reason and the next step are printed); 2 the server's administrator could NOT be put back -- the exact values to set by hand are printed. .EXAMPLE .\Grant-PimSupportSqlAccess.ps1 -TenantId -SubscriptionId -ResourceGroup rg-pim -SqlServerName sql-pim-contoso -SupportAppId -WhatIf Preview: reads everything and prints what it would do. Then the same command without -WhatIf. .NOTES Requirements: PowerShell: 7.0 or later (pwsh). Windows PowerShell 5.1 is not supported. Role: SQL Server Contributor (or Contributor / Owner) on the PIM SQL server or its resource group (Azure); a database owner -- a member of the SQL admin group or the server's Microsoft Entra administrator. Hosts: login.microsoftonline.com, management.azure.com, graph.microsoft.com, *.database.windows.net (port 1433), api.ipify.org (this machine's public address, unless -SetupHostIp is given) PERMISSIONS AND CHANGES (from Grant-PimSupportSqlAccess.ps1 manifest, PIM Manager 3.0.70; full page: https://invardia.com/docs/pim/scripts/Grant-PimSupportSqlAccess/) The person running it needs: - SQL Server Contributor (or Contributor / Owner) [azureRbac, the PIM SQL server (or its resource group)] -- Reads the server, its Microsoft Entra administrator and its firewall rules; opens and removes the one firewall rule 'AllowSetupHost'; and, only in the Support app's own session when the database refuses the sign-in, changes the server's administrator for the step and puts it back. - A database owner: a member of the SQL admin group (grp-pim-sql-admins) or the server's Microsoft Entra administrator [other, the PIM database] -- Installs the support access step: the read role, the consent level, the Support app's database user in the read role. In the Invardia Support app's own session this is not needed: the Support app is made the server's administrator for the step. - The Invardia Support app's session in this window, or your own browser sign-in [other, the target tenant and subscription] -- A session of another tenant than -TenantId, or of another application than -SupportAppId, is refused. No Azure CLI, no PowerShell modules, no secret on the command line. What it creates, changes or grants: - grant a database user for the Invardia Support app, created from the application's client id (CREATE USER ... WITH SID, never FROM EXTERNAL PROVIDER) when no user has that id; an existing user of the Support app is reused whatever its name (The PIM database): pim_support_read (SELECT on the product schemas only) @ the one PIM database (-SqlDatabase, default PimPlatform) -- Invardia support reads the store to troubleshoot. This is the Support app's only standing database right; with consent 'setup' a support session adds the database owner role until its end (at most 8 hours) and takes it back by itself. The run never adds the database owner role or a SQL admin group membership; one an earlier version gave is shown as a warning and left as found. Undo: Run Grant-PimSupportAccess.ps1 -Remove (drops the user), or switch the Invardia Support app off in Microsoft Entra ID, which ends the access at once. - create the support access step: the read role pim_support_read, the consent level (-ConsentLevel, else the level already recorded, else troubleshoot) and the signed procedures that open and close a support session (their signer certificate is a db_owner member; EXECUTE on the close and the state read for the product's own pim_engine, pim_web and pim_updater roles) (The PIM database) @ the one PIM database -- The same step a new installation takes when a Support app is named. A support session with consent 'setup' adds db_owner to the Support app's user until its end and takes it back by itself. Undo: Run Grant-PimSupportAccess.ps1 -Remove; the consent level is changed with -ConsentLevel. - create the firewall rule 'AllowSetupHost' for this machine's public address, only when it is not there yet; removed again at the end of the run and read back, also after a failed step (Azure SQL server) @ the PIM SQL server -- The database steps connect from this machine. Undo: None needed: the run removes it. If the run is killed: Azure portal > the SQL server > Networking > Firewall rules: delete 'AllowSetupHost'. - update the server's Microsoft Entra administrator, set to the Invardia Support app FOR THE STEP -- only in the Support app's own session and only when the database refuses its sign-in; put back exactly as it was read (login, id, type, tenant, Entra-only setting) and read back, also after a failed step (Azure SQL server) @ the PIM SQL server -- An application that is only a member of the administrator group has not been accepted by the database on the servers this was measured on; as the administrator it can create its own database user. Undo: None needed: the run puts it back and proves it. Exit code 2 means it could not: the values to set by hand are printed (Azure portal > the SQL server > Microsoft Entra ID > Set admin). -WhatIf: Signs in, reads the SQL server (administrator, Entra-only setting, firewall rule), the Support app and the SQL admin group, prints 'before', and prints one 'What if:' line for each thing it would do: open and remove the firewall rule, make the Support app the administrator for the step (only in a Support session, only when refused) and put the administrator back, install the support access step with the database user in pim_support_read only. It does not connect to the database. Nothing is changed. Undo: Run Grant-PimSupportAccess.ps1 -Remove (drops the database user), or switch the Invardia Support app off in Microsoft Entra ID. The firewall rule and the server's administrator are put back by the run itself. .LINK https://invardia.com/docs/pim/scripts/Grant-PimSupportSqlAccess/ #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)][ValidatePattern('^[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}$')][string]$TenantId, [Parameter(Mandatory)][ValidatePattern('^[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}$')][string]$SubscriptionId, # the resource group of the SQL server [Parameter(Mandatory)][string]$ResourceGroup, # the SQL server name or its FQDN (sql-x or sql-x.database.windows.net) [Parameter(Mandatory)][string]$SqlServerName, [string]$SqlDatabase = 'PimPlatform', # the Invardia Support app's application (client) id. In the Support app's own session it may be left out. [ValidatePattern('^$|^[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}$')][string]$SupportAppId = '', [string]$DbUserName = 'invardia-support', [string]$SqlAdminGroupName = 'grp-pim-sql-admins', # this machine's public address for the firewall rule; without it the address is read from api.ipify.org [ValidatePattern('^$|^\d{1,3}(\.\d{1,3}){3}$')][string]$SetupHostIp = '', [ValidateRange(20, 1800)][int]$SignInWaitSeconds = 300, # the consent level recorded with the read-only user: troubleshoot (read only) or setup (admin only inside an open # support session); without it the level already recorded on this installation, else troubleshoot [ValidateSet('', 'troubleshoot', 'setup')][string]$ConsentLevel = '', # --- test seams (tests/Test-PimSupportSqlAccess.ps1); omit them for a real run --- [scriptblock]$Arm, [scriptblock]$Graph, [scriptblock]$Sql, [scriptblock]$Sleep ) $ErrorActionPreference = 'Stop' # Published as ONE standalone file (https://invardia.com/support/pim/Grant-PimSupportSqlAccess.ps1): every helper is # dot-sourced by a literal path relative to this script's folder, so Build-PimSupportScripts.ps1 inlines it. The next line # tells the build to leave out the OPTIONAL loads the engine libraries end with and to fail on any load left. # BUILD-NO-OPTIONAL-LOADS # ===== BEGIN inlined helper: _PimScriptDoc.ps1 ===== <# .SYNOPSIS Framework 12.7 SCRIPT-DOC-1 + 12.10 item 11 -- the ONE place that knows where a PIM script's documentation page, download and checksum list live, the command form every surface shows (line 1 download, line 2+ run -- owner 2026-10-11), and the run frame every script a person runs uses (the first line "