Skip to content

Commit 7c1afbf

Browse files
committed
Use app permissions to update partner tenant sam app else use delegate permissions as fallback
1 parent 913b828 commit 7c1afbf

3 files changed

Lines changed: 48 additions & 16 deletions

File tree

Modules/CIPPCore/Public/Add-CIPPApplicationPermission.ps1

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ function Add-CIPPApplicationPermission {
44
$RequiredResourceAccess,
55
$TemplateId,
66
$ApplicationId,
7-
$TenantFilter
7+
$TenantFilter,
8+
[bool]$AsApp = $false
89
)
910
if ($ApplicationId -eq $env:ApplicationID -and $TenantFilter -eq $env:TenantID) {
1011
$RequiredResourceAccess = 'CIPPDefaults'
@@ -57,22 +58,37 @@ function Add-CIPPApplicationPermission {
5758

5859
Write-Information "Adding application permissions to application $ApplicationId in tenant $TenantFilter"
5960

61+
# Use app auth when requested, but fall back to delegated on the first failure - the app may not
62+
# hold the application permissions needed. $UseAsApp latches to $false for the rest of the run.
63+
$UseAsApp = $AsApp
64+
$GetServicePrincipalList = { New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -skipTokenCache $true -tenantid $TenantFilter -NoAuthCheck $true -AsApp $UseAsApp }
65+
6066
$ServicePrincipalList = [System.Collections.Generic.List[object]]::new()
61-
$SPList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -skipTokenCache $true -tenantid $TenantFilter -NoAuthCheck $true
67+
try {
68+
$SPList = & $GetServicePrincipalList
69+
} catch {
70+
if ($UseAsApp) {
71+
Write-Information "App-auth request failed, falling back to delegated permissions: $($_.Exception.Message)"
72+
$UseAsApp = $false
73+
$SPList = & $GetServicePrincipalList
74+
} else {
75+
throw
76+
}
77+
}
6278
foreach ($SP in $SPList) { $ServicePrincipalList.Add($SP) }
6379
$ourSVCPrincipal = $ServicePrincipalList | Where-Object -Property AppId -EQ $ApplicationId
6480
if (!$ourSVCPrincipal) {
6581
#Our Service Principal isn't available yet. We do a sleep and reexecute after 3 seconds.
6682
Start-Sleep -Seconds 5
6783
$ServicePrincipalList.Clear()
68-
$SPList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -skipTokenCache $true -tenantid $TenantFilter -NoAuthCheck $true
84+
$SPList = & $GetServicePrincipalList
6985
foreach ($SP in $SPList) { $ServicePrincipalList.Add($SP) }
7086
$ourSVCPrincipal = $ServicePrincipalList | Where-Object -Property AppId -EQ $ApplicationId
7187
}
7288

7389
$Results = [System.Collections.Generic.List[string]]::new()
7490

75-
$CurrentRoles = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals/$($ourSVCPrincipal.id)/appRoleAssignments" -tenantid $TenantFilter -skipTokenCache $true -NoAuthCheck $true
91+
$CurrentRoles = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals/$($ourSVCPrincipal.id)/appRoleAssignments" -tenantid $TenantFilter -skipTokenCache $true -NoAuthCheck $true -AsApp $UseAsApp
7692

7793
# Collect missing service principals and prepare bulk request
7894
$MissingServicePrincipals = [System.Collections.Generic.List[object]]::new()
@@ -102,7 +118,7 @@ function Add-CIPPApplicationPermission {
102118
# Create missing service principals in bulk
103119
if ($MissingServicePrincipals.Count -gt 0) {
104120
try {
105-
$BulkResults = New-GraphBulkRequest -Requests $MissingServicePrincipals -tenantid $TenantFilter -NoAuthCheck $true
121+
$BulkResults = New-GraphBulkRequest -Requests $MissingServicePrincipals -tenantid $TenantFilter -NoAuthCheck $true -AsApp $UseAsApp
106122
foreach ($Result in $BulkResults) {
107123
if ($Result.status -eq 201) {
108124
$ServicePrincipalList.Add($Result.body)
@@ -150,7 +166,7 @@ function Add-CIPPApplicationPermission {
150166
}
151167

152168
try {
153-
$BulkResults = New-GraphBulkRequest -Requests $GrantRequests -tenantid $TenantFilter -NoAuthCheck $true
169+
$BulkResults = New-GraphBulkRequest -Requests $GrantRequests -tenantid $TenantFilter -NoAuthCheck $true -AsApp $UseAsApp
154170
foreach ($Result in $BulkResults) {
155171
if ($Result.status -eq 201) {
156172
$counter++

Modules/CIPPCore/Public/Add-CIPPDelegatedPermission.ps1

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ function Add-CIPPDelegatedPermission {
55
$TemplateId,
66
$ApplicationId,
77
$NoTranslateRequired,
8-
$TenantFilter
8+
$TenantFilter,
9+
[bool]$AsApp = $false
910
)
1011
Write-Information 'Adding Delegated Permissions'
1112
$ApplicationId = $ApplicationId ?? $env:ApplicationID
@@ -71,19 +72,34 @@ function Add-CIPPDelegatedPermission {
7172
}
7273

7374
$Translator = Get-Content (Join-Path $env:CIPPRootPath 'Config\PermissionsTranslator.json') | ConvertFrom-Json
74-
$ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=appId,id,displayName&`$top=999" -tenantid $TenantFilter -skipTokenCache $true -NoAuthCheck $true
75+
76+
# Use app auth when requested, but fall back to delegated on the first failure - the app may not
77+
# hold the application permissions needed. $UseAsApp latches to $false for the rest of the run.
78+
$UseAsApp = $AsApp
79+
$GetServicePrincipalList = { New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=appId,id,displayName&`$top=999" -tenantid $TenantFilter -skipTokenCache $true -NoAuthCheck $true -AsApp $UseAsApp }
80+
try {
81+
$ServicePrincipalList = & $GetServicePrincipalList
82+
} catch {
83+
if ($UseAsApp) {
84+
Write-Information "App-auth request failed, falling back to delegated permissions: $($_.Exception.Message)"
85+
$UseAsApp = $false
86+
$ServicePrincipalList = & $GetServicePrincipalList
87+
} else {
88+
throw
89+
}
90+
}
7591
$Results = [System.Collections.Generic.List[string]]::new()
7692

7793
$ourSVCPrincipal = $ServicePrincipalList | Where-Object -Property AppId -EQ $ApplicationId | Select-Object -First 1
7894
if (!$ourSVCPrincipal) {
79-
$ourSvcPrincipal = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals(appId='$ApplicationId')?`$select=appId,id,displayName" -tenantid $TenantFilter -skipTokenCache $true -NoAuthCheck $true
95+
$ourSvcPrincipal = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals(appId='$ApplicationId')?`$select=appId,id,displayName" -tenantid $TenantFilter -skipTokenCache $true -NoAuthCheck $true -AsApp $UseAsApp
8096
}
8197
if (!$ourSVCPrincipal) {
8298
$Results.Add("Failed to find service principal for application $ApplicationId in tenant $TenantFilter")
8399
return $Results
84100
}
85101

86-
$CurrentDelegatedScopes = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals/$($ourSVCPrincipal.id)/oauth2PermissionGrants" -skipTokenCache $true -tenantid $TenantFilter -NoAuthCheck $true
102+
$CurrentDelegatedScopes = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals/$($ourSVCPrincipal.id)/oauth2PermissionGrants" -skipTokenCache $true -tenantid $TenantFilter -NoAuthCheck $true -AsApp $UseAsApp
87103

88104
foreach ($App in $RequiredResourceAccess) {
89105
if (!$App) {
@@ -95,7 +111,7 @@ function Add-CIPPDelegatedPermission {
95111
$Body = @{
96112
appId = $App.resourceAppId
97113
} | ConvertTo-Json -Compress
98-
$svcPrincipalId = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/v1.0/servicePrincipals' -tenantid $TenantFilter -body $Body -type POST -NoAuthCheck $true
114+
$svcPrincipalId = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/v1.0/servicePrincipals' -tenantid $TenantFilter -body $Body -type POST -NoAuthCheck $true -AsApp $UseAsApp
99115
} catch {
100116
$Results.add("Failed to create service principal for $($App.resourceAppId): $(Get-NormalizedError -message $_.Exception.Message)")
101117
continue
@@ -134,7 +150,7 @@ function Add-CIPPDelegatedPermission {
134150
resourceId = $svcPrincipalId.id
135151
scope = $NewScope
136152
} | ConvertTo-Json -Compress
137-
$CreateRequest = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/v1.0/oauth2PermissionGrants' -tenantid $TenantFilter -body $Createbody -type POST -NoAuthCheck $true
153+
$CreateRequest = New-GraphPOSTRequest -uri 'https://graph.microsoft.com/v1.0/oauth2PermissionGrants' -tenantid $TenantFilter -body $Createbody -type POST -NoAuthCheck $true -AsApp $UseAsApp
138154
$Results.add("Successfully added permissions for $($svcPrincipalId.displayName)")
139155
} catch {
140156
$Results.add("Failed to add permissions for $($svcPrincipalId.displayName): $(Get-NormalizedError -message $_.Exception.Message)")
@@ -147,7 +163,7 @@ function Add-CIPPDelegatedPermission {
147163
$OldScope.id | ForEach-Object {
148164
if ($_ -ne $OldScopeId) {
149165
try {
150-
$null = New-GraphPOSTRequest -uri "https://graph.microsoft.com/v1.0/oauth2PermissionGrants/$_" -tenantid $TenantFilter -type DELETE -NoAuthCheck $true
166+
$null = New-GraphPOSTRequest -uri "https://graph.microsoft.com/v1.0/oauth2PermissionGrants/$_" -tenantid $TenantFilter -type DELETE -NoAuthCheck $true -AsApp $UseAsApp
151167
} catch {
152168
}
153169
}
@@ -171,7 +187,7 @@ function Add-CIPPDelegatedPermission {
171187
scope = "$NewScope"
172188
} | ConvertTo-Json -Compress
173189
try {
174-
$null = New-GraphPOSTRequest -uri "https://graph.microsoft.com/v1.0/oauth2PermissionGrants/$($OldScopeId)" -tenantid $TenantFilter -body $Patchbody -type PATCH -NoAuthCheck $true
190+
$null = New-GraphPOSTRequest -uri "https://graph.microsoft.com/v1.0/oauth2PermissionGrants/$($OldScopeId)" -tenantid $TenantFilter -body $Patchbody -type PATCH -NoAuthCheck $true -AsApp $UseAsApp
175191
} catch {
176192
$Results.add("Failed to update permissions for $($svcPrincipalId.displayName): $(Get-NormalizedError -message $_.Exception.Message)")
177193
continue

Modules/CIPPHTTP/Public/Entrypoints/HTTP Functions/CIPP/Settings/Invoke-ExecPermissionRepair.ps1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ function Invoke-ExecPermissionRepair {
2525

2626
# 2) Refresh the grants on the partner CIPP-SAM service principal so the effective set
2727
# (manifest + extras, read from the table) is actually consented on the SP.
28-
$AppResults = Add-CIPPApplicationPermission -RequiredResourceAccess 'CIPPDefaults' -ApplicationId $env:ApplicationID -TenantFilter $env:TenantID
29-
$DelegatedResults = Add-CIPPDelegatedPermission -RequiredResourceAccess 'CIPPDefaults' -ApplicationId $env:ApplicationID -TenantFilter $env:TenantID
28+
$AppResults = Add-CIPPApplicationPermission -RequiredResourceAccess 'CIPPDefaults' -ApplicationId $env:ApplicationID -TenantFilter $env:TenantID -AsApp $true
29+
$DelegatedResults = Add-CIPPDelegatedPermission -RequiredResourceAccess 'CIPPDefaults' -ApplicationId $env:ApplicationID -TenantFilter $env:TenantID -AsApp $true
3030

3131
$Results = @($TableResult) + @($AppResults) + @($DelegatedResults) | Where-Object { $_ }
3232
Write-LogMessage -Headers $Request.Headers -API 'ExecPermissionRepair' -message "CIPP-SAM permissions repaired by $UpdatedBy" -Sev 'Info' -LogData @{ Results = @($Results) }

0 commit comments

Comments
 (0)