#Requires -Version 7.2 <# .SYNOPSIS Gives the Entra Policy Suite engine identity (id-eps-engine) the Microsoft Graph permissions and the Exchange right it is missing - or takes one away with -Remove. Every grant is read back. .DESCRIPTION The install grants the engine its rights once. Run this when a right is missing afterwards (an approver granted it later, a feature is switched on that needs it, the install ran as an account that could not grant it) or to take a right away that a feature no longer needs. Only the rights Entra Policy Suite declares for its engine can be granted - anything else is refused. -GraphPermission: the Graph application permissions (none given: every one the engine needs). -Exchange: the Exchange right of the recipient conditions - the application permission Exchange.ManageAsApp plus the Entra role Exchange Recipient Administrator. You sign in in a browser (no module). -WhatIf: the plan - what is there, what would be granted or removed - nothing changed. It prints per right: granted / already there / removed / not there / refused (with the reason), and exits 1 when anything was refused. A new grant reaches the engine's token within about 30 minutes. .EXAMPLE ./Grant-EpsEnginePermissions.ps1 -TenantId -SubscriptionId -WhatIf .EXAMPLE ./Grant-EpsEnginePermissions.ps1 -TenantId -SubscriptionId -GraphPermission Organization.Read.All .EXAMPLE ./Grant-EpsEnginePermissions.ps1 -TenantId -SubscriptionId -Exchange -Remove .LINK https://invardia.com/docs/eps/scripts/Grant-EpsEnginePermissions #> # PUBLISHED as a self-contained launcher of Grant-EpsEnginePermissions.ps1 (EntraPolicySuite 2.0.107, Publish-EpsHandover): it runs release 2.0.107 unless -EpsVersion picks another. [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)][guid]$TenantId, [Parameter(Mandatory)][guid]$SubscriptionId, [string]$ResourceGroup = '', [string[]]$GraphPermission = @(), [switch]$Exchange, [switch]$Remove, [ValidatePattern('^$|^2\.\d+\.\d+$')][string]$EpsVersion = '2.0.107' ) $ErrorActionPreference = 'Stop' # A self-contained launcher of Grant-EpsEnginePermissions.ps1 (invardia.com/support/eps/): it downloads the EntraPolicySuite release this script # was handed over for (2.0.107 - the version of your install's ring; -EpsVersion picks another, -EpsVersion '' the # latest), checks it against the release's published SHA-256 digest and runs the release's own Grant-EpsEnginePermissions.ps1 with the # parameters you gave. Nothing is installed on this machine; the download goes to a temporary folder. $what = [bool]$WhatIfPreference; $WhatIfPreference = $false $repo = 'KnudsenMorten/EntraPolicySuite'; $h = @{ 'User-Agent' = 'EntraPolicySuite-support' } $rel = Invoke-RestMethod -Uri $(if ($EpsVersion) { "https://api.github.com/repos/$repo/releases/tags/v$EpsVersion" } else { "https://api.github.com/repos/$repo/releases?per_page=30" }) -Headers $h $rel = @($rel | Where-Object { $_.tag_name -match '^v2\.' -and -not $_.draft -and -not $_.prerelease } | Sort-Object { [version]($_.tag_name.TrimStart('v') -replace '[^0-9.].*$', '') } -Descending)[0] if (-not $rel) { Write-Host 'No EntraPolicySuite v2 release found.' -ForegroundColor Red; exit 3 } $asset = @($rel.assets | Where-Object { $_.name -match '^EntraPolicySuite-v2[0-9A-Za-z.+-]*\.zip$' })[0] if (-not $asset) { Write-Host "Release $($rel.tag_name) has no EntraPolicySuite-v2*.zip." -ForegroundColor Red; exit 3 } $dir = Join-Path ([IO.Path]::GetTempPath()) "eps-$($rel.tag_name)-$([guid]::NewGuid().ToString('N').Substring(0, 6))" New-Item -ItemType Directory -Path $dir | Out-Null $zip = Join-Path $dir $asset.name Invoke-WebRequest -Uri $asset.browser_download_url -OutFile $zip -Headers $h $got = (Get-FileHash -LiteralPath $zip -Algorithm SHA256).Hash.ToLowerInvariant() $published = if ("$($asset.digest)" -match '^(?i)sha256:([0-9a-f]{64})$') { $Matches[1].ToLowerInvariant() } else { '' } if (-not $published -or $got -ne $published) { [IO.Directory]::Delete($dir, $true); Write-Host "The download does not match the release's SHA-256 - deleted, nothing run." -ForegroundColor Red; exit 3 } Write-Host "Release $($rel.tag_name), SHA-256 $got (matches the release)" Expand-Archive -LiteralPath $zip -DestinationPath $dir -Force $script = Get-ChildItem -LiteralPath $dir -Recurse -Filter 'Grant-EpsEnginePermissions.ps1' -File | Select-Object -First 1 if (-not $script) { Write-Host 'The release has no Grant-EpsEnginePermissions.ps1.' -ForegroundColor Red; exit 3 } $pass = @{} foreach ($k in @($PSBoundParameters.Keys)) { if ($k -notin 'EpsVersion', 'WhatIf', 'Confirm') { $pass[$k] = $PSBoundParameters[$k] } } if ($what) { $pass.WhatIf = $true } & $script.FullName @pass exit $LASTEXITCODE