Skip to content

Commit 497b750

Browse files
committed
app approval template support
1 parent 75e73ce commit 497b750

File tree

4 files changed

+113
-38
lines changed

4 files changed

+113
-38
lines changed

Modules/CIPPCore/Public/Add-CIPPApplicationPermission.ps1

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ function Add-CIPPApplicationPermission {
22
[CmdletBinding()]
33
param(
44
$RequiredResourceAccess,
5+
$TemplateId,
56
$ApplicationId,
67
$Tenantfilter
78
)
@@ -31,7 +32,34 @@ function Add-CIPPApplicationPermission {
3132

3233
$RequiredResourceAccess.Add($Resource)
3334
}
35+
} else {
36+
if (!$RequiredResourceAccess -and $TemplateId) {
37+
Write-Information "Adding application permissions for template $TemplateId"
38+
$TemplateTable = Get-CIPPTable -TableName 'templates'
39+
$Filter = "RowKey eq '$TemplateId' and PartitionKey eq 'AppApprovalTemplate'"
40+
$Template = (Get-CIPPAzDataTableEntity @TemplateTable -Filter $Filter).JSON | ConvertFrom-Json -ErrorAction SilentlyContinue
41+
$ApplicationId = $Template.AppId
42+
$Permissions = $Template.Permissions
43+
$RequiredResourceAccess = [System.Collections.Generic.List[object]]::new()
44+
foreach ($AppId in $Permissions.PSObject.Properties.Name) {
45+
$AppPermissions = @($Permissions.$AppId.applicationPermissions)
46+
$Resource = @{
47+
resourceAppId = $AppId
48+
resourceAccess = [System.Collections.Generic.List[object]]::new()
49+
}
50+
foreach ($Permission in $AppPermissions) {
51+
$Resource.ResourceAccess.Add(@{
52+
id = $Permission.id
53+
type = 'Role'
54+
})
55+
}
56+
57+
$RequiredResourceAccess.Add($Resource)
58+
}
59+
}
3460
}
61+
62+
3563
$ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -skipTokenCache $true -tenantid $Tenantfilter -NoAuthCheck $true
3664
$ourSVCPrincipal = $ServicePrincipalList | Where-Object -Property AppId -EQ $ApplicationId
3765
if (!$ourSVCPrincipal) {
@@ -59,7 +87,7 @@ function Add-CIPPApplicationPermission {
5987
}
6088
}
6189
foreach ($SingleResource in $App.ResourceAccess | Where-Object -Property Type -EQ 'Role') {
62-
if ($SingleResource.id -In $CurrentRoles.appRoleId) { continue }
90+
if ($SingleResource.id -in $CurrentRoles.appRoleId) { continue }
6391
[pscustomobject]@{
6492
principalId = $($ourSVCPrincipal.id)
6593
resourceId = $($svcPrincipalId.id)

Modules/CIPPCore/Public/Add-CIPPDelegatedPermission.ps1

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ function Add-CIPPDelegatedPermission {
22
[CmdletBinding()]
33
param(
44
$RequiredResourceAccess,
5+
$TemplateId,
56
$ApplicationId,
67
$NoTranslateRequired,
78
$Tenantfilter
@@ -40,7 +41,34 @@ function Add-CIPPDelegatedPermission {
4041
# remove the partner center permission if not pushing to partner tenant
4142
$RequiredResourceAccess = $RequiredResourceAccess | Where-Object { $_.resourceAppId -ne 'fa3d9a0c-3fb0-42cc-9193-47c7ecd2edbd' }
4243
}
44+
} else {
45+
if (!$RequiredResourceAccess -and $TemplateId) {
46+
Write-Information "Adding delegated permissions for template $TemplateId"
47+
$TemplateTable = Get-CIPPTable -TableName 'templates'
48+
$Filter = "RowKey eq '$TemplateId' and PartitionKey eq 'AppApprovalTemplate'"
49+
$Template = (Get-CIPPAzDataTableEntity @TemplateTable -Filter $Filter).JSON | ConvertFrom-Json -ErrorAction SilentlyContinue
50+
$ApplicationId = $Template.AppId
51+
$Permissions = $Template.Permissions
52+
$NoTranslateRequired = $true
53+
$RequiredResourceAccess = [System.Collections.Generic.List[object]]::new()
54+
foreach ($AppId in $Permissions.PSObject.Properties.Name) {
55+
$DelegatedPermissions = @($Permissions.$AppId.delegatedPermissions)
56+
$ResourceAccess = [System.Collections.Generic.List[object]]::new()
57+
foreach ($Permission in $DelegatedPermissions) {
58+
$ResourceAccess.Add(@{
59+
id = $Permission.value
60+
type = 'Scope'
61+
})
62+
}
63+
$Resource = @{
64+
resourceAppId = $AppId
65+
resourceAccess = @($ResourceAccess)
66+
}
67+
$RequiredResourceAccess.Add($Resource)
68+
}
69+
}
4370
}
71+
4472
$Translator = Get-Content '.\PermissionsTranslator.json' | ConvertFrom-Json
4573
$ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=appId,id,displayName&`$top=999" -tenantid $Tenantfilter -skipTokenCache $true -NoAuthCheck $true
4674
$ourSVCPrincipal = $ServicePrincipalList | Where-Object -Property appId -EQ $ApplicationId
@@ -66,6 +94,7 @@ function Add-CIPPDelegatedPermission {
6694
}
6795

6896
$DelegatedScopes = $App.resourceAccess | Where-Object -Property type -EQ 'Scope'
97+
6998
if ($NoTranslateRequired) {
7099
$NewScope = @($DelegatedScopes | ForEach-Object { $_.id } | Sort-Object -Unique) -join ' '
71100
} else {

Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-ExecAppApprovalTemplate.ps1

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,23 @@ function Push-ExecAppApprovalTemplate {
88
try {
99
$Item = $Item | ConvertTo-Json -Depth 10 | ConvertFrom-Json
1010
$TemplateId = $Item.templateId
11-
12-
$TemplateTable = Get-CIPPTable -TableName 'templates'
13-
$Filter = "RowKey eq '$TemplateId' and PartitionKey eq 'AppApprovalTemplate'"
14-
$Template = (Get-CIPPAzDataTableEntity @TemplateTable -Filter $Filter).JSON | ConvertFrom-Json -ErrorAction SilentlyContinue
15-
16-
if (!$Template) {
17-
Write-LogMessage -message "Template $TemplateId not found" -tenant $Item.Tenant -API 'Add Multitenant App' -sev Error
11+
if (!$TemplateId) {
12+
Write-LogMessage -message 'No template specified' -tenant $Item.Tenant -API 'Add Multitenant App' -sev Error
1813
return
1914
}
2015

21-
$Permissions = $Template.Permissions
22-
23-
Write-Host "$($Item | ConvertTo-Json -Depth 10)"
2416
$ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -tenantid $Item.Tenant
2517
if ($Item.AppId -notin $ServicePrincipalList.appId) {
18+
Write-Information "Adding $($Item.AppId) to tenant $($Item.Tenant)."
2619
$PostResults = New-GraphPostRequest 'https://graph.microsoft.com/beta/servicePrincipals' -type POST -tenantid $Item.tenant -body "{ `"appId`": `"$($Item.appId)`" }"
2720
Write-LogMessage -message "Added $($Item.AppId) to tenant $($Item.Tenant)" -tenant $Item.Tenant -API 'Add Multitenant App' -sev Info
2821
} else {
2922
Write-LogMessage -message "This app already exists in tenant $($Item.Tenant). We're adding the required permissions." -tenant $Item.Tenant -API 'Add Multitenant App' -sev Info
3023
}
31-
Add-CIPPApplicationPermission -RequiredResourceAccess ($Item.applicationResourceAccess) -ApplicationId $Item.AppId -Tenantfilter $Item.Tenant
32-
Add-CIPPDelegatedPermission -RequiredResourceAccess ($Item.DelegateResourceAccess) -ApplicationId $Item.AppId -Tenantfilter $Item.Tenant
24+
Add-CIPPApplicationPermission -TemplateId $TemplateId -Tenantfilter $Item.Tenant
25+
Add-CIPPDelegatedPermission -TemplateId $TemplateId -Tenantfilter $Item.Tenant
3326
} catch {
3427
Write-LogMessage -message "Error adding application to tenant $($Item.Tenant) - $($_.Exception.Message)" -tenant $Item.Tenant -API 'Add Multitenant App' -sev Error
28+
Write-Error $_.Exception.Message
3529
}
3630
}

Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Application Approval/Invoke-ExecAddMultiTenantApp.ps1

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -33,26 +33,30 @@ function Invoke-ExecAddMultiTenantApp {
3333

3434
$TenantCount = ($TenantFilter | Measure-Object).Count
3535
$Queue = New-CippQueueEntry -Name 'Application Approval' -TotalTasks $TenantCount
36-
foreach ($Tenant in $TenantFilter) {
37-
try {
38-
$InputObject = @{
39-
OrchestratorName = 'ExecMultiTenantAppOrchestrator'
40-
Batch = @([pscustomobject]@{
41-
FunctionName = $Command
42-
Tenant = $tenant
43-
AppId = $Request.Body.AppId
44-
applicationResourceAccess = $ApplicationResourceAccess
45-
delegateResourceAccess = $DelegateResourceAccess
46-
QueueId = $Queue.RowKey
47-
})
48-
SkipLog = $true
49-
}
50-
$null = Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($InputObject | ConvertTo-Json -Depth 5 -Compress)
51-
"Queued application to tenant $Tenant. See the logbook for deployment details"
52-
} catch {
53-
"Error queuing application to tenant $Tenant - $($_.Exception.Message)"
36+
$Batch = foreach ($Tenant in $TenantFilter) {
37+
[pscustomobject]@{
38+
FunctionName = $Command
39+
Tenant = $tenant
40+
AppId = $Request.Body.AppId
41+
applicationResourceAccess = $ApplicationResourceAccess
42+
delegateResourceAccess = $DelegateResourceAccess
43+
QueueId = $Queue.RowKey
5444
}
5545
}
46+
47+
try {
48+
$InputObject = @{
49+
OrchestratorName = 'ExecMultiTenantAppOrchestrator'
50+
Batch = @($Batch)
51+
SkipLog = $true
52+
}
53+
$null = Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($InputObject | ConvertTo-Json -Depth 5 -Compress)
54+
$Results = 'Deploying {0} to {1}, see the logbook for details' -f $Request.Body.AppId, ($Request.Body.tenantFilter.label -join ', ')
55+
} catch {
56+
$ErrorMsg = Get-NormalizedError -message $($_.Exception.Message)
57+
$Results = "Function Error: $ErrorMsg"
58+
}
59+
5660
$StatusCode = [HttpStatusCode]::OK
5761
} catch {
5862
$ErrorMsg = Get-NormalizedError -message $($_.Exception.Message)
@@ -61,14 +65,34 @@ function Invoke-ExecAddMultiTenantApp {
6165
}
6266
} elseif ($Request.Body.configMode -eq 'template') {
6367
Write-Information 'Application Approval - Template Mode'
64-
Write-Information ($Request.Body | ConvertTo-Json -Depth 5)
65-
66-
67-
68-
69-
68+
if ('allTenants' -in $Request.Body.tenantFilter.value) {
69+
$TenantFilter = (Get-Tenants).defaultDomainName
70+
} else {
71+
$TenantFilter = $Request.Body.tenantFilter.value
72+
}
73+
$TenantCount = ($TenantFilter | Measure-Object).Count
74+
$Queue = New-CippQueueEntry -Name 'Application Approval (Template)' -TotalTasks $TenantCount
7075

71-
$Results = 'Deploying {0} to {1}' -f $Request.Body.selectedTemplate.label, ($Request.Body.tenantFilter.label -join ', ')
76+
$Batch = foreach ($Tenant in $TenantFilter) {
77+
[pscustomobject]@{
78+
FunctionName = 'ExecAppApprovalTemplate'
79+
Tenant = $tenant
80+
TemplateId = $Request.Body.selectedTemplate.value
81+
AppId = $Request.Body.selectedTemplate.addedFields.AppId
82+
QueueId = $Queue.RowKey
83+
}
84+
}
85+
try {
86+
$InputObject = @{
87+
OrchestratorName = 'ExecMultiTenantAppOrchestrator'
88+
Batch = @($Batch)
89+
SkipLog = $true
90+
}
91+
$null = Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($InputObject | ConvertTo-Json -Depth 5 -Compress)
92+
$Results = 'Deploying {0} to {1}, see the logbook for details' -f $Request.Body.selectedTemplate.label, ($Request.Body.tenantFilter.label -join ', ')
93+
} catch {
94+
$Results = "Error queuing application - $($_.Exception.Message)"
95+
}
7296
$StatusCode = [HttpStatusCode]::OK
7397
}
7498

0 commit comments

Comments
 (0)