@@ -197,88 +197,44 @@ function Get-CippSamPermissions {
197197 }
198198 }
199199
200- # Diff the effective set against what is actually GRANTED on the partner CIPP-SAM enterprise
201- # application (service principal): appRoleAssignments for application (Role) permissions and
202- # oauth2PermissionGrants for delegated (Scope) permissions. The app registration's
203- # requiredResourceAccess is intentionally NOT used - permissions are applied as SP grants, so the
204- # grants are the real source of truth for what the app can do.
205- # MissingPermissions = effective perms not yet granted on the SP (need to be added).
206- # PartnerAppDiff also surfaces extra grants on the SP that are not in the effective set.
200+ # Diff the manifest-required base against the saved AppPermissions table. The table records what has
201+ # been applied to the CIPP-SAM app - the repair/update flow persists it as manifest ∪ extras - so it
202+ # stands in for the "current" permission set and no partner-tenant Graph call is needed here.
203+ # MissingPermissions = manifest-required perms not yet present in the table (a Permissions repair is needed).
204+ # PartnerAppDiff mirrors MissingPermissions in the shape the SAM permissions page expects.
207205 $MissingPermissions = @ {}
208206 $PartnerAppDiff = @ {}
209207 if (! $NoDiff.IsPresent ) {
210- try {
211- $PartnerSP = New-GraphGETRequest - uri " https://graph.microsoft.com/beta/servicePrincipals(appId='$ ( $env: ApplicationID ) ')?`$ select=id" - tenantid $env: TenantID - NoAuthCheck $true
212- $AppRoleAssignments = New-GraphGETRequest - uri " https://graph.microsoft.com/beta/servicePrincipals/$ ( $PartnerSP.id ) /appRoleAssignments?`$ top=999" - tenantid $env: TenantID - NoAuthCheck $true
213- $OAuthGrants = New-GraphGETRequest - uri " https://graph.microsoft.com/beta/servicePrincipals/$ ( $PartnerSP.id ) /oauth2PermissionGrants?`$ top=999" - tenantid $env: TenantID - NoAuthCheck $true
214-
215- # Grants reference the resource SP's object id; map it back to the resource appId the
216- # effective set is keyed on. Use $UsedServicePrincipals - it carries both id and appId
217- # ($ServicePrincipals is selected without id, so its .id is null).
218- $ResourceIdToAppId = @ {}
219- foreach ($SP in $UsedServicePrincipals ) { if ($SP.id ) { $ResourceIdToAppId [$SP.id ] = $SP.appId } }
220-
221- # Granted application roles (GUIDs) per resource appId.
222- $GrantedRoleIdsByApp = @ {}
223- foreach ($Assignment in $AppRoleAssignments ) {
224- $ResAppId = $ResourceIdToAppId [$Assignment.resourceId ]
225- if (! $ResAppId -or ! $Assignment.appRoleId ) { continue }
226- if (-not $GrantedRoleIdsByApp.ContainsKey ($ResAppId )) { $GrantedRoleIdsByApp [$ResAppId ] = [System.Collections.Generic.List [string ]]::new() }
227- $GrantedRoleIdsByApp [$ResAppId ].Add([string ]$Assignment.appRoleId )
228- }
208+ foreach ($AppId in $AllAppIds ) {
209+ $ManifestApp = $ManifestPermissions .$AppId
210+ $SavedApp = $SavedPermissions .$AppId
229211
230- # Granted delegated scope NAMES per resource appId (oauth2 grants store space-delimited names).
231- $GrantedScopesByApp = @ {}
232- foreach ($Grant in $OAuthGrants ) {
233- $ResAppId = $ResourceIdToAppId [$Grant.resourceId ]
234- if (! $ResAppId ) { continue }
235- if (-not $GrantedScopesByApp.ContainsKey ($ResAppId )) { $GrantedScopesByApp [$ResAppId ] = [System.Collections.Generic.List [string ]]::new() }
236- foreach ($ScopeName in @ (($Grant.scope -split ' ' ) | Where-Object { $_ })) { $GrantedScopesByApp [$ResAppId ].Add($ScopeName ) }
237- }
212+ $SavedAppIds = @ ($SavedApp.applicationPermissions.id )
213+ $SavedDelIds = @ ($SavedApp.delegatedPermissions.id )
238214
239- foreach ($AppId in $AllAppIds ) {
240- $ServicePrincipal = $ServicePrincipals | Where-Object - Property appId -EQ $AppId
241- $GrantedRoleIds = @ ($GrantedRoleIdsByApp [$AppId ] | Where-Object { $_ })
242- $GrantedScopeNames = @ ($GrantedScopesByApp [$AppId ] | Where-Object { $_ })
243-
244- # Application (Role) permissions compare by GUID against appRoleAssignments.
245- $EffApp = @ ($EffectivePermissions .$AppId.applicationPermissions | Where-Object { $_.id -match $GuidRegex })
246- # Delegated (Scope) permissions compare by NAME (value) against oauth2 grant scopes -
247- # this covers both GUID-resolved scopes and the string-named AdditionalPermissions.
248- $EffDel = @ ($EffectivePermissions .$AppId.delegatedPermissions )
249- $EffAppIds = @ ($EffApp.id )
250- $EffDelNames = @ ($EffDel.value )
251-
252- $MissingApp = @ (foreach ($Permission in $EffApp ) { if ($GrantedRoleIds -notcontains $Permission.id ) { $Permission } })
253- $MissingDel = @ (foreach ($Permission in $EffDel ) { if ($Permission.value -and $GrantedScopeNames -notcontains $Permission.value ) { $Permission } })
254- $ExtraApp = @ (foreach ($Id in ($GrantedRoleIds | Sort-Object - Unique)) {
255- if ($EffAppIds -notcontains $Id ) {
256- [PSCustomObject ]@ { id = $Id ; value = (($ServicePrincipal.appRoles | Where-Object - Property id -EQ $Id ).value) ?? $Id }
257- }
258- })
259- $ExtraDel = @ (foreach ($Name in ($GrantedScopeNames | Sort-Object - Unique)) {
260- if ($EffDelNames -notcontains $Name ) {
261- [PSCustomObject ]@ { id = $Name ; value = $Name }
262- }
263- })
264-
265- if ($MissingApp.Count -gt 0 -or $MissingDel.Count -gt 0 ) {
266- $MissingPermissions .$AppId = @ {
267- applicationPermissions = $MissingApp
268- delegatedPermissions = $MissingDel
215+ $MissingApp = @ (foreach ($Permission in $ManifestApp.applicationPermissions ) {
216+ if ($Permission.id -and $SavedAppIds -notcontains $Permission.id ) {
217+ [PSCustomObject ]@ { id = $Permission.id ; value = $Permission.value }
269218 }
270- }
271- if ($MissingApp.Count -gt 0 -or $MissingDel.Count -gt 0 -or $ExtraApp.Count -gt 0 -or $ExtraDel.Count -gt 0 ) {
272- $PartnerAppDiff .$AppId = @ {
273- missingApplicationPermissions = $MissingApp
274- missingDelegatedPermissions = $MissingDel
275- extraApplicationPermissions = $ExtraApp
276- extraDelegatedPermissions = $ExtraDel
219+ })
220+ $MissingDel = @ (foreach ($Permission in $ManifestApp.delegatedPermissions ) {
221+ if ($Permission.id -and $SavedDelIds -notcontains $Permission.id ) {
222+ [PSCustomObject ]@ { id = $Permission.id ; value = $Permission.value }
277223 }
224+ })
225+
226+ if ($MissingApp.Count -gt 0 -or $MissingDel.Count -gt 0 ) {
227+ $MissingPermissions .$AppId = @ {
228+ applicationPermissions = $MissingApp
229+ delegatedPermissions = $MissingDel
230+ }
231+ $PartnerAppDiff .$AppId = @ {
232+ missingApplicationPermissions = $MissingApp
233+ missingDelegatedPermissions = $MissingDel
234+ extraApplicationPermissions = @ ()
235+ extraDelegatedPermissions = @ ()
278236 }
279237 }
280- } catch {
281- Write-Information " Failed to retrieve partner enterprise app grants for permission diff: $ ( $_.Exception.Message ) "
282238 }
283239 }
284240
0 commit comments