Skip to content

Commit 04ce9f6

Browse files
Merge branch 'dev' of https://github.com/KelvinTegelaar/CIPP-API into dev
2 parents 2f6e6ea + fd635b6 commit 04ce9f6

File tree

12 files changed

+259
-90
lines changed

12 files changed

+259
-90
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 {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
function Push-ExecAppApprovalTemplate {
2+
<#
3+
.FUNCTIONALITY
4+
Entrypoint
5+
#>
6+
param($Item)
7+
8+
try {
9+
$Item = $Item | ConvertTo-Json -Depth 10 | ConvertFrom-Json
10+
$TemplateId = $Item.templateId
11+
if (!$TemplateId) {
12+
Write-LogMessage -message 'No template specified' -tenant $Item.Tenant -API 'Add Multitenant App' -sev Error
13+
return
14+
}
15+
16+
$ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -tenantid $Item.Tenant
17+
if ($Item.AppId -notin $ServicePrincipalList.appId) {
18+
Write-Information "Adding $($Item.AppId) to tenant $($Item.Tenant)."
19+
$PostResults = New-GraphPostRequest 'https://graph.microsoft.com/beta/servicePrincipals' -type POST -tenantid $Item.tenant -body "{ `"appId`": `"$($Item.appId)`" }"
20+
Write-LogMessage -message "Added $($Item.AppId) to tenant $($Item.Tenant)" -tenant $Item.Tenant -API 'Add Multitenant App' -sev Info
21+
} else {
22+
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
23+
}
24+
Add-CIPPApplicationPermission -TemplateId $TemplateId -Tenantfilter $Item.Tenant
25+
Add-CIPPDelegatedPermission -TemplateId $TemplateId -Tenantfilter $Item.Tenant
26+
} catch {
27+
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
29+
}
30+
}

Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Standards/Push-CIPPStandard.ps1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ function Push-CIPPStandard {
2121
}
2222
try {
2323
& $FunctionName -Tenant $Item.Tenant -Settings $Item.Settings -ErrorAction Stop
24+
Write-Information "Standard $($Standard) completed for tenant $($Tenant)"
2425
} catch {
26+
Write-LogMessage -API 'Standards' -tenant $Tenant -message "Error running standard $($Standard) for tenant $($Tenant) - $($_.Exception.Message)" -sev Error -LogData (Get-CippException -Exception $_)
27+
Write-Warning "Error running standard $($Standard) for tenant $($Tenant) - $($_.Exception.Message)"
28+
Write-Information $_.InvocationInfo.PositionMessage
2529
throw $_.Exception.Message
2630
}
2731
}

Modules/CIPPCore/Public/Entrypoints/HTTP Functions/CIPP/Core/Invoke-ExecServicePrincipals.ps1

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,32 @@ function Invoke-ExecServicePrincipals {
2020
try {
2121
switch ($Request.Query.Action) {
2222
'Create' {
23+
$BlockList = @(
24+
'e9a7fea1-1cc0-4cd9-a31b-9137ca5deedd', # eM Client
25+
'ff8d92dc-3d82-41d6-bcbd-b9174d163620', # PerfectData Software
26+
'a245e8c0-b53c-4b67-9b45-751d1dff8e6b', # Newsletter Software Supermailer
27+
'b15665d9-eda6-4092-8539-0eec376afd59', # rclone
28+
'a43e5392-f48b-46a4-a0f1-098b5eeb4757', # CloudSponge
29+
'caffae8c-0882-4c81-9a27-d1803af53a40' # SigParser
30+
)
2331
$Action = 'Create'
32+
2433
if ($Request.Query.AppId -match '^[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$') {
25-
$Body = @{
26-
'appId' = $Request.Query.AppId
27-
} | ConvertTo-Json -Compress
28-
try {
29-
$ServicePrincipal = New-GraphPostRequest -Uri 'https://graph.microsoft.com/beta/servicePrincipals' -tenantid $TenantFilter -type POST -body $Body -NoAuthCheck $true
30-
$Results = "Created service principal for $($ServicePrincipal.displayName) ($($ServicePrincipal.appId))"
31-
} catch {
32-
$Results = "Unable to create service principal: $($_.Exception.Message)"
34+
35+
if ($BlockList -contains $Request.Query.AppId) {
36+
$Results = 'Service Principal creation is blocked for this AppId'
3337
$Success = $false
38+
} else {
39+
$Body = @{
40+
'appId' = $Request.Query.AppId
41+
} | ConvertTo-Json -Compress
42+
try {
43+
$ServicePrincipal = New-GraphPostRequest -Uri 'https://graph.microsoft.com/beta/servicePrincipals' -tenantid $TenantFilter -type POST -body $Body -NoAuthCheck $true
44+
$Results = "Created service principal for $($ServicePrincipal.displayName) ($($ServicePrincipal.appId))"
45+
} catch {
46+
$Results = "Unable to create service principal: $($_.Exception.Message)"
47+
$Success = $false
48+
}
3449
}
3550
} else {
3651
$Results = 'Invalid AppId'

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

Lines changed: 71 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -12,51 +12,90 @@ function Invoke-ExecAddMultiTenantApp {
1212
$APIName = $Request.Params.CIPPEndpoint
1313
$Headers = $Request.Headers
1414
Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug'
15-
$DelegateResources = $request.body.permissions | Where-Object -Property origin -EQ 'Delegated' | ForEach-Object { @{ id = $_.id; type = 'Scope' } }
16-
$DelegateResourceAccess = @{ ResourceAppId = '00000003-0000-0000-c000-000000000000'; resourceAccess = $DelegateResources }
17-
$ApplicationResources = $request.body.permissions | Where-Object -Property origin -EQ 'Application' | ForEach-Object { @{ id = $_.id; type = 'Role' } }
18-
$ApplicationResourceAccess = @{ ResourceAppId = '00000003-0000-0000-c000-000000000000'; resourceAccess = $ApplicationResources }
1915

20-
$Results = try {
21-
if ($Request.Body.CopyPermissions -eq $true) {
22-
$Command = 'ExecApplicationCopy'
23-
} else {
24-
$Command = 'ExecAddMultiTenantApp'
25-
}
26-
if ('allTenants' -in $Request.Body.tenantFilter.value) {
27-
$TenantFilter = (Get-Tenants).defaultDomainName
28-
} else {
29-
$TenantFilter = $Request.Body.tenantFilter.value
30-
}
16+
if ($Request.Body.configMode -eq 'manual') {
17+
$DelegateResources = $request.body.permissions | Where-Object -Property origin -EQ 'Delegated' | ForEach-Object { @{ id = $_.id; type = 'Scope' } }
18+
$DelegateResourceAccess = @{ ResourceAppId = '00000003-0000-0000-c000-000000000000'; resourceAccess = $DelegateResources }
19+
$ApplicationResources = $request.body.permissions | Where-Object -Property origin -EQ 'Application' | ForEach-Object { @{ id = $_.id; type = 'Role' } }
20+
$ApplicationResourceAccess = @{ ResourceAppId = '00000003-0000-0000-c000-000000000000'; resourceAccess = $ApplicationResources }
21+
22+
$Results = try {
23+
if ($Request.Body.CopyPermissions -eq $true) {
24+
$Command = 'ExecApplicationCopy'
25+
} else {
26+
$Command = 'ExecAddMultiTenantApp'
27+
}
28+
if ('allTenants' -in $Request.Body.tenantFilter.value) {
29+
$TenantFilter = (Get-Tenants).defaultDomainName
30+
} else {
31+
$TenantFilter = $Request.Body.tenantFilter.value
32+
}
33+
34+
$TenantCount = ($TenantFilter | Measure-Object).Count
35+
$Queue = New-CippQueueEntry -Name 'Application Approval' -TotalTasks $TenantCount
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
44+
}
45+
}
3146

32-
$TenantCount = ($TenantFilter | Measure-Object).Count
33-
$Queue = New-CippQueueEntry -Name 'Application Approval' -TotalTasks $TenantCount
34-
foreach ($Tenant in $TenantFilter) {
3547
try {
3648
$InputObject = @{
3749
OrchestratorName = 'ExecMultiTenantAppOrchestrator'
38-
Batch = @([pscustomobject]@{
39-
FunctionName = $Command
40-
Tenant = $tenant
41-
AppId = $Request.Body.AppId
42-
applicationResourceAccess = $ApplicationResourceAccess
43-
delegateResourceAccess = $DelegateResourceAccess
44-
QueueId = $Queue.RowKey
45-
})
50+
Batch = @($Batch)
4651
SkipLog = $true
4752
}
4853
$null = Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($InputObject | ConvertTo-Json -Depth 5 -Compress)
49-
"Queued application to tenant $Tenant. See the logbook for deployment details"
54+
$Results = 'Deploying {0} to {1}, see the logbook for details' -f $Request.Body.AppId, ($Request.Body.tenantFilter.label -join ', ')
5055
} catch {
51-
"Error queuing application to tenant $Tenant - $($_.Exception.Message)"
56+
$ErrorMsg = Get-NormalizedError -message $($_.Exception.Message)
57+
$Results = "Function Error: $ErrorMsg"
5258
}
59+
60+
$StatusCode = [HttpStatusCode]::OK
61+
} catch {
62+
$ErrorMsg = Get-NormalizedError -message $($_.Exception.Message)
63+
$Results = "Function Error: $ErrorMsg"
64+
$StatusCode = [HttpStatusCode]::BadRequest
65+
}
66+
} elseif ($Request.Body.configMode -eq 'template') {
67+
Write-Information 'Application Approval - Template Mode'
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
75+
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)"
5395
}
5496
$StatusCode = [HttpStatusCode]::OK
55-
} catch {
56-
$ErrorMsg = Get-NormalizedError -message $($_.Exception.Message)
57-
$Results = "Function Error: $ErrorMsg"
58-
$StatusCode = [HttpStatusCode]::BadRequest
5997
}
98+
6099
# Associate values to output bindings by calling 'Push-OutputBinding'.
61100
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
62101
StatusCode = $StatusCode

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,10 @@ function Invoke-ListAppApprovalTemplates {
5353
}
5454
}
5555

56-
Write-LogMessage -headers $Headers -API $APIName -message "Listed App Deployment Templates: $($Body.Count) templates found" -Sev 'Info'
5756
} catch {
5857
$Body = @{
5958
Results = "Failed to list app deployment templates: $($_.Exception.Message)"
6059
}
61-
Write-LogMessage -headers $Headers -API $APIName -message "Failed to list App Deployment Templates: $($_.Exception.Message)" -Sev 'Error'
6260
}
6361

6462
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{

Modules/CIPPCore/Public/Entrypoints/Timer Functions/Start-CIPPGraphSubscriptionRenewalTimer.ps1

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,6 @@ function Start-CIPPGraphSubscriptionRenewalTimer {
77
param()
88

99
if ($PSCmdlet.ShouldProcess('Start-CIPPGraphSubscriptionRenewalTimer', 'Starting Graph Subscription Renewal Timer')) {
10-
try {
11-
Write-LogMessage -API 'Scheduler_RenewGraphSubscriptions' -tenant 'none' -message 'Starting Graph Subscription Renewal' -sev Info
12-
Invoke-CippGraphWebhookRenewal
13-
} catch {
14-
Write-LogMessage -API 'Scheduler_RenewGraphSubscriptions' -tenant 'none' -message 'Failed to renew graph subscriptions' -sev Info
15-
}
10+
Invoke-CippGraphWebhookRenewal
1611
}
1712
}

0 commit comments

Comments
 (0)