From 0676b70f512bbda02f180fb1f1cb4e79c33c256f Mon Sep 17 00:00:00 2001 From: John Duprey Date: Sun, 5 Nov 2023 20:52:29 -0500 Subject: [PATCH 01/55] Routed API calls - Create Z_CIPP triggers for http and queue (Z_ necessary for not overriding existing) - Update GraphRequest functions to use new format --- .../Entrypoints/Invoke-Z_CIPPHttpTrigger.ps1 | 28 +++++++++ .../Push-ListGraphRequestQueue.ps1 | 8 +-- .../Entrypoints/Push-Z_CIPPQueueTrigger.ps1 | 9 +++ .../GraphRequests/Get-GraphRequestList.ps1 | 57 +++++++++---------- .../function.json | 12 +++- .../function.json | 4 +- 6 files changed, 78 insertions(+), 40 deletions(-) create mode 100644 Modules/CIPPCore/Public/Entrypoints/Invoke-Z_CIPPHttpTrigger.ps1 create mode 100644 Modules/CIPPCore/Public/Entrypoints/Push-Z_CIPPQueueTrigger.ps1 rename {ListGraphRequest => Z_CIPPHttpTrigger}/function.json (58%) rename {ListGraphRequestQueue => Z_CIPPQueueTrigger}/function.json (84%) diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-Z_CIPPHttpTrigger.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-Z_CIPPHttpTrigger.ps1 new file mode 100644 index 000000000000..9f0083676d1e --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-Z_CIPPHttpTrigger.ps1 @@ -0,0 +1,28 @@ +function Invoke-Z_CIPPHttpTrigger { + <# + .FUNCTIONALITY + Entrypoint + #> + Param( + $Request, + $TriggerMetadata + ) + + $FunctionName = 'Invoke-{0}' -f $Request.Params.CIPPEndpoint + + Write-Host "Function: $($Request.Params.CIPPEndpoint)" + + $HttpTrigger = @{ + Request = $Request + TriggerMetadata = $TriggerMetadata + } + + if (Get-Command -Name $FunctionName -ErrorAction SilentlyContinue) { + & $FunctionName @HttpTrigger + } else { + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::NotFound + Body = 'Endpoint not found' + }) + } +} \ No newline at end of file diff --git a/Modules/CIPPCore/Public/Entrypoints/Push-ListGraphRequestQueue.ps1 b/Modules/CIPPCore/Public/Entrypoints/Push-ListGraphRequestQueue.ps1 index 426e1538bf15..e5fd7c364d63 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Push-ListGraphRequestQueue.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Push-ListGraphRequestQueue.ps1 @@ -9,7 +9,7 @@ function Push-ListGraphRequestQueue { # Write out the queue message and metadata to the information log. Write-Host "PowerShell queue trigger function processed work item: $($QueueItem.Endpoint) - $($QueueItem.Tenant)" - #Write-Host ($QueueItem | ConvertTo-Json -Depth 5) + $QueueItem = $QueueItem.QueueItem $TenantQueueName = '{0} - {1}' -f $QueueItem.QueueName, $QueueItem.Tenant Update-CippQueueEntry -RowKey $QueueItem.QueueId -Status 'Processing' -Name $TenantQueueName @@ -41,8 +41,7 @@ function Push-ListGraphRequestQueue { $RawGraphRequest = try { Get-GraphRequestList @GraphRequestParams - } - catch { + } catch { [PSCustomObject]@{ Tenant = $QueueItem.Tenant CippStatus = "Could not connect to tenant. $($_.Exception.message)" @@ -63,8 +62,7 @@ function Push-ListGraphRequestQueue { try { Add-CIPPAzDataTableEntity @Table -Entity $GraphResults -Force | Out-Null Update-CippQueueEntry -RowKey $QueueItem.QueueId -Status 'Completed' - } - catch { + } catch { Write-Host "Queue Error: $($_.Exception.Message)" Update-CippQueueEntry -RowKey $QueueItem.QueueId -Status 'Failed' } diff --git a/Modules/CIPPCore/Public/Entrypoints/Push-Z_CIPPQueueTrigger.ps1 b/Modules/CIPPCore/Public/Entrypoints/Push-Z_CIPPQueueTrigger.ps1 new file mode 100644 index 000000000000..da3e22e1885a --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/Push-Z_CIPPQueueTrigger.ps1 @@ -0,0 +1,9 @@ +function Push-Z_CIPPQueueTrigger { + Param($QueueItem, $TriggerMetadata) + $APIName = $QueueItem.FunctionName + + $FunctionName = 'Push-{0}' -f $APIName + if (Get-Command -Name $FunctionName -ErrorAction SilentlyContinue) { + & $FunctionName -QueueItem $QueueItem -TriggerMetadata $TriggerMetadata + } +} \ No newline at end of file diff --git a/Modules/CIPPCore/Public/GraphRequests/Get-GraphRequestList.ps1 b/Modules/CIPPCore/Public/GraphRequests/Get-GraphRequestList.ps1 index 768fb3a81e52..ce5a064cba8e 100644 --- a/Modules/CIPPCore/Public/GraphRequests/Get-GraphRequestList.ps1 +++ b/Modules/CIPPCore/Public/GraphRequests/Get-GraphRequestList.ps1 @@ -72,8 +72,7 @@ function Get-GraphRequestList { if ($QueueNameOverride) { $QueueName = $QueueNameOverride - } - else { + } else { $TextInfo = (Get-Culture).TextInfo $QueueName = $TextInfo.ToTitleCase($DisplayName -csplit '(?=[A-Z])' -ne '' -join ' ') } @@ -94,20 +93,17 @@ function Get-GraphRequestList { $Filter = "QueueId eq '{0}'" -f $QueueId $Rows = Get-CIPPAzDataTableEntity @Table -Filter $Filter $Type = 'Queue' - } - elseif ($TenantFilter -eq 'AllTenants' -or (!$SkipCache.IsPresent -and !$ClearCache.IsPresent -and !$CountOnly.IsPresent)) { + } elseif ($TenantFilter -eq 'AllTenants' -or (!$SkipCache.IsPresent -and !$ClearCache.IsPresent -and !$CountOnly.IsPresent)) { $Table = Get-CIPPTable -TableName $TableName if ($TenantFilter -eq 'AllTenants') { $Filter = "PartitionKey eq '{0}' and QueueType eq 'AllTenants'" -f $PartitionKey - } - else { + } else { $Filter = "PartitionKey eq '{0}' and Tenant eq '{1}'" -f $PartitionKey, $TenantFilter } #Write-Host $Filter $Rows = Get-CIPPAzDataTableEntity @Table -Filter $Filter | Where-Object { $_.Timestamp.DateTime -gt (Get-Date).ToUniversalTime().AddHours(-1) } $Type = 'Cache' - } - else { + } else { $Type = 'None' $Rows = @() } @@ -134,16 +130,14 @@ function Get-GraphRequestList { try { Get-GraphRequestList @GraphRequestParams | Select-Object *, @{l = 'Tenant'; e = { $_.defaultDomainName } }, @{l = 'CippStatus'; e = { 'Good' } } - } - catch { + } catch { [PSCustomObject]@{ Tenant = $_.defaultDomainName CippStatus = "Could not connect to tenant. $($_.Exception.message)" } } } - } - else { + } else { if ($RunningQueue) { Write-Host 'Queue currently running' Write-Host ($RunningQueue | ConvertTo-Json) @@ -152,8 +146,7 @@ function Get-GraphRequestList { QueueId = $RunningQueue.RowKey Queued = $true } - } - else { + } else { $Queue = New-CippQueueEntry -Name "$QueueName (All Tenants)" -Link $CippLink -Reference $QueueReference [PSCustomObject]@{ QueueMessage = 'Loading data for all tenants. Please check back after the job completes' @@ -164,7 +157,7 @@ function Get-GraphRequestList { try { Get-Tenants -IncludeErrors | ForEach-Object { $TenantFilter = $_.defaultDomainName - $QueueTenant = @{ + $QueueTenant = [PSCustomObject]@{ TenantFilter = $TenantFilter Endpoint = $Endpoint QueueId = $Queue.RowKey @@ -176,12 +169,15 @@ function Get-GraphRequestList { NoAuthCheck = $NoAuthCheck.IsPresent ReverseTenantLookupProperty = $ReverseTenantLookupProperty ReverseTenantLookup = $ReverseTenantLookup.IsPresent - } | ConvertTo-Json -Depth 5 -Compress + } - Push-OutputBinding -Name QueueItem -Value $QueueTenant + $QueueItem = [PSCustomObject]@{ + FunctionName = 'ListGraphRequestQueue' + QueueItem = $QueueTenant + } + Push-OutputBinding -Name QueueItem -Value $QueueItem } - } - catch { + } catch { Write-Host "QUEUE ERROR: $($_.Exception.Message)" } } @@ -222,10 +218,9 @@ function Get-GraphRequestList { QueueId = $RunningQueue.RowKey Queued = $true } - } - else { + } else { $Queue = New-CippQueueEntry -Name $QueueName -Link $CippLink -Reference $QueueReference - $QueueTenant = @{ + $QueueTenant = [PSCustomObject]@{ TenantFilter = $TenantFilter Endpoint = $Endpoint QueueId = $Queue.RowKey @@ -236,9 +231,14 @@ function Get-GraphRequestList { NoAuthCheck = $NoAuthCheck.IsPresent ReverseTenantLookupProperty = $ReverseTenantLookupProperty ReverseTenantLookup = $ReverseTenantLookup.IsPresent - } | ConvertTo-Json -Depth 5 -Compress + } + + $QueueItem = [PSCustomObject]@{ + FunctionName = 'ListGraphRequestQueue' + QueueItem = $QueueTenant + } + Push-OutputBinding -Name QueueItem -Value $QueueItem - Push-OutputBinding -Name QueueItem -Value $QueueTenant [PSCustomObject]@{ QueueMessage = ('Loading {0} rows for {1}. Please check back after the job completes' -f $Count, $TenantFilter) QueueId = $Queue.RowKey @@ -257,20 +257,17 @@ function Get-GraphRequestList { foreach ($Result in $GraphRequestResults) { $Result | Select-Object @{n = 'TenantInfo'; e = { $TenantInfo | Where-Object { $Result.$ReverseTenantLookupProperty -eq $_.tenantId } } }, * } - } - else { + } else { $GraphRequestResults } } - } - catch { + } catch { throw $_.Exception } } } - } - else { + } else { $Rows | ForEach-Object { $_.Data | ConvertFrom-Json } diff --git a/ListGraphRequest/function.json b/Z_CIPPHttpTrigger/function.json similarity index 58% rename from ListGraphRequest/function.json rename to Z_CIPPHttpTrigger/function.json index a58da1def32f..8bcb9e5eb526 100644 --- a/ListGraphRequest/function.json +++ b/Z_CIPPHttpTrigger/function.json @@ -1,5 +1,5 @@ { - "scriptFile": "../Modules/CippEntryPoints/CippEntryPoints.psm1", + "scriptFile": "../Modules/CippEntrypoints/CippEntrypoints.psm1", "entryPoint": "Receive-CippHttpTrigger", "bindings": [ { @@ -7,7 +7,8 @@ "type": "httpTrigger", "direction": "in", "name": "Request", - "methods": ["get", "post"] + "methods": ["get", "post"], + "route": "{CIPPEndpoint}" }, { "type": "http", @@ -18,7 +19,12 @@ "type": "queue", "direction": "out", "name": "QueueItem", - "queueName": "GraphRequestQueue" + "queueName": "CIPPGenericQueue" + }, + { + "name": "starter", + "type": "durableClient", + "direction": "in" } ] } diff --git a/ListGraphRequestQueue/function.json b/Z_CIPPQueueTrigger/function.json similarity index 84% rename from ListGraphRequestQueue/function.json rename to Z_CIPPQueueTrigger/function.json index 372b2c5a4b4a..c048325fc313 100644 --- a/ListGraphRequestQueue/function.json +++ b/Z_CIPPQueueTrigger/function.json @@ -1,4 +1,4 @@ -{ +{ "scriptFile": "../Modules/CippEntryPoints/CippEntryPoints.psm1", "entryPoint": "Receive-CippQueueTrigger", "bindings": [ @@ -6,7 +6,7 @@ "name": "QueueItem", "type": "queueTrigger", "direction": "in", - "queueName": "GraphRequestQueue" + "queueName": "CIPPGenericQueue" } ] } From 85d50fb00e38a26f0f16e3755e2bd6b6638ec1ba Mon Sep 17 00:00:00 2001 From: John Duprey Date: Mon, 6 Nov 2023 17:20:23 -0500 Subject: [PATCH 02/55] Update GraphRequest --- .../Entrypoints/Push-ListGraphRequestQueue.ps1 | 2 -- .../Public/GraphRequests/Get-GraphRequestList.ps1 | 14 ++++---------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Push-ListGraphRequestQueue.ps1 b/Modules/CIPPCore/Public/Entrypoints/Push-ListGraphRequestQueue.ps1 index e5fd7c364d63..9bb3b2086bcd 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Push-ListGraphRequestQueue.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Push-ListGraphRequestQueue.ps1 @@ -9,8 +9,6 @@ function Push-ListGraphRequestQueue { # Write out the queue message and metadata to the information log. Write-Host "PowerShell queue trigger function processed work item: $($QueueItem.Endpoint) - $($QueueItem.Tenant)" - $QueueItem = $QueueItem.QueueItem - $TenantQueueName = '{0} - {1}' -f $QueueItem.QueueName, $QueueItem.Tenant Update-CippQueueEntry -RowKey $QueueItem.QueueId -Status 'Processing' -Name $TenantQueueName diff --git a/Modules/CIPPCore/Public/GraphRequests/Get-GraphRequestList.ps1 b/Modules/CIPPCore/Public/GraphRequests/Get-GraphRequestList.ps1 index ce5a064cba8e..c93ebbb06c80 100644 --- a/Modules/CIPPCore/Public/GraphRequests/Get-GraphRequestList.ps1 +++ b/Modules/CIPPCore/Public/GraphRequests/Get-GraphRequestList.ps1 @@ -158,6 +158,7 @@ function Get-GraphRequestList { Get-Tenants -IncludeErrors | ForEach-Object { $TenantFilter = $_.defaultDomainName $QueueTenant = [PSCustomObject]@{ + FunctionName = 'ListGraphRequestQueue' TenantFilter = $TenantFilter Endpoint = $Endpoint QueueId = $Queue.RowKey @@ -171,11 +172,7 @@ function Get-GraphRequestList { ReverseTenantLookup = $ReverseTenantLookup.IsPresent } - $QueueItem = [PSCustomObject]@{ - FunctionName = 'ListGraphRequestQueue' - QueueItem = $QueueTenant - } - Push-OutputBinding -Name QueueItem -Value $QueueItem + Push-OutputBinding -Name QueueItem -Value $QueueTenant } } catch { Write-Host "QUEUE ERROR: $($_.Exception.Message)" @@ -221,6 +218,7 @@ function Get-GraphRequestList { } else { $Queue = New-CippQueueEntry -Name $QueueName -Link $CippLink -Reference $QueueReference $QueueTenant = [PSCustomObject]@{ + FunctionName = 'ListGraphRequestQueue' TenantFilter = $TenantFilter Endpoint = $Endpoint QueueId = $Queue.RowKey @@ -233,11 +231,7 @@ function Get-GraphRequestList { ReverseTenantLookup = $ReverseTenantLookup.IsPresent } - $QueueItem = [PSCustomObject]@{ - FunctionName = 'ListGraphRequestQueue' - QueueItem = $QueueTenant - } - Push-OutputBinding -Name QueueItem -Value $QueueItem + Push-OutputBinding -Name QueueItem -Value $QueueTenant [PSCustomObject]@{ QueueMessage = ('Loading {0} rows for {1}. Please check back after the job completes' -f $Count, $TenantFilter) From 580ca61400a957d51f175e5793283429b0164cd2 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Mon, 6 Nov 2023 17:20:45 -0500 Subject: [PATCH 03/55] Add more mailbox parameters --- ListMailboxes/run.ps1 | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/ListMailboxes/run.ps1 b/ListMailboxes/run.ps1 index 8f617d95006b..9166a675a9c5 100644 --- a/ListMailboxes/run.ps1 +++ b/ListMailboxes/run.ps1 @@ -16,12 +16,36 @@ try { $users = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/?`$top=999&`$select=id,userPrincipalName,assignedLicenses" -Tenantid $tenantfilter $ExoRequest = @{ - tenantid = $TenantFilter - cmdlet = 'Get-Mailbox' + tenantid = $TenantFilter + cmdlet = 'Get-Mailbox' + cmdParams = @{} } - if ([bool]$Request.Query.SoftDeletedMailbox -eq $true) { - $ExoRequest.cmdParams = @{ SoftDeletedMailbox = $true } + $AllowedParameters = @( + @{Parameter = 'Anr'; Type = 'String' } + @{Parameter = 'Archive'; Type = 'Bool' } + @{Parameter = 'Filter'; Type = 'String' } + @{Parameter = 'GroupMailbox'; Type = 'Bool' } + @{Parameter = 'PublicFolder'; Type = 'Bool' } + @{Parameter = 'RecipientTypeDetails'; Type = 'String' } + ) + + foreach ($Param in $Request.Query.Keys) { + $CmdParam = $AllowedParameters | Where-Object { $_.Parameter -eq $Param } + if ($CmdParam) { + switch ($CmdParam.Type) { + 'String' { + if (![string]::IsNullOrEmpty($Request.Query.$Param)) { + $ExoRequest.cmdParams.$Param = $Request.Query.$Param + } + } + 'Bool' { + if ([bool]$Request.Query.$Param -eq $true) { + $ExoRequest.cmdParams.$Param = $true + } + } + } + } } Write-Host ($ExoRequest | ConvertTo-Json) From 05c132598306c701ecd18fa1690e4e7c40ec4cb3 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Mon, 6 Nov 2023 17:32:31 -0500 Subject: [PATCH 04/55] Update run.ps1 --- ListMailboxes/run.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/ListMailboxes/run.ps1 b/ListMailboxes/run.ps1 index 9166a675a9c5..7585e1147efd 100644 --- a/ListMailboxes/run.ps1 +++ b/ListMailboxes/run.ps1 @@ -28,6 +28,7 @@ try { @{Parameter = 'GroupMailbox'; Type = 'Bool' } @{Parameter = 'PublicFolder'; Type = 'Bool' } @{Parameter = 'RecipientTypeDetails'; Type = 'String' } + @{Parameter = 'SoftDeletedMailbox'; Type = 'Bool' } ) foreach ($Param in $Request.Query.Keys) { From 9a2965b2e679583ca8104e250d8f87ea84e9ea58 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Wed, 8 Nov 2023 20:46:40 -0500 Subject: [PATCH 05/55] Fix GDAP Invite for company admin --- ExecGDAPInvite/run.ps1 | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ExecGDAPInvite/run.ps1 b/ExecGDAPInvite/run.ps1 index 2e043db68286..a7b48f56a7d2 100644 --- a/ExecGDAPInvite/run.ps1 +++ b/ExecGDAPInvite/run.ps1 @@ -10,6 +10,13 @@ $RoleMappings = $Request.body.gdapRoles $Results = [System.Collections.Generic.List[string]]::new() $InviteUrls = [System.Collections.Generic.List[string]]::new() + +if ($RoleMappings.roleDefinitionId -contains '62e90394-69f5-4237-9190-012177145e10') { + $AutoExtendDuration = 'PT0S' +} else { + $AutoExtendDuration = 'P180D' +} + $Table = Get-CIPPTable -TableName 'GDAPInvites' try { $JSONBody = @{ @@ -17,7 +24,7 @@ try { 'accessDetails' = @{ 'unifiedRoles' = @($RoleMappings | Select-Object roleDefinitionId) } - 'autoExtendDuration' = 'P180D' + 'autoExtendDuration' = $AutoExtendDuration 'duration' = 'P730D' } | ConvertTo-Json -Depth 5 -Compress @@ -56,6 +63,7 @@ try { } } catch { $Results.add('Error creating GDAP relationship') + Write-Host "GDAP ERROR: $($_.Exception.Message)" } Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Created GDAP Invite - $InviteUrl" -Sev 'Info' From cd727a613da5fbc664057f2ae3d4fe4273d642ca Mon Sep 17 00:00:00 2001 From: John Duprey Date: Wed, 8 Nov 2023 20:50:14 -0500 Subject: [PATCH 06/55] Fix duplicate name issue --- .../Public/Test-CIPPGDAPRelationships.ps1 | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/Modules/CIPPCore/Public/Test-CIPPGDAPRelationships.ps1 b/Modules/CIPPCore/Public/Test-CIPPGDAPRelationships.ps1 index cf2bacb49e68..6c6a969d906f 100644 --- a/Modules/CIPPCore/Public/Test-CIPPGDAPRelationships.ps1 +++ b/Modules/CIPPCore/Public/Test-CIPPGDAPRelationships.ps1 @@ -2,7 +2,7 @@ function Test-CIPPGDAPRelationships { [CmdletBinding()] param ( $TenantFilter, - $APIName = "Access Check", + $APIName = 'Access Check', $ExecutingUser ) @@ -15,26 +15,26 @@ function Test-CIPPGDAPRelationships { foreach ($Tenant in $RelationshipsByTenant) { if ($Tenant.Group.displayName.count -le 1 -and $Tenant.Group.displayName -like 'MLT_*') { $GDAPissues.add([PSCustomObject]@{ - Type = "Error" - Issue = "This tenant only has a MLT(Microsoft Led Transition) relationship. This is a read-only relationship. You must migrate this tenant to GDAP." + Type = 'Error' + Issue = 'This tenant only has a MLT(Microsoft Led Transition) relationship. This is a read-only relationship. You must migrate this tenant to GDAP.' Tenant = $Tenant.Group.customer.displayName Relationship = $Tenant.Group.displayName - Link = "https://docs.cipp.app/setup/gdap/index" + Link = 'https://docs.cipp.app/setup/gdap/index' }) | Out-Null } foreach ($Group in $Tenant.Group) { - if ("62e90394-69f5-4237-9190-012177145e10" -in $Group.accessDetails.unifiedRoles.roleDefinitionId) { + if ('62e90394-69f5-4237-9190-012177145e10' -in $Group.accessDetails.unifiedRoles.roleDefinitionId) { $GDAPissues.add([PSCustomObject]@{ - Type = "Warning" - Issue = "The relationship has global administrator access. Auto-Extend is not available." - Tenant = $Tenant.Group.customer.displayName | Out-String - Relationship = $group.displayName | Out-String - Link = "https://docs.cipp.app/setup/gdap/troubleshooting#autoextend" + Type = 'Warning' + Issue = 'The relationship has global administrator access. Auto-Extend is not available.' + Tenant = $Group.customer.displayName | Out-String + Relationship = $Group.displayName | Out-String + Link = 'https://docs.cipp.app/setup/gdap/troubleshooting#autoextend' }) | Out-Null } } - + } $me = (New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/me?$select=UserPrincipalName' -NoAuthCheck $true).UserPrincipalName $CIPPGroupCount = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/groups/`$count?`$filter=startsWith(displayName,'M365 GDAP')" -NoAuthCheck $true -ComplexFilter @@ -67,29 +67,28 @@ function Test-CIPPGDAPRelationships { } if (-not $GroupFound) { $GDAPissues.add([PSCustomObject]@{ - Type = "Warning" + Type = 'Warning' Issue = "$($Group) is not assigned to the SAM user $me. If you have migrated outside of CIPP this is to be expected. Please perform an access check to make sure you have the correct set of permissions." - Tenant = "*Partner Tenant" - Relationship = "None" - Link = "https://docs.cipp.app/setup/gdap/troubleshooting#groups" + Tenant = '*Partner Tenant' + Relationship = 'None' + Link = 'https://docs.cipp.app/setup/gdap/troubleshooting#groups' }) | Out-Null } if ($CIPPGroupCount -lt 12) { $GDAPissues.add([PSCustomObject]@{ - Type = "Warning" + Type = 'Warning' Issue = "We only found $($CIPPGroupCount) of the 12 required groups. If you have migrated outside of CIPP this is to be expected. Please perform an access check to make sure you have the correct set of permissions." - Tenant = "*Partner Tenant" - Relationship = "None" - Link = "https://docs.cipp.app/setup/gdap/troubleshooting#groups" + Tenant = '*Partner Tenant' + Relationship = 'None' + Link = 'https://docs.cipp.app/setup/gdap/troubleshooting#groups' }) | Out-Null } } - } - catch { - Write-LogMessage -user $ExecutingUser -API $APINAME -message "Failed to run GDAP check for $($TenantFilter): $($_.Exception.Message)" -Sev "Error" + } catch { + Write-LogMessage -user $ExecutingUser -API $APINAME -message "Failed to run GDAP check for $($TenantFilter): $($_.Exception.Message)" -Sev 'Error' } return [PSCustomObject]@{ From 122ee80b0023eed797cbb63c0f51653c450d84b0 Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Fri, 10 Nov 2023 13:52:04 +0000 Subject: [PATCH 07/55] Update GraphHelper.psm1 Added the ability to use tenantid on Exo Calls via the API --- GraphHelper.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GraphHelper.psm1 b/GraphHelper.psm1 index 1848c74ecb09..576bee5a7bb9 100644 --- a/GraphHelper.psm1 +++ b/GraphHelper.psm1 @@ -565,7 +565,7 @@ function Remove-CIPPCache { function New-ExoRequest ($tenantid, $cmdlet, $cmdParams, $useSystemMailbox, $Anchor, $NoAuthCheck) { if ((Get-AuthorisedRequest -TenantID $tenantid) -or $NoAuthCheck -eq $True) { $token = Get-ClassicAPIToken -resource 'https://outlook.office365.com' -Tenantid $tenantid - $tenant = (get-tenants -IncludeErrors | Where-Object -Property defaultDomainName -EQ $tenantid).customerId + $tenant = (get-tenants -IncludeErrors | Where-Object { $_.defaultDomainName -eq $tenantid -or $_.customerId -eq $tenantid }).customerId if ($cmdParams) { $Params = $cmdParams } From 0fd67802c79db792adfb0dc666252541854d3867 Mon Sep 17 00:00:00 2001 From: Jr7468 Date: Fri, 10 Nov 2023 14:38:22 +0000 Subject: [PATCH 08/55] Increased output for API access --- AddUser/run.ps1 | 10 ++++++++-- Modules/CIPPCore/Public/Set-CIPPCopyGroupMembers.ps1 | 12 +++++++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/AddUser/run.ps1 b/AddUser/run.ps1 index f2bac94e00f6..7de7b212c642 100644 --- a/AddUser/run.ps1 +++ b/AddUser/run.ps1 @@ -98,9 +98,15 @@ catch { } if ($Request.body.CopyFrom -ne "") { $CopyFrom = Set-CIPPCopyGroupMembers -ExecutingUser $request.headers.'x-ms-client-principal' -tenantid $Userobj.tenantid -CopyFromId $Request.body.CopyFrom -UserID $UserprincipalName -TenantFilter $Userobj.tenantid - $results.AddRange($CopyFrom) + $results.Add($CopyFrom.Success -join ', ') + $results.Add($CopyFrom.Error -join ', ') +} +$body = [pscustomobject] @{ + "Results" = @($results) + "Username" = $UserprincipalName + "Password" = $password + "CopyFrom" = $CopyFrom } -$body = @{"Results" = @($results) } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK diff --git a/Modules/CIPPCore/Public/Set-CIPPCopyGroupMembers.ps1 b/Modules/CIPPCore/Public/Set-CIPPCopyGroupMembers.ps1 index c6a7722120ec..098c0fc41b94 100644 --- a/Modules/CIPPCore/Public/Set-CIPPCopyGroupMembers.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPCopyGroupMembers.ps1 @@ -8,7 +8,8 @@ function Set-CIPPCopyGroupMembers( $MemberIDs = "https://graph.microsoft.com/v1.0/directoryObjects/" + (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$UserId" -tenantid $TenantFilter).id $AddMemberBody = "{ `"members@odata.bind`": $(ConvertTo-Json @($MemberIDs)) }" - $Results = New-Object System.Collections.ArrayList + $Success = New-Object System.Collections.ArrayList + $Errors = New-Object System.Collections.ArrayList (New-GraphGETRequest -uri "https://graph.microsoft.com/beta/users/$CopyFromId/memberOf" -tenantid $TenantFilter) | Where-Object { $_.GroupTypes -notin "DynamicMemberShip" } | ForEach-Object { try { $MailGroup = $_ @@ -20,14 +21,19 @@ function Set-CIPPCopyGroupMembers( $GroupResult = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups/$($_.id)" -tenantid $TenantFilter -type patch -body $AddMemberBody -Verbose } Write-LogMessage -user $ExecutingUser -API $APIName -message "Added $UserId to group $($_.displayName)" -Sev "Info" -tenant $TenantFilter - $Results.Add("Added group: $($MailGroup.displayName)") | Out-Null + $Success.Add("Added group: $($MailGroup.displayName)") | Out-Null } catch { $NormalizedError = Get-NormalizedError -message $($_.Exception.Message) - $Results.Add("We've failed to add the group $($MailGroup.displayName): $NormalizedError") | Out-Null + $Errors.Add("We've failed to add the group $($MailGroup.displayName): $NormalizedError") | Out-Null Write-LogMessage -user $ExecutingUser -API $APIName -tenant $TenantFilter -message "Group adding failed for group $($_.displayName): $($_.Exception.Message)" -Sev "Error" } } + $Results = [PSCustomObject]@{ + "Success" = $Success + "Error" = $Errors + } + return $Results } From 8e809e848395e49bd9717472ee902f39b63c2a89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Fri, 10 Nov 2023 20:27:04 +0100 Subject: [PATCH 09/55] fix oauth colum giving object id and not application id --- ListOAuthApps/run.ps1 | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/ListOAuthApps/run.ps1 b/ListOAuthApps/run.ps1 index f29b4e0c31a3..d88ab1c30664 100644 --- a/ListOAuthApps/run.ps1 +++ b/ListOAuthApps/run.ps1 @@ -17,14 +17,16 @@ if ($TenantFilter -eq "AllTenants") { $Tenants = (Get-Tenants).defaultDomainName try { $GraphRequest = foreach ($Tenant in $Tenants) { try { - $ServicePrincipals = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=id,displayName" -tenantid $Tenant + $ServicePrincipals = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=id,displayName,appid" -tenantid $Tenant New-GraphGetRequest -uri "https://graph.microsoft.com/beta/oauth2PermissionGrants" -tenantid $Tenant | ForEach-Object { + $CurrentServicePrincipal = ($ServicePrincipals | Where-Object -Property id -EQ $_.clientId) [PSCustomObject]@{ - Tenant = $Tenant - Name = ($ServicePrincipals | Where-Object -Property id -EQ $_.clientId).displayName - ID = $_.clientId - Scope = ($_.scope -join ',') - StartTime = $_.startTime + Tenant = $Tenant + Name = $CurrentServicePrincipal.displayName + ApplicationID = $CurrentServicePrincipal.appid + ObjectID = $_.clientId + Scope = ($_.scope -join ',') + StartTime = $_.startTime } } $StatusCode = [HttpStatusCode]::OK From 7326d401b62fd36efb62969646e6f852e72ccdac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Sat, 11 Nov 2023 00:26:51 +0100 Subject: [PATCH 10/55] Add mailbox type to Email settings pane under list user-API --- ListUserMailboxDetails/run.ps1 | 46 ++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/ListUserMailboxDetails/run.ps1 b/ListUserMailboxDetails/run.ps1 index adb9d2ce2e6e..90affe48fe95 100644 --- a/ListUserMailboxDetails/run.ps1 +++ b/ListUserMailboxDetails/run.ps1 @@ -97,28 +97,29 @@ else { } if ($ArchiveSize) { -$GraphRequest = [ordered]@{ - ForwardAndDeliver = $MailboxDetailedRequest.DeliverToMailboxAndForward - ForwardingAddress = $ForwardingAddress - LitiationHold = $MailboxDetailedRequest.LitigationHoldEnabled - HiddenFromAddressLists = $MailboxDetailedRequest.HiddenFromAddressListsEnabled - EWSEnabled = $CASRequest.EwsEnabled - MailboxMAPIEnabled = $CASRequest.MAPIEnabled - MailboxOWAEnabled = $CASRequest.OWAEnabled - MailboxImapEnabled = $CASRequest.ImapEnabled - MailboxPopEnabled = $CASRequest.PopEnabled - MailboxActiveSyncEnabled = $CASRequest.ActiveSyncEnabled - Permissions = $ParsedPerms - ProhibitSendQuota = [math]::Round([float]($MailboxDetailedRequest.ProhibitSendQuota -split ' GB')[0], 2) - ProhibitSendReceiveQuota = [math]::Round([float]($MailboxDetailedRequest.ProhibitSendReceiveQuota -split ' GB')[0], 2) - ItemCount = [math]::Round($StatsRequest.ItemCount, 2) - TotalItemSize = [math]::Round($StatsRequest.TotalItemSize / 1Gb, 2) - TotalArchiveItemSize = $ArchiveSize.totalItemSize.split('(')[0] - TotalArchiveItemCount = [math]::Round($ArchiveSize.ItemCount, 2) - BlockedForSpam = $BlockedForSpam - ArchiveMailBox = $ArchiveEnabled - AutoExpandingArchive = $Archive.AutoExpandingArchiveEnabled -} + $GraphRequest = [ordered]@{ + ForwardAndDeliver = $MailboxDetailedRequest.DeliverToMailboxAndForward + ForwardingAddress = $ForwardingAddress + LitiationHold = $MailboxDetailedRequest.LitigationHoldEnabled + HiddenFromAddressLists = $MailboxDetailedRequest.HiddenFromAddressListsEnabled + EWSEnabled = $CASRequest.EwsEnabled + MailboxMAPIEnabled = $CASRequest.MAPIEnabled + MailboxOWAEnabled = $CASRequest.OWAEnabled + MailboxImapEnabled = $CASRequest.ImapEnabled + MailboxPopEnabled = $CASRequest.PopEnabled + MailboxActiveSyncEnabled = $CASRequest.ActiveSyncEnabled + Permissions = $ParsedPerms + ProhibitSendQuota = [math]::Round([float]($MailboxDetailedRequest.ProhibitSendQuota -split ' GB')[0], 2) + ProhibitSendReceiveQuota = [math]::Round([float]($MailboxDetailedRequest.ProhibitSendReceiveQuota -split ' GB')[0], 2) + ItemCount = [math]::Round($StatsRequest.ItemCount, 2) + TotalItemSize = [math]::Round($StatsRequest.TotalItemSize / 1Gb, 2) + TotalArchiveItemSize = $ArchiveSize.totalItemSize.split('(')[0] + TotalArchiveItemCount = [math]::Round($ArchiveSize.ItemCount, 2) + BlockedForSpam = $BlockedForSpam + ArchiveMailBox = $ArchiveEnabled + AutoExpandingArchive = $Archive.AutoExpandingArchiveEnabled + RecipientTypeDetails = $MailboxDetailedRequest.RecipientTypeDetails + } } else { $GraphRequest = [ordered]@{ @@ -142,6 +143,7 @@ else { BlockedForSpam = $BlockedForSpam ArchiveMailBox = $ArchiveEnabled AutoExpandingArchive = $Archive.AutoExpandingArchiveEnabled + RecipientTypeDetails = $MailboxDetailedRequest.RecipientTypeDetails } } From 7c8ef7b38408334bb3ef4a8d73a763ee5a8ce7ff Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Sat, 11 Nov 2023 10:31:36 +0000 Subject: [PATCH 11/55] Fixed Missing Return Fixed missing return --- Modules/CIPPCore/Public/Remove-CIPPMobileDevice.ps1 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Modules/CIPPCore/Public/Remove-CIPPMobileDevice.ps1 b/Modules/CIPPCore/Public/Remove-CIPPMobileDevice.ps1 index 6f65ff4da439..ad59e935e9d1 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPMobileDevice.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPMobileDevice.ps1 @@ -12,15 +12,16 @@ function Remove-CIPPMobileDevice { $devices = New-ExoRequest -tenantid $tenantFilter -cmdlet "Get-MobileDevice" -Anchor $username -cmdParams @{mailbox = $username } | ForEach-Object { try { New-ExoRequest -tenantid $tenantFilter -cmdlet "Remove-MobileDevice" -Anchor $username -cmdParams @{Identity = $_.Identity } - "Removed device: $($_.FriendlyName)" + return "Removed device: $($_.FriendlyName)" } catch { - "Could not remove device: $($_.FriendlyName)" + return "Could not remove device: $($_.FriendlyName)" continue } } Write-LogMessage -user $ExecutingUser -API $APIName -message "Deleted mobile devices for $($username)" -Sev "Info" -tenant $tenantFilter + return "Deleted mobile devices for $($username)" } catch { Write-LogMessage -user $ExecutingUser -API $APIName -message "Could not delete mobile devices for $($username): $($_.Exception.Message)" -Sev "Error" -tenant $tenantFilter From 02bf6719dcc3e16f5ca28729bc923851ec57406e Mon Sep 17 00:00:00 2001 From: BNWEIN Date: Mon, 13 Nov 2023 12:51:03 +0000 Subject: [PATCH 12/55] Update Remove-CIPPGroups.ps1 Updated the function so you can just supply a username and it works. No UserID is required --- Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 b/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 index 443b24c5fbbc..ec0a0c151052 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 @@ -1,16 +1,20 @@ function Remove-CIPPGroups { [CmdletBinding()] param( - $userid, + $Username, $tenantFilter, $APIName = "Remove From Groups", $ExecutingUser, - $Username + $userid ) - $AllGroups = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/groups/?$select=DisplayName,mailEnabled" -tenantid $tenantFilter) +if (-not $userid) { + $userid = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($Username)" -tenantid $Tenantfilter).id +} + $AllGroups = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/groups/?`$select=displayName,mailEnabled,id,groupTypes" -tenantid $tenantFilter) (New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($userid)/GetMemberGroups" -tenantid $tenantFilter -type POST -body '{"securityEnabledOnly": false}').value | ForEach-Object -Parallel { + Import-Module CIPPCore Import-Module '.\GraphHelper.psm1' $group = $_ From 56df158ed1116c0f25b3d5b04697a66e2b64482d Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 13 Nov 2023 17:40:23 +0100 Subject: [PATCH 13/55] updated repos --- .github/workflows/dev_cippb2p4g.yml | 29 ---------------- .github/workflows/powershell-analysis.yml | 42 ----------------------- 2 files changed, 71 deletions(-) delete mode 100644 .github/workflows/dev_cippb2p4g.yml delete mode 100644 .github/workflows/powershell-analysis.yml diff --git a/.github/workflows/dev_cippb2p4g.yml b/.github/workflows/dev_cippb2p4g.yml deleted file mode 100644 index e82ec8c1ba86..000000000000 --- a/.github/workflows/dev_cippb2p4g.yml +++ /dev/null @@ -1,29 +0,0 @@ -# Docs for the Azure Web Apps Deploy action: https://github.com/azure/functions-action -# More GitHub Actions for Azure: https://github.com/Azure/actions - -name: Build and deploy Powershell project to Azure Function App - cippb2p4g - -on: - push: - branches: - - dev - workflow_dispatch: - -env: - AZURE_FUNCTIONAPP_PACKAGE_PATH: '.' # set this to the path to your web app project, defaults to the repository root - -jobs: - build-and-deploy: - runs-on: windows-latest - steps: - - name: 'Checkout GitHub Action' - uses: actions/checkout@v4 - - - name: 'Run Azure Functions Action' - uses: Azure/functions-action@v1 - id: fa - with: - app-name: 'cippb2p4g' - slot-name: 'Production' - package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }} - publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_C106B398356B4EFCB81F779ED5806A0D }} diff --git a/.github/workflows/powershell-analysis.yml b/.github/workflows/powershell-analysis.yml deleted file mode 100644 index e1c8092af020..000000000000 --- a/.github/workflows/powershell-analysis.yml +++ /dev/null @@ -1,42 +0,0 @@ -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. -# -# https://github.com/microsoft/action-psscriptanalyzer -# For more information on PSScriptAnalyzer in general, see -# https://github.com/PowerShell/PSScriptAnalyzer - -name: PSScriptAnalyzer - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - schedule: - - cron: '22 22 * * 5' - -jobs: - build: - name: PSScriptAnalyzer - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - - name: Run PSScriptAnalyzer - uses: microsoft/psscriptanalyzer-action@2044ae068e37d0161fa2127de04c19633882f061 - with: - # Check https://github.com/microsoft/action-psscriptanalyzer for more info about the options. - # The below set up runs PSScriptAnalyzer to your entire repository and runs some basic security rules. - path: .\ - recurse: true - # Include your own basic security rules. Removing this option will run all the rules - includeRule: '"PSAvoidGlobalAliases", "PSAvoidUsingConvertToSecureStringWithPlainText"' - output: results.sarif - - # Upload the SARIF file generated in the previous step - - name: Upload SARIF results file - uses: github/codeql-action/upload-sarif@v2 - with: - sarif_file: results.sarif From 98348856427fda0946fc846cbbf9f7dc8c9349ca Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Tue, 14 Nov 2023 10:58:24 +0100 Subject: [PATCH 14/55] fixes https://github.com/KelvinTegelaar/CIPP/issues/1867 --- ListGroupTemplates/run.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ListGroupTemplates/run.ps1 b/ListGroupTemplates/run.ps1 index 870b45496879..df07537a56a7 100644 --- a/ListGroupTemplates/run.ps1 +++ b/ListGroupTemplates/run.ps1 @@ -16,7 +16,8 @@ $Table = Get-CippTable -tablename 'templates' $Filter = "PartitionKey eq 'GroupTemplate'" $Templates = (Get-CIPPAzDataTableEntity @Table -Filter $Filter) | ForEach-Object { $data = $_.JSON | ConvertFrom-Json - $data + $data | Add-Member -MemberType NoteProperty -Name GUID -Value $_.RowKey -Force + $data } | Sort-Object -Property displayName if ($Request.query.ID) { $Templates = $Templates | Where-Object -Property GUID -EQ $Request.query.id } From bc0f4cf546bb21ff3a17c35b57730b67da916169 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Tue, 14 Nov 2023 11:00:52 +0100 Subject: [PATCH 15/55] Fixes https://github.com/KelvinTegelaar/CIPP/issues/1862 --- Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 b/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 index ec0a0c151052..305c36ec4625 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 @@ -13,7 +13,7 @@ if (-not $userid) { } $AllGroups = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/groups/?`$select=displayName,mailEnabled,id,groupTypes" -tenantid $tenantFilter) - (New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($userid)/GetMemberGroups" -tenantid $tenantFilter -type POST -body '{"securityEnabledOnly": false}').value | ForEach-Object -Parallel { + $Returnval = (New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($userid)/GetMemberGroups" -tenantid $tenantFilter -type POST -body '{"securityEnabledOnly": false}').value | ForEach-Object -Parallel { Import-Module CIPPCore Import-Module '.\GraphHelper.psm1' $group = $_ @@ -35,11 +35,12 @@ if (-not $userid) { } Write-LogMessage -user $using:ExecutingUser -API $($using:APIName) -message "Removed $($using:Username) from $groupname" -Sev "Info" -tenant $using:TenantFilter - return "Successfully removed $($using:Username) from group $Groupname" + "Successfully removed $($using:Username) from group $Groupname" } catch { Write-LogMessage -user $using:ExecutingUser -API $($using:APIName) -message "Could not remove $($using:Username) from group $groupname" -Sev "Error" -tenant $using:TenantFilter - return "Could not remove $($using:Username) from group $($Groupname): $($_.Exception.Message). This is likely because its a Dynamic Group or synched with active directory" + "Could not remove $($using:Username) from group $($Groupname): $($_.Exception.Message). This is likely because its a Dynamic Group or synched with active directory" } } + return $Returnval } From 4cb047b22dff6e3f8e1edcef0867358d5a79515e Mon Sep 17 00:00:00 2001 From: Jr7468 Date: Tue, 14 Nov 2023 12:06:17 +0000 Subject: [PATCH 16/55] Fixed a typo :) --- ExecEmailForward/run.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ExecEmailForward/run.ps1 b/ExecEmailForward/run.ps1 index 868f0a0dbacf..d0586980fb7e 100644 --- a/ExecEmailForward/run.ps1 +++ b/ExecEmailForward/run.ps1 @@ -52,7 +52,7 @@ elseif ($DisableForwarding -eq "True") { try { New-ExoRequest -tenantid $TenantFilter -cmdlet "Set-Mailbox" -cmdParams @{Identity = $Username; ForwardingAddress = $null; ForwardingSMTPAddress = $null; DeliverToMailboxAndForward = $false } Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Disabled Email forwarding for $($username)" -Sev "Info" -tenant $TenantFilter - $results = "Disabled Email Forwerding for $($username)" + $results = "Disabled Email Forwarding for $($username)" } catch { Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Could not disable Email forwarding for $($username)" -Sev "Error" -tenant $TenantFilter From 37d9a18612028e888639d12e4e979a30ed54e525 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Tue, 14 Nov 2023 14:32:12 +0100 Subject: [PATCH 17/55] add allusers --- .../Public/Remove-CIPPMailboxPermissions.ps1 | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 b/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 index 1602e9861665..7ecb1c672454 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 @@ -10,22 +10,30 @@ function Remove-CIPPMailboxPermissions { ) try { - $Results = $PermissionsLevel | ForEach-Object { - switch ($_) { - "SendOnBehalf" { - $MailboxPerms = New-ExoRequest -Anchor $username -tenantid $Tenantfilter -cmdlet "Set-Mailbox" -cmdParams @{Identity = $userid; GrantSendonBehalfTo = @{'@odata.type' = '#Exchange.GenericHashTable'; remove = $AccessUser }; } - Write-LogMessage -user $ExecutingUser -API $APIName -message "Removed SendOnBehalf permissions for $($AccessUser) from $($userid)'s mailbox." -Sev "Info" -tenant $TenantFilter - "Removed SendOnBehalf permissions for $($AccessUser) from $($userid)'s mailbox." - } - "SendAS" { - $MailboxPerms = New-ExoRequest -Anchor $username -tenantid $Tenantfilter -cmdlet "Remove-RecipientPermission" -cmdParams @{Identity = $userid; Trustee = $AccessUser; accessRights = @("SendAs") } - Write-LogMessage -user $ExecutingUser -API $APIName -message "Removed SendAs permissions for $($AccessUser) from $($userid)'s mailbox." -Sev "Info" -tenant $TenantFilter - "Removed SendAs permissions for $($AccessUser) from $($userid)'s mailbox." - } - "FullAccess" { - $permissions = New-ExoRequest -tenantid $TenantFilter -cmdlet "Remove-MailboxPermission" -cmdParams @{Identity = $userid; user = $AccessUser; accessRights = @("FullAccess") } -Anchor $userid - Write-LogMessage -user $ExecutingUser -API $APIName -message "Removed FullAccess permissions for $($AccessUser) from $($userid)'s mailbox." -Sev "Info" -tenant $TenantFilter - "Removed FullAccess permissions for $($AccessUser) from $($userid)'s mailbox." + if ($userid -eq "AllUsers") { + $Mailboxes = New-ExoRequest -tenantid $QueueItem.TenantFilter -cmdlet "get-mailbox" + foreach ($Mailbox in $Mailboxes) { + Remove-CIPPMailboxPermissions -PermissionsLevel @("FullAccess", "SendAs", "SendOnBehalf") -userid $Mailbox.UserPrincipalName -AccessUser $QueueItem.User -TenantFilter $QueueItem.TenantFilter -APIName $APINAME -ExecutingUser $QueueItem.ExecutingUser + } + } + else { + $Results = $PermissionsLevel | ForEach-Object { + switch ($_) { + "SendOnBehalf" { + $MailboxPerms = New-ExoRequest -Anchor $username -tenantid $Tenantfilter -cmdlet "Set-Mailbox" -cmdParams @{Identity = $userid; GrantSendonBehalfTo = @{'@odata.type' = '#Exchange.GenericHashTable'; remove = $AccessUser }; } + Write-LogMessage -user $ExecutingUser -API $APIName -message "Removed SendOnBehalf permissions for $($AccessUser) from $($userid)'s mailbox." -Sev "Info" -tenant $TenantFilter + "Removed SendOnBehalf permissions for $($AccessUser) from $($userid)'s mailbox." + } + "SendAS" { + $MailboxPerms = New-ExoRequest -Anchor $username -tenantid $Tenantfilter -cmdlet "Remove-RecipientPermission" -cmdParams @{Identity = $userid; Trustee = $AccessUser; accessRights = @("SendAs") } + Write-LogMessage -user $ExecutingUser -API $APIName -message "Removed SendAs permissions for $($AccessUser) from $($userid)'s mailbox." -Sev "Info" -tenant $TenantFilter + "Removed SendAs permissions for $($AccessUser) from $($userid)'s mailbox." + } + "FullAccess" { + $permissions = New-ExoRequest -tenantid $TenantFilter -cmdlet "Remove-MailboxPermission" -cmdParams @{Identity = $userid; user = $AccessUser; accessRights = @("FullAccess") } -Anchor $userid + Write-LogMessage -user $ExecutingUser -API $APIName -message "Removed FullAccess permissions for $($AccessUser) from $($userid)'s mailbox." -Sev "Info" -tenant $TenantFilter + "Removed FullAccess permissions for $($AccessUser) from $($userid)'s mailbox." + } } } } From eecac04fb3e7783cf929262b97048a8a054ed299 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Tue, 14 Nov 2023 14:34:30 +0100 Subject: [PATCH 18/55] corrected permissions level --- Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 b/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 index 7ecb1c672454..60f00e018b7b 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 @@ -13,7 +13,7 @@ function Remove-CIPPMailboxPermissions { if ($userid -eq "AllUsers") { $Mailboxes = New-ExoRequest -tenantid $QueueItem.TenantFilter -cmdlet "get-mailbox" foreach ($Mailbox in $Mailboxes) { - Remove-CIPPMailboxPermissions -PermissionsLevel @("FullAccess", "SendAs", "SendOnBehalf") -userid $Mailbox.UserPrincipalName -AccessUser $QueueItem.User -TenantFilter $QueueItem.TenantFilter -APIName $APINAME -ExecutingUser $QueueItem.ExecutingUser + Remove-CIPPMailboxPermissions -PermissionsLevel $PermissionsLevel -userid $Mailbox.UserPrincipalName -AccessUser $QueueItem.User -TenantFilter $QueueItem.TenantFilter -APIName $APINAME -ExecutingUser $QueueItem.ExecutingUser } } else { From ab7057a18d3746955aa29140476a3e4d9ab31782 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Tue, 14 Nov 2023 14:39:23 +0100 Subject: [PATCH 19/55] fixes groups --- Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 b/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 index 305c36ec4625..ca673419332f 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 @@ -8,9 +8,9 @@ function Remove-CIPPGroups { $userid ) -if (-not $userid) { - $userid = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($Username)" -tenantid $Tenantfilter).id -} + if (-not $userid) { + $userid = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($Username)" -tenantid $Tenantfilter).id + } $AllGroups = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/groups/?`$select=displayName,mailEnabled,id,groupTypes" -tenantid $tenantFilter) $Returnval = (New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($userid)/GetMemberGroups" -tenantid $tenantFilter -type POST -body '{"securityEnabledOnly": false}').value | ForEach-Object -Parallel { @@ -42,5 +42,5 @@ if (-not $userid) { "Could not remove $($using:Username) from group $($Groupname): $($_.Exception.Message). This is likely because its a Dynamic Group or synched with active directory" } } - return $Returnval + return ($Returnval | Out-String) } From afa06b646c5a443dc8dff3add2d18eeab3f2b1a1 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Tue, 14 Nov 2023 15:36:01 +0100 Subject: [PATCH 20/55] only replace current body. --- Standards_PWdisplayAppInformationRequiredState/run.ps1 | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Standards_PWdisplayAppInformationRequiredState/run.ps1 b/Standards_PWdisplayAppInformationRequiredState/run.ps1 index 8ec998ca485f..3f59c422019e 100644 --- a/Standards_PWdisplayAppInformationRequiredState/run.ps1 +++ b/Standards_PWdisplayAppInformationRequiredState/run.ps1 @@ -1,9 +1,12 @@ param($tenant) try { - $body = @" -{"@odata.type":"#microsoft.graph.microsoftAuthenticatorAuthenticationMethodConfiguration","id":"MicrosoftAuthenticator","includeTargets":[{"id":"all_users","isRegistrationRequired":false,"targetType":"group","authenticationMode":"any"}],"excludeTargets":[],"state":"enabled","featureSettings":{"displayLocationInformationRequiredState":{"state":"enabled","includeTarget":{"id":"all_users","targetType":"group","displayName":"All users"}},"displayAppInformationRequiredState":{"state":"enabled","includeTarget":{"id":"all_users","targetType":"group","displayName":"All users"}},"companionAppAllowedState":{"state":"default","includeTarget":{"id":"all_users","targetType":"group","displayName":"All users"}}}} -"@ + + $CurrentInfo = new-graphgetRequest -uri "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator" -tenantid $Tenant + $CurrentInfo.featureSettings.PSObject.Properties.Remove('numberMatchingRequiredState') + $CurrentInfo.featureSettings.displayAppInformationRequiredState.state = "enabled" + $CurrentInfo.featureSettings.displayLocationInformationRequiredState.state = "enabled" + $body = ($CurrentInfo | ConvertTo-Json -depth 10) (New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator" -Type patch -Body $body -ContentType "application/json") Write-LogMessage -API "Standards" -tenant $tenant -message "Enabled passwordless with Information and Number Matching." -sev Info From 2a2396492b228ee25fa3259f577c6d1cf08ef621 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Tue, 14 Nov 2023 15:38:54 +0100 Subject: [PATCH 21/55] add oauth token standard --- Standards_allowOAuthTokens/function.json | 9 +++++++++ Standards_allowOAuthTokens/run.ps1 | 15 +++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 Standards_allowOAuthTokens/function.json create mode 100644 Standards_allowOAuthTokens/run.ps1 diff --git a/Standards_allowOAuthTokens/function.json b/Standards_allowOAuthTokens/function.json new file mode 100644 index 000000000000..2d4ea9094b24 --- /dev/null +++ b/Standards_allowOAuthTokens/function.json @@ -0,0 +1,9 @@ +{ + "bindings": [ + { + "name": "tenant", + "direction": "in", + "type": "activityTrigger" + } + ] +} \ No newline at end of file diff --git a/Standards_allowOAuthTokens/run.ps1 b/Standards_allowOAuthTokens/run.ps1 new file mode 100644 index 000000000000..4619289b1f84 --- /dev/null +++ b/Standards_allowOAuthTokens/run.ps1 @@ -0,0 +1,15 @@ +param($tenant) + +try { + + $CurrentInfo = new-graphgetRequest -uri "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator" -tenantid $Tenant + $CurrentInfo.featureSettings.PSObject.Properties.Remove('numberMatchingRequiredState') + $CurrentInfo.isSoftwareOathEnabled = $true + $body = ($CurrentInfo | ConvertTo-Json -Depth 10) + (New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator" -Type patch -Body $body -ContentType "application/json") + + Write-LogMessage -API "Standards" -tenant $tenant -message "Enabled software OTP/oAuth tokens" -sev Info +} +catch { + Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to enable software OTP/oAuth tokens. Error: $($_.exception.message)" -sev "Error" +} \ No newline at end of file From d46b6a65671e77f641608f818722762dbed3e58b Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Tue, 14 Nov 2023 17:04:51 +0100 Subject: [PATCH 22/55] added feature that we meant to add --- Standards_allowOAuthTokens/run.ps1 | 7 +++---- Standards_allowOTPTokens/function.json | 9 +++++++++ Standards_allowOTPTokens/run.ps1 | 15 +++++++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 Standards_allowOTPTokens/function.json create mode 100644 Standards_allowOTPTokens/run.ps1 diff --git a/Standards_allowOAuthTokens/run.ps1 b/Standards_allowOAuthTokens/run.ps1 index 4619289b1f84..7b18fd438449 100644 --- a/Standards_allowOAuthTokens/run.ps1 +++ b/Standards_allowOAuthTokens/run.ps1 @@ -2,11 +2,10 @@ param($tenant) try { - $CurrentInfo = new-graphgetRequest -uri "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator" -tenantid $Tenant - $CurrentInfo.featureSettings.PSObject.Properties.Remove('numberMatchingRequiredState') - $CurrentInfo.isSoftwareOathEnabled = $true + $CurrentInfo = new-graphgetRequest -uri "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/softwareOath" -tenantid $Tenant + $CurrentInfo.state = "enabled" $body = ($CurrentInfo | ConvertTo-Json -Depth 10) - (New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator" -Type patch -Body $body -ContentType "application/json") + (New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/softwareOath" -Type patch -Body $body -ContentType "application/json") Write-LogMessage -API "Standards" -tenant $tenant -message "Enabled software OTP/oAuth tokens" -sev Info } diff --git a/Standards_allowOTPTokens/function.json b/Standards_allowOTPTokens/function.json new file mode 100644 index 000000000000..2d4ea9094b24 --- /dev/null +++ b/Standards_allowOTPTokens/function.json @@ -0,0 +1,9 @@ +{ + "bindings": [ + { + "name": "tenant", + "direction": "in", + "type": "activityTrigger" + } + ] +} \ No newline at end of file diff --git a/Standards_allowOTPTokens/run.ps1 b/Standards_allowOTPTokens/run.ps1 new file mode 100644 index 000000000000..4619289b1f84 --- /dev/null +++ b/Standards_allowOTPTokens/run.ps1 @@ -0,0 +1,15 @@ +param($tenant) + +try { + + $CurrentInfo = new-graphgetRequest -uri "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator" -tenantid $Tenant + $CurrentInfo.featureSettings.PSObject.Properties.Remove('numberMatchingRequiredState') + $CurrentInfo.isSoftwareOathEnabled = $true + $body = ($CurrentInfo | ConvertTo-Json -Depth 10) + (New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator" -Type patch -Body $body -ContentType "application/json") + + Write-LogMessage -API "Standards" -tenant $tenant -message "Enabled software OTP/oAuth tokens" -sev Info +} +catch { + Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to enable software OTP/oAuth tokens. Error: $($_.exception.message)" -sev "Error" +} \ No newline at end of file From c9165b64c81c204feb086d88f1803ae87a5d9392 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 14 Nov 2023 12:24:10 -0500 Subject: [PATCH 23/55] Mailbox Restores - Add flag to skip graph call for license check - Add Suspend, Restore, Remove options for mailbox restores --- ListMailboxes/run.ps1 | 6 +- .../Entrypoints/Invoke-ExecMailboxRestore.ps1 | 90 +++++++++++++------ 2 files changed, 70 insertions(+), 26 deletions(-) diff --git a/ListMailboxes/run.ps1 b/ListMailboxes/run.ps1 index 7585e1147efd..544a716a761b 100644 --- a/ListMailboxes/run.ps1 +++ b/ListMailboxes/run.ps1 @@ -13,7 +13,11 @@ Write-Host 'PowerShell HTTP trigger function processed a request.' # Interact with query parameters or the body of the request. $TenantFilter = $Request.Query.TenantFilter try { - $users = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/?`$top=999&`$select=id,userPrincipalName,assignedLicenses" -Tenantid $tenantfilter + if ([bool]$Request.Query.SkipLicense -ne $true) { + $users = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/?`$top=999&`$select=id,userPrincipalName,assignedLicenses" -Tenantid $tenantfilter + } else { + $users = @() + } $ExoRequest = @{ tenantid = $TenantFilter diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecMailboxRestore.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecMailboxRestore.ps1 index f483d40ae7a7..8dc0bf5981f6 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecMailboxRestore.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecMailboxRestore.ps1 @@ -1,49 +1,89 @@ function Invoke-ExecMailboxRestore { + <# + .FUNCTIONALITY + Entrypoint + #> Param($Request, $TriggerMetadata) $APIName = $TriggerMetadata.FunctionName Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' - # Interact with query parameters or the body of the request. - $TenantFilter = $Request.Body.TenantFilter - $RequestName = $Request.Body.RequestName - $SourceMailbox = $Request.Body.SourceMailbox - $TargetMailbox = $Request.Body.TargetMailbox - try { - $ExoRequest = @{ - tenantid = $TenantFilter - cmdlet = 'New-MailboxRestoreRequest' - cmdParams = @{ - Name = $RequestName - SourceMailbox = $SourceMailbox - TargetMailbox = $TargetMailbox - AllowLegacyDNMismatch = $true + switch ($Request.Query.Action) { + 'Remove' { + $ExoRequest = @{ + tenantid = $Request.Query.TenantFilter + cmdlet = 'Remove-MailboxRestoreRequest' + cmdParams = @{ + Identity = $Request.Query.Identity + } + } + $SuccessMessage = 'Mailbox restore request removed successfully' + } + 'Resume' { + $ExoRequest = @{ + tenantid = $Request.Query.TenantFilter + cmdlet = 'Resume-MailboxRestoreRequest' + cmdParams = @{ + Identity = $Request.Query.Identity + } + } + $SuccessMessage = 'Mailbox restore request resumed successfully' + } + 'Suspend' { + $ExoRequest = @{ + tenantid = $Request.Query.TenantFilter + cmdlet = 'Suspend-MailboxRestoreRequest' + cmdParams = @{ + Identity = $Request.Query.Identity + } + } + $SuccessMessage = 'Mailbox restore request suspended successfully' + } + default { + $TenantFilter = $Request.Body.TenantFilter + $RequestName = $Request.Body.RequestName + $SourceMailbox = $Request.Body.SourceMailbox + $TargetMailbox = $Request.Body.TargetMailbox + + $ExoRequest = @{ + tenantid = $TenantFilter + cmdlet = 'New-MailboxRestoreRequest' + cmdParams = @{ + Name = $RequestName + SourceMailbox = $SourceMailbox + TargetMailbox = $TargetMailbox + AllowLegacyDNMismatch = $true + } + } + if ([bool]$Request.Body.AcceptLargeDataLoss -eq $true) { + $ExoRequest.cmdParams.AcceptLargeDataLoss = $true + } + if ([int]$Request.Body.BadItemLimit -gt 0) { + $ExoRequest.cmdParams.BadItemLimit = $Request.Body.BadItemLimit + } + if ([int]$Request.Body.LargeItemLimit -gt 0) { + $ExoRequest.cmdParams.LargeItemLimit = $Request.Body.LargeItemLimit + } + + $SuccessMessage = 'Mailbox restore request created successfully' } - } - if ([bool]$Request.Body.AcceptLargeDataLoss -eq $true) { - $ExoRequest.cmdParams.AcceptLargeDataLoss = $true - } - if ([int]$Request.Body.BadItemLimit -gt 0) { - $ExoRequest.cmdParams.BadItemLimit = $Request.Body.BadItemLimit - } - if ([int]$Request.Body.LargeItemLimit -gt 0) { - $ExoRequest.cmdParams.LargeItemLimit = $Request.Body.LargeItemLimit } $GraphRequest = New-ExoRequest @ExoRequest $Body = @{ RestoreRequest = $GraphRequest - Results = @('Mailbox restore request started successfully') + Results = @($SuccessMessage) } $StatusCode = [HttpStatusCode]::OK } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message - $StatusCode = [HttpStatusCode]::Forbidden + $StatusCode = [HttpStatusCode]::OK $Body = @{ RestoreRequest = $null Results = @($ErrorMessage) + colour = 'danger' } } # Associate values to output bindings by calling 'Push-OutputBinding'. From 684a21701b819ecfb744aa7dfb02fd6c729950a4 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 14 Nov 2023 16:36:56 -0500 Subject: [PATCH 24/55] BobbyTables fix - Limit returned properties to prevent entity error when removing --- ExecDnsConfig/run.ps1 | 2 +- ExecExcludeLicenses/run.ps1 | 10 +++---- ListMailboxRules/run.ps1 | 18 ++++++------ .../Push-ListGraphRequestQueue.ps1 | 2 +- .../Public/Remove-CIPPGraphSubscription.ps1 | 28 +++++++++---------- RemoveCATemplate/run.ps1 | 17 ++++++----- RemoveExConnectorTemplate/run.ps1 | 17 ++++++----- RemoveGroupTemplate/run.ps1 | 17 ++++++----- RemoveIntuneTemplate/run.ps1 | 17 ++++++----- RemoveQueuedAlert/run.ps1 | 7 ++--- RemoveQueuedApp/run.ps1 | 17 ++++++----- RemoveSpamfilterTemplate/run.ps1 | 17 ++++++----- RemoveStandard/run.ps1 | 17 ++++++----- RemoveTransportRuleTemplate/run.ps1 | 7 ++--- 14 files changed, 90 insertions(+), 103 deletions(-) diff --git a/ExecDnsConfig/run.ps1 b/ExecDnsConfig/run.ps1 index 697a3ac14930..f224d28c1e9e 100644 --- a/ExecDnsConfig/run.ps1 +++ b/ExecDnsConfig/run.ps1 @@ -87,7 +87,7 @@ try { } 'RemoveDomain' { $Filter = "RowKey eq '{0}'" -f $Request.Query.Domain - $DomainRow = Get-CIPPAzDataTableEntity @DomainTable -Filter $Filter + $DomainRow = Get-CIPPAzDataTableEntity @DomainTable -Filter $Filter -Property PartitionKey, RowKey Remove-AzDataTableEntity @DomainTable -Entity $DomainRow Write-LogMessage -API $APINAME -tenant 'Global' -user $request.headers.'x-ms-client-principal' -message "Removed Domain - $($Request.Query.Domain) " -Sev 'Info' $body = [pscustomobject]@{ 'Results' = "Domain removed - $($Request.Query.Domain)" } diff --git a/ExecExcludeLicenses/run.ps1 b/ExecExcludeLicenses/run.ps1 index 9db35ec5b002..1ecedd09c706 100644 --- a/ExecExcludeLicenses/run.ps1 +++ b/ExecExcludeLicenses/run.ps1 @@ -11,7 +11,7 @@ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -m Write-Host 'PowerShell HTTP trigger function processed a request.' $Table = Get-CIPPTable -TableName ExcludedLicenses try { - + if ($Request.Query.List) { $Rows = Get-CIPPAzDataTableEntity @Table if ($Rows.Count -lt 1) { @@ -19,10 +19,10 @@ try { $TableRows = foreach ($Row in $TableBaseData) { $Row.PartitionKey = 'License' $Row.RowKey = $Row.GUID - + Add-CIPPAzDataTableEntity @Table -Entity ([pscustomobject]$Row) -Force | Out-Null } - + $Rows = Get-CIPPAzDataTableEntity @Table Write-LogMessage -API $APINAME -user $request.headers.'x-ms-client-principal' -message 'got excluded licenses list' -Sev 'Info' @@ -41,13 +41,13 @@ try { } Add-CIPPAzDataTableEntity @Table -Entity $AddObject -Force - Write-LogMessage -API $APINAME -user $request.headers.'x-ms-client-principal' -message "Added exclusion $($request.body.SKUName)" -Sev 'Info' + Write-LogMessage -API $APINAME -user $request.headers.'x-ms-client-principal' -message "Added exclusion $($request.body.SKUName)" -Sev 'Info' $body = [pscustomobject]@{'Results' = "Success. We've added $($request.body.SKUName) to the excluded list." } } if ($Request.Query.RemoveExclusion) { $Filter = "RowKey eq '{0}' and PartitionKey eq 'License'" -f $Request.Query.Guid - $Entity = Get-CIPPAzDataTableEntity @Table -Filter $Filter + $Entity = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey Remove-AzDataTableEntity @Table -Entity $Entity Write-LogMessage -API $APINAME -user $request.headers.'x-ms-client-principal' -message "Removed exclusion $($Request.Query.GUID)" -Sev 'Info' $body = [pscustomobject]@{'Results' = "Success. We've removed $($Request.query.guid) from the excluded list." } diff --git a/ListMailboxRules/run.ps1 b/ListMailboxRules/run.ps1 index c57f61520169..d2150d11e636 100644 --- a/ListMailboxRules/run.ps1 +++ b/ListMailboxRules/run.ps1 @@ -21,26 +21,24 @@ if (!$Rows) { Tenant = 'Loading data. Please check back in 1 minute' Licenses = 'Loading data. Please check back in 1 minute' } -} -else { - if ($TenantFilter -ne "AllTenants") { - $GraphRequest = $Rows | Where-Object -Property Tenant -EQ $TenantFilter | ForEach-Object { +} else { + if ($TenantFilter -ne 'AllTenants') { + $GraphRequest = $Rows | Where-Object -Property Tenant -EQ $TenantFilter | ForEach-Object { $NewObj = $_.Rules | ConvertFrom-Json - $NewObj | Add-Member -NotePropertyName "Tenant" -NotePropertyValue $TenantFilter + $NewObj | Add-Member -NotePropertyName 'Tenant' -NotePropertyValue $TenantFilter $NewObj } - } - else { - $GraphRequest = $Rows | ForEach-Object { + } else { + $GraphRequest = $Rows | ForEach-Object { $TenantName = $_.Tenant $NewObj = $_.Rules | ConvertFrom-Json - $NewObj | Add-Member -NotePropertyName "Tenant" -NotePropertyValue $TenantName + $NewObj | Add-Member -NotePropertyName 'Tenant' -NotePropertyValue $TenantName $NewObj } } } #Remove all old cache -Remove-AzDataTableEntity @Table -Entity (Get-CIPPAzDataTableEntity @Table | Where-Object -Property Timestamp -LT (Get-Date).AddMinutes(-15)) +Remove-AzDataTableEntity @Table -Entity (Get-CIPPAzDataTableEntity @Table -Property PartitionKey, RowKey, Timestamp | Where-Object -Property Timestamp -LT (Get-Date).AddMinutes(-15)) Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ diff --git a/Modules/CIPPCore/Public/Entrypoints/Push-ListGraphRequestQueue.ps1 b/Modules/CIPPCore/Public/Entrypoints/Push-ListGraphRequestQueue.ps1 index 9bb3b2086bcd..d760261ef6aa 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Push-ListGraphRequestQueue.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Push-ListGraphRequestQueue.ps1 @@ -25,7 +25,7 @@ function Push-ListGraphRequestQueue { $Filter = "PartitionKey eq '{0}' and Tenant eq '{1}'" -f $PartitionKey, $QueueItem.Tenant Write-Host $Filter - Get-CIPPAzDataTableEntity @Table -Filter $Filter | Remove-AzDataTableEntity @Table + Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey | Remove-AzDataTableEntity @Table $GraphRequestParams = @{ TenantFilter = $QueueItem.TenantFilter diff --git a/Modules/CIPPCore/Public/Remove-CIPPGraphSubscription.ps1 b/Modules/CIPPCore/Public/Remove-CIPPGraphSubscription.ps1 index 9bd4e8df50f9..e0ff1f4ef9ad 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPGraphSubscription.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPGraphSubscription.ps1 @@ -3,31 +3,29 @@ function Remove-CIPPGraphSubscription { param ( $TenantFilter, $CIPPID, - $APIName = "Remove Graph Webhook", + $APIName = 'Remove Graph Webhook', $ExecutingUser ) try { $WebhookTable = Get-CIPPTable -TableName webhookTable $WebhookRow = Get-CIPPAzDataTableEntity @WebhookTable | Where-Object { $_.RowKey -eq $CIPPID } - if ($WebhookRow.Resource -eq "M365AuditLogs") { + $Entity = $WebhookRow | Select-Object PartitionKey, RowKey + if ($WebhookRow.Resource -eq 'M365AuditLogs') { try { - $AuditLog = New-GraphPOSTRequest -uri "https://manage.office.com/api/v1.0/$($TenantFilter)/activity/feed/subscriptions/stop?contentType=$($WebhookRow.EventType)" -scope "https://manage.office.com/.default" -tenantid $TenantFilter -type POST -body "{}" -verbose - } - catch { + $AuditLog = New-GraphPOSTRequest -uri "https://manage.office.com/api/v1.0/$($TenantFilter)/activity/feed/subscriptions/stop?contentType=$($WebhookRow.EventType)" -scope 'https://manage.office.com/.default' -tenantid $TenantFilter -type POST -body '{}' -verbose + } catch { #allowed to fail if the subscription is already removed } - $null = Remove-AzDataTableEntity @WebhookTable -Entity $WebhookRow - } - else { - $OldID = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/subscriptions" -tenantid $TenantFilter) | Where-Object { $_.notificationUrl -eq $WebhookRow.WebhookNotificationUrl } + $null = Remove-AzDataTableEntity @WebhookTable -Entity $Entity + } else { + $OldID = (New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/subscriptions' -tenantid $TenantFilter) | Where-Object { $_.notificationUrl -eq $WebhookRow.WebhookNotificationUrl } $GraphRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/subscriptions/$($oldId.ID)" -tenantid $TenantFilter -type DELETE -body {} -Verbose - $null = Remove-AzDataTableEntity @WebhookTable -Entity $WebhookRow + $null = Remove-AzDataTableEntity @WebhookTable -Entity $Entity } - return "Removed webhook subscription to $($WebhookRow.resource) for $($TenantFilter)" + return "Removed webhook subscription to $($WebhookRow.resource) for $($TenantFilter)" - } - catch { - Write-LogMessage -user $ExecutingUser -API $APIName -message "Failed to renew Webhook Subscription: $($_.Exception.Message)" -Sev "Error" -tenant $TenantFilter - return "Failed to remove Webhook Subscription $($GraphRequest.value.notificationUrl): $($_.Exception.Message)" + } catch { + Write-LogMessage -user $ExecutingUser -API $APIName -message "Failed to renew Webhook Subscription: $($_.Exception.Message)" -Sev 'Error' -tenant $TenantFilter + return "Failed to remove Webhook Subscription $($GraphRequest.value.notificationUrl): $($_.Exception.Message)" } } \ No newline at end of file diff --git a/RemoveCATemplate/run.ps1 b/RemoveCATemplate/run.ps1 index e518b5b37664..4d682d715b92 100644 --- a/RemoveCATemplate/run.ps1 +++ b/RemoveCATemplate/run.ps1 @@ -4,21 +4,20 @@ using namespace System.Net param($Request, $TriggerMetadata) $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" +Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' $ID = $request.query.id try { $Table = Get-CippTable -tablename 'templates' - $Filter = "PartitionKey eq 'CATemplate' and RowKey eq '$id'" - $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter + $Filter = "PartitionKey eq 'CATemplate' and RowKey eq '$id'" + $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey Remove-AzDataTableEntity @Table -Entity $clearRow - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Removed Conditional Access Template with ID $ID." -Sev "Info" - $body = [pscustomobject]@{"Results" = "Successfully removed Conditional Access Template" } -} -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to remove Conditional Access template $ID. $($_.Exception.Message)" -Sev "Error" - $body = [pscustomobject]@{"Results" = "Failed to remove template: $($_.Exception.Message)" } + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Removed Conditional Access Template with ID $ID." -Sev 'Info' + $body = [pscustomobject]@{'Results' = 'Successfully removed Conditional Access Template' } +} catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to remove Conditional Access template $ID. $($_.Exception.Message)" -Sev 'Error' + $body = [pscustomobject]@{'Results' = "Failed to remove template: $($_.Exception.Message)" } } diff --git a/RemoveExConnectorTemplate/run.ps1 b/RemoveExConnectorTemplate/run.ps1 index 0b2ddf87fc91..718e4e72e403 100644 --- a/RemoveExConnectorTemplate/run.ps1 +++ b/RemoveExConnectorTemplate/run.ps1 @@ -4,20 +4,19 @@ using namespace System.Net param($Request, $TriggerMetadata) $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" +Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' $ID = $request.query.id try { $Table = Get-CippTable -tablename 'templates' - $Filter = "PartitionKey eq 'ExConnectorTemplate' and RowKey eq '$id'" - $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter + $Filter = "PartitionKey eq 'ExConnectorTemplate' and RowKey eq '$id'" + $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey Remove-AzDataTableEntity @Table -Entity $clearRow - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Removed Exchange Connector Template with ID $ID." -Sev "Info" - $body = [pscustomobject]@{"Results" = "Successfully removed Exchange Connector Template" } -} -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to remove Exchange Connector Template $ID. $($_.Exception.Message)" -Sev "Error" - $body = [pscustomobject]@{"Results" = "Failed to remove template: $($_.Exception.Message)" } + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Removed Exchange Connector Template with ID $ID." -Sev 'Info' + $body = [pscustomobject]@{'Results' = 'Successfully removed Exchange Connector Template' } +} catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to remove Exchange Connector Template $ID. $($_.Exception.Message)" -Sev 'Error' + $body = [pscustomobject]@{'Results' = "Failed to remove template: $($_.Exception.Message)" } } diff --git a/RemoveGroupTemplate/run.ps1 b/RemoveGroupTemplate/run.ps1 index 98b6d7680e03..d9069b9f7e3c 100644 --- a/RemoveGroupTemplate/run.ps1 +++ b/RemoveGroupTemplate/run.ps1 @@ -4,23 +4,22 @@ using namespace System.Net param($Request, $TriggerMetadata) $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" +Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' $ID = $request.query.id try { $Table = Get-CippTable -tablename 'templates' Write-Host $id - $Filter = "PartitionKey eq 'GroupTemplate' and RowKey eq '$id'" + $Filter = "PartitionKey eq 'GroupTemplate' and RowKey eq '$id'" Write-Host $Filter - $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter + $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey Remove-AzDataTableEntity @Table -Entity $clearRow - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Removed Intune Template with ID $ID." -Sev "Info" - $body = [pscustomobject]@{"Results" = "Successfully removed Template" } -} -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to remove intune template $ID. $($_.Exception.Message)" -Sev "Error" - $body = [pscustomobject]@{"Results" = "Failed to remove template: $($_.Exception.Message)" } + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Removed Intune Template with ID $ID." -Sev 'Info' + $body = [pscustomobject]@{'Results' = 'Successfully removed Template' } +} catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to remove intune template $ID. $($_.Exception.Message)" -Sev 'Error' + $body = [pscustomobject]@{'Results' = "Failed to remove template: $($_.Exception.Message)" } } diff --git a/RemoveIntuneTemplate/run.ps1 b/RemoveIntuneTemplate/run.ps1 index 5d716b3e8c52..c4f678b4eef4 100644 --- a/RemoveIntuneTemplate/run.ps1 +++ b/RemoveIntuneTemplate/run.ps1 @@ -4,23 +4,22 @@ using namespace System.Net param($Request, $TriggerMetadata) $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" +Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' $ID = $request.query.id try { $Table = Get-CippTable -tablename 'templates' Write-Host $id - $Filter = "PartitionKey eq 'IntuneTemplate' and RowKey eq '$id'" + $Filter = "PartitionKey eq 'IntuneTemplate' and RowKey eq '$id'" Write-Host $Filter - $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter + $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey Remove-AzDataTableEntity @Table -Entity $clearRow - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Removed Intune Template with ID $ID." -Sev "Info" - $body = [pscustomobject]@{"Results" = "Successfully removed Intune Template" } -} -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to remove intune template $ID. $($_.Exception.Message)" -Sev "Error" - $body = [pscustomobject]@{"Results" = "Failed to remove template: $($_.Exception.Message)" } + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Removed Intune Template with ID $ID." -Sev 'Info' + $body = [pscustomobject]@{'Results' = 'Successfully removed Intune Template' } +} catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to remove intune template $ID. $($_.Exception.Message)" -Sev 'Error' + $body = [pscustomobject]@{'Results' = "Failed to remove template: $($_.Exception.Message)" } } diff --git a/RemoveQueuedAlert/run.ps1 b/RemoveQueuedAlert/run.ps1 index 4317546c0a10..81b7a3cb907b 100644 --- a/RemoveQueuedAlert/run.ps1 +++ b/RemoveQueuedAlert/run.ps1 @@ -5,16 +5,15 @@ param($Request, $TriggerMetadata) $APIName = $TriggerMetadata.FunctionName Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -$Table = Get-CIPPTable -TableName 'SchedulerConfig' +$Table = Get-CIPPTable -TableName 'SchedulerConfig' $ID = $request.query.id try { $Filter = "RowKey eq '{0}' and PartitionKey eq 'Alert'" -f $ID - $Alert = Get-CIPPAzDataTableEntity @Table -Filter $Filter + $Alert = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey Remove-AzDataTableEntity @Table -Entity $Alert Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Removed application queue for $ID." -Sev 'Info' $body = [pscustomobject]@{'Results' = 'Successfully removed from queue.' } -} -catch { +} catch { Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to remove from queue $ID. $($_.Exception.Message)" -Sev 'Error' $body = [pscustomobject]@{'Results' = "Failed to remove alert from queue $($_.Exception.Message)" } } diff --git a/RemoveQueuedApp/run.ps1 b/RemoveQueuedApp/run.ps1 index 62b7e9a83a64..7ce40f7ca3fd 100644 --- a/RemoveQueuedApp/run.ps1 +++ b/RemoveQueuedApp/run.ps1 @@ -4,20 +4,19 @@ using namespace System.Net param($Request, $TriggerMetadata) $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" +Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' $ID = $request.query.id try { $Table = Get-CippTable -tablename 'apps' - $Filter = "PartitionKey eq 'apps' and RowKey eq '$id'" - $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter + $Filter = "PartitionKey eq 'apps' and RowKey eq '$id'" + $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey Remove-AzDataTableEntity @Table -Entity $clearRow - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Removed application queue for $ID." -Sev "Info" - $body = [pscustomobject]@{"Results" = "Successfully removed from queue." } -} -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to remove application queue for $ID. $($_.Exception.Message)" -Sev "Error" - $body = [pscustomobject]@{"Results" = "Failed to remove standard)" } + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Removed application queue for $ID." -Sev 'Info' + $body = [pscustomobject]@{'Results' = 'Successfully removed from queue.' } +} catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to remove application queue for $ID. $($_.Exception.Message)" -Sev 'Error' + $body = [pscustomobject]@{'Results' = 'Failed to remove standard)' } } diff --git a/RemoveSpamfilterTemplate/run.ps1 b/RemoveSpamfilterTemplate/run.ps1 index 271fe5ca5cff..a79169c0995a 100644 --- a/RemoveSpamfilterTemplate/run.ps1 +++ b/RemoveSpamfilterTemplate/run.ps1 @@ -4,20 +4,19 @@ using namespace System.Net param($Request, $TriggerMetadata) $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" +Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' $ID = $request.query.id try { $Table = Get-CippTable -tablename 'templates' - $Filter = "PartitionKey eq 'SpamfilterTemplate' and RowKey eq '$id'" - $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter + $Filter = "PartitionKey eq 'SpamfilterTemplate' and RowKey eq '$id'" + $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey Remove-AzDataTableEntity @Table -Entity $clearRow - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Removed Transport Rule Template with ID $ID." -Sev "Info" - $body = [pscustomobject]@{"Results" = "Successfully removed Transport Rule Template" } -} -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to remove Transport Rule template $ID. $($_.Exception.Message)" -Sev "Error" - $body = [pscustomobject]@{"Results" = "Failed to remove template: $($_.Exception.Message)" } + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Removed Transport Rule Template with ID $ID." -Sev 'Info' + $body = [pscustomobject]@{'Results' = 'Successfully removed Transport Rule Template' } +} catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to remove Transport Rule template $ID. $($_.Exception.Message)" -Sev 'Error' + $body = [pscustomobject]@{'Results' = "Failed to remove template: $($_.Exception.Message)" } } diff --git a/RemoveStandard/run.ps1 b/RemoveStandard/run.ps1 index b1ed82e61385..c38d977111f2 100644 --- a/RemoveStandard/run.ps1 +++ b/RemoveStandard/run.ps1 @@ -4,22 +4,21 @@ using namespace System.Net param($Request, $TriggerMetadata) $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" +Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' $ID = $request.query.id try { $Table = Get-CippTable -tablename 'standards' - $Filter = "PartitionKey eq 'standards' and RowKey eq '$id'" - $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter + $Filter = "PartitionKey eq 'standards' and RowKey eq '$id'" + $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey Remove-AzDataTableEntity @Table -Entity $clearRow - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Removed standards for $ID." -Sev "Info" - $body = [pscustomobject]@{"Results" = "Successfully removed standards deployment" } + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Removed standards for $ID." -Sev 'Info' + $body = [pscustomobject]@{'Results' = 'Successfully removed standards deployment' } -} -catch { - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to remove standard for $ID. $($_.Exception.Message)" -Sev "Error" - $body = [pscustomobject]@{"Results" = "Failed to remove standard)" } +} catch { + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to remove standard for $ID. $($_.Exception.Message)" -Sev 'Error' + $body = [pscustomobject]@{'Results' = 'Failed to remove standard)' } } diff --git a/RemoveTransportRuleTemplate/run.ps1 b/RemoveTransportRuleTemplate/run.ps1 index 9ab1b6af2fc0..7e4b7b6b6548 100644 --- a/RemoveTransportRuleTemplate/run.ps1 +++ b/RemoveTransportRuleTemplate/run.ps1 @@ -9,13 +9,12 @@ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -m $ID = $request.query.id try { $Table = Get-CippTable -tablename 'templates' - $Filter = "PartitionKey eq 'TransportTemplate' and RowKey eq '$id'" - $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter + $Filter = "PartitionKey eq 'TransportTemplate' and RowKey eq '$id'" + $ClearRow = Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey Remove-AzDataTableEntity @Table -Entity $clearRow Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Removed Transport Rule Template with ID $ID." -Sev 'Info' $body = [pscustomobject]@{'Results' = 'Successfully removed Transport Rule Template' } -} -catch { +} catch { Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Failed to remove Transport Rule template $ID. $($_.Exception.Message)" -Sev 'Error' $body = [pscustomobject]@{'Results' = "Failed to remove template: $($_.Exception.Message)" } } From 58009023d55867876d2b38df74b1b53db5233ca1 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Tue, 14 Nov 2023 17:20:44 -0500 Subject: [PATCH 25/55] Update Push-ListGraphRequestQueue.ps1 --- .../Public/Entrypoints/Push-ListGraphRequestQueue.ps1 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/CIPPCore/Public/Entrypoints/Push-ListGraphRequestQueue.ps1 b/Modules/CIPPCore/Public/Entrypoints/Push-ListGraphRequestQueue.ps1 index d760261ef6aa..126e8d14335d 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Push-ListGraphRequestQueue.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Push-ListGraphRequestQueue.ps1 @@ -7,9 +7,9 @@ function Push-ListGraphRequestQueue { param($QueueItem, $TriggerMetadata) # Write out the queue message and metadata to the information log. - Write-Host "PowerShell queue trigger function processed work item: $($QueueItem.Endpoint) - $($QueueItem.Tenant)" + Write-Host "PowerShell queue trigger function processed work item: $($QueueItem.Endpoint) - $($QueueItem.TenantFilter)" - $TenantQueueName = '{0} - {1}' -f $QueueItem.QueueName, $QueueItem.Tenant + $TenantQueueName = '{0} - {1}' -f $QueueItem.QueueName, $QueueItem.TenantFilter Update-CippQueueEntry -RowKey $QueueItem.QueueId -Status 'Processing' -Name $TenantQueueName $ParamCollection = [System.Web.HttpUtility]::ParseQueryString([String]::Empty) @@ -23,7 +23,7 @@ function Push-ListGraphRequestQueue { Write-Host $TableName $Table = Get-CIPPTable -TableName $TableName - $Filter = "PartitionKey eq '{0}' and Tenant eq '{1}'" -f $PartitionKey, $QueueItem.Tenant + $Filter = "PartitionKey eq '{0}' and Tenant eq '{1}'" -f $PartitionKey, $QueueItem.TenantFilter Write-Host $Filter Get-CIPPAzDataTableEntity @Table -Filter $Filter -Property PartitionKey, RowKey | Remove-AzDataTableEntity @Table @@ -49,7 +49,7 @@ function Push-ListGraphRequestQueue { $GraphResults = foreach ($Request in $RawGraphRequest) { $Json = ConvertTo-Json -Depth 5 -Compress -InputObject $Request [PSCustomObject]@{ - Tenant = [string]$QueueItem.Tenant + TenantFilter = [string]$QueueItem.TenantFilter QueueId = [string]$QueueItem.QueueId QueueType = [string]$QueueItem.QueueType RowKey = [string](New-Guid) From e5e45f2f2b046e7169c55f43187fb7d110f9f6ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Tue, 14 Nov 2023 23:23:15 +0100 Subject: [PATCH 26/55] Updated OTP log message --- Standards_allowOTPTokens/run.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Standards_allowOTPTokens/run.ps1 b/Standards_allowOTPTokens/run.ps1 index 4619289b1f84..c9d138129cce 100644 --- a/Standards_allowOTPTokens/run.ps1 +++ b/Standards_allowOTPTokens/run.ps1 @@ -8,8 +8,8 @@ try { $body = ($CurrentInfo | ConvertTo-Json -Depth 10) (New-GraphPostRequest -tenantid $tenant -Uri "https://graph.microsoft.com/beta/policies/authenticationMethodsPolicy/authenticationMethodConfigurations/microsoftAuthenticator" -Type patch -Body $body -ContentType "application/json") - Write-LogMessage -API "Standards" -tenant $tenant -message "Enabled software OTP/oAuth tokens" -sev Info + Write-LogMessage -API "Standards" -tenant $tenant -message "Enabled MS authenticator OTP/oAuth tokens" -sev Info } catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to enable software OTP/oAuth tokens. Error: $($_.exception.message)" -sev "Error" + Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to enable MS authenticator OTP/oAuth tokens. Error: $($_.exception.message)" -sev "Error" } \ No newline at end of file From 460431fbea40f466ffa054f76babad39bf469bc7 Mon Sep 17 00:00:00 2001 From: rvdwegen Date: Tue, 14 Nov 2023 23:42:21 +0100 Subject: [PATCH 27/55] Add tenant offboarding feature --- ExecOffboardTenant/function.json | 16 +++++ ExecOffboardTenant/run.ps1 | 108 +++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 ExecOffboardTenant/function.json create mode 100644 ExecOffboardTenant/run.ps1 diff --git a/ExecOffboardTenant/function.json b/ExecOffboardTenant/function.json new file mode 100644 index 000000000000..4ee273331c44 --- /dev/null +++ b/ExecOffboardTenant/function.json @@ -0,0 +1,16 @@ +{ + "bindings": [ + { + "authLevel": "anonymous", + "type": "httpTrigger", + "direction": "in", + "name": "Request", + "methods": ["get", "post"] + }, + { + "type": "http", + "direction": "out", + "name": "Response" + } + ] +} diff --git a/ExecOffboardTenant/run.ps1 b/ExecOffboardTenant/run.ps1 new file mode 100644 index 000000000000..a8be1ff1d1b5 --- /dev/null +++ b/ExecOffboardTenant/run.ps1 @@ -0,0 +1,108 @@ +using namespace System.Net +# Input bindings are passed in via param block. +param($Request, $TriggerMetadata) +try { + $APIName = $TriggerMetadata.FunctionName + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" + + $Tenantfilter = $request.body.tenantfilter + + $results = [System.Collections.ArrayList]@() + $errors = [System.Collections.ArrayList]@() + + if ($request.body.RemoveCSPGuestUsers) { + # Delete guest users who's domains match the CSP tenants + try { + try { + $domains = (New-GraphGETRequest -Uri "https://graph.microsoft.com/v1.0/domains?`$select=id" -tenantid $env:TenantID -NoAuthCheck:$true).id + $CSPGuestUsers = (New-GraphGETRequest -Uri "https://graph.microsoft.com/v1.0/users?`$select=id,mail&`$filter=userType eq 'Guest' and $(($domains | ForEach-Object { "endswith(mail, '$_')" }) -join " or ")&`$count=true" -tenantid $Tenantfilter -ComplexFilter) + } catch { + $errors.Add("Failed to retrieve guest users: $($_.Exception.message)") + } + + if ($CSPGuestUsers) { + [System.Collections.Generic.List[PSCustomObject]]$BulkRequests = @($CSPGuestUsers | ForEach-Object { + @{ + id = $($_.id) + method = "DELETE" + url = "/users/$($_.id)" + } + }) + + $BulkResults = New-GraphBulkRequest -Requests $BulkRequests -tenantid $TenantFilter + + $results.Add("Succesfully removed guest users") + } else { + $results.Add("No guest users found to remove") + } + } catch { + $errors.Add("Something went wrong while deleting guest users: $($_.Exception.message)") + } + } + + # All customer tenant specific actions ALWAYS have to be completed before this action! + if ($request.body.RemoveMultitenantApps) { + # Remove multi-tenant apps with the CSP tenant as origin + try { + $multitenantCSPApps = (New-GraphGETRequest -Uri "https://graph.microsoft.com/v1.0/servicePrincipals?`$count=true&`$select=displayName,appId,id,appOwnerOrganizationId&`$filter=appOwnerOrganizationId eq $($env:TenantID)" -tenantid $Tenantfilter -ComplexFilter) + $sortedArray = $multitenantCSPApps | Sort-Object @{Expression = { if ($_.appId -eq $env:applicationid) { 1 } else { 0 } }; Ascending = $true } + $sortedArray | ForEach-Object { + try { + $delete = (New-GraphPostRequest -type "DELETE" -Uri "https://graph.microsoft.com/v1.0/serviceprincipals/$($_.id)" -tenantid $Tenantfilter) + $results.Add("Succesfully removed app $($_.displayName)") + } catch { + #$results.Add("Failed to removed app $($_.displayName)") + $errors.Add("Failed to removed app $($_.displayName)") + } + } + } catch { + #$results.Add("Failed to retrieve multitenant apps, no apps have been removed: $($_.Exception.message)") + $errors.Add("Failed to retrieve multitenant apps, no apps have been removed: $($_.Exception.message)") + } + } + + if ($request.body.TerminateGDAP) { + # Terminate GDAP relationships + try { + $delegatedAdminRelationships = (New-GraphGETRequest -Uri "https://graph.microsoft.com/v1.0/tenantRelationships/delegatedAdminRelationships?`$filter=(status eq 'active') AND (customer/tenantId eq '$TenantFilter')" -tenantid $env:TenantID) + $delegatedAdminRelationships | ForEach-Object { + try { + $terminate = (New-GraphPostRequest -type "POST" -Uri "https://graph.microsoft.com/v1.0/tenantRelationships/delegatedAdminRelationships/$($_.id)/requests" -body '{"action":"terminate"}' -ContentType "application/json" -tenantid $env:TenantID) + $results.Add("Succesfully terminated GDAP relationship $($_.displayName) from tenant $TenantFilter") + } catch { + #$results.Add("Failed to terminate GDAP relationship $($_.displayName): $($_.Exception.message)") + $errors.Add("Failed to terminate GDAP relationship $($_.displayName): $($_.Exception.message)") + } + } + } catch { + #$results.Add("Failed to retrieve GDAP relationships, no relationships have been terminated: $($_.Exception.message)") + $errors.Add("Failed to retrieve GDAP relationships, no relationships have been terminated: $($_.Exception.message)") + } + } + + if ($request.body.TerminateContract) { + # Terminate contract relationship + try { + $terminate = (New-GraphPostRequest -type "PATCH" -body '{ "relationshipToPartner": "none" }' -Uri "https://api.partnercenter.microsoft.com/v1/customers/$TenantFilter" -ContentType "application/json" -scope "https://api.partnercenter.microsoft.com/user_impersonation" -tenantid $env:TenantID) + $results.Add("Succesfully terminated contract relationship") + } + catch { + #$results.Add("Failed to terminate contract relationship: $($_.Exception.message)") + $errors.Add("Failed to terminate contract relationship: $($_.Exception.message)") + } + } + + $StatusCode = [HttpStatusCode]::OK + $body = [pscustomobject]@{ + "Results" = @($results) + "Errors" = @($errors) + } +} +catch { + $StatusCode = [HttpStatusCode]::OK + $body = $_.Exception.message +} +Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = $StatusCode + Body = $Body + }) \ No newline at end of file From 030355a59b03ea219c2569f254d87a6fdab7f353 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Wed, 15 Nov 2023 01:40:16 +0100 Subject: [PATCH 28/55] fixes bug with standard setup --- Standards_GetQueue/run.ps1 | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Standards_GetQueue/run.ps1 b/Standards_GetQueue/run.ps1 index 021fe7017d3e..24a4f64dc523 100644 --- a/Standards_GetQueue/run.ps1 +++ b/Standards_GetQueue/run.ps1 @@ -8,17 +8,22 @@ $Tenants = (Get-CIPPAzDataTableEntity @Table -Filter $Filter).JSON | ConvertFrom $object = foreach ($Tenant in $Tenants) { $Tenant.standards.psobject.properties.name | ForEach-Object { $Standard = $_ + Write-Host "Standard is $Standard" if ($Tenant.Tenant -ne 'AllTenants' -and $SkipList.defaultDomainName -notcontains $Tenant.Tenant) { Write-Host 'Not all tenants. Single object' - [pscustomobject]@{ - Tenant = $tenant.Tenant - Standard = $Standard + if ($Standard -ne "OverrideAllTenants") { + [pscustomobject]@{ + Tenant = $tenant.Tenant + Standard = $Standard + } } - } elseif ($Tenant.Tenant -eq 'AllTenants') { + } + elseif ($Tenant.Tenant -eq 'AllTenants') { Get-Tenants | ForEach-Object { - $Tenant = $_ - $TenantStandard = $Tenants | Where-Object { $_.Tenant -eq $Tenant.defaultDomainName } - if ($TenantStandard.OverrideAllTenants -ne $true) { + $TenantForStandard = $_ + $TenantStandard = $Tenants | Where-Object { $_.Tenant -eq $TenantForStandard.defaultDomainName } + Write-Host "Working on all Tenants. Current Tenant is $($Tenant.defaultDomainName) and standard is $Standard" + if ($TenantStandard.standards.OverrideAllTenants -ne $true) { [pscustomobject]@{ Tenant = $_.defaultDomainName Standard = $Standard @@ -28,4 +33,5 @@ $object = foreach ($Tenant in $Tenants) { } } } + $object \ No newline at end of file From 9b573f42b671104cf9902e927c4cc691a04777c6 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Wed, 15 Nov 2023 11:49:00 +0100 Subject: [PATCH 29/55] Fix all users --- Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 b/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 index 60f00e018b7b..0ebf6a798c04 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 @@ -13,7 +13,7 @@ function Remove-CIPPMailboxPermissions { if ($userid -eq "AllUsers") { $Mailboxes = New-ExoRequest -tenantid $QueueItem.TenantFilter -cmdlet "get-mailbox" foreach ($Mailbox in $Mailboxes) { - Remove-CIPPMailboxPermissions -PermissionsLevel $PermissionsLevel -userid $Mailbox.UserPrincipalName -AccessUser $QueueItem.User -TenantFilter $QueueItem.TenantFilter -APIName $APINAME -ExecutingUser $QueueItem.ExecutingUser + Remove-CIPPMailboxPermissions -PermissionsLevel @("FullAccess", "SendAs", "SendOnBehalf") -userid $Mailbox.UserPrincipalName -AccessUser $AccessUser -TenantFilter $QueueItem.TenantFilter -APIName $APINAME -ExecutingUser $ExecutingUser } } else { From 96268c5105ab009b1c501132e6f63eed3cc33115 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Wed, 15 Nov 2023 14:02:41 +0100 Subject: [PATCH 30/55] try catch the roles --- Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 | 2 +- Modules/CIPPCore/Public/Test-CIPPAccessTenant.ps1 | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 b/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 index 0ebf6a798c04..b327f7f9231c 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 @@ -13,7 +13,7 @@ function Remove-CIPPMailboxPermissions { if ($userid -eq "AllUsers") { $Mailboxes = New-ExoRequest -tenantid $QueueItem.TenantFilter -cmdlet "get-mailbox" foreach ($Mailbox in $Mailboxes) { - Remove-CIPPMailboxPermissions -PermissionsLevel @("FullAccess", "SendAs", "SendOnBehalf") -userid $Mailbox.UserPrincipalName -AccessUser $AccessUser -TenantFilter $QueueItem.TenantFilter -APIName $APINAME -ExecutingUser $ExecutingUser + Remove-CIPPMailboxPermissions -PermissionsLevel @("FullAccess", "SendAs", "SendOnBehalf") -userid $Mailbox.UserPrincipalName -AccessUser $AccessUser -TenantFilter $TenantFilter -APIName $APINAME -ExecutingUser $ExecutingUser } } else { diff --git a/Modules/CIPPCore/Public/Test-CIPPAccessTenant.ps1 b/Modules/CIPPCore/Public/Test-CIPPAccessTenant.ps1 index 677b642e24c0..dd82b4fe2b98 100644 --- a/Modules/CIPPCore/Public/Test-CIPPAccessTenant.ps1 +++ b/Modules/CIPPCore/Public/Test-CIPPAccessTenant.ps1 @@ -25,7 +25,13 @@ function Test-CIPPAccessTenant { $TenantIds = foreach ($Tenant in $Tenants) { ($TenantList | Where-Object { $_.defaultDomainName -eq $Tenant }).customerId } - $MyRoles = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/tenantRelationships/managedTenants/myRoles?`$filter=tenantId in ('$($TenantIds -join "','")')" + try { + $MyRoles = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/tenantRelationships/managedTenants/myRoles?`$filter=tenantId in ('$($TenantIds -join "','")')" + } + catch { + $MyRoles = @() + $AddedText = 'but could not retrieve GDAP roles from Lighthouse API' + } $results = foreach ($tenant in $Tenants) { $AddedText = '' try { From bb2305202c532f11bab5bd26b7dafa97bd8ffe15 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Wed, 15 Nov 2023 14:07:46 +0100 Subject: [PATCH 31/55] added some Halo PSA troubleshooting. --- Modules/CippExtensions/Private/New-HaloPSATicket.ps1 | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Modules/CippExtensions/Private/New-HaloPSATicket.ps1 b/Modules/CippExtensions/Private/New-HaloPSATicket.ps1 index 4b0690dc823d..2b1b18486d7b 100644 --- a/Modules/CippExtensions/Private/New-HaloPSATicket.ps1 +++ b/Modules/CippExtensions/Private/New-HaloPSATicket.ps1 @@ -36,8 +36,12 @@ function New-HaloPSATicket { Write-Host "Sending ticket to HaloPSA" Write-Host $body - - $Ticket = Invoke-RestMethod -Uri "$($Configuration.ResourceURL)/Tickets" -ContentType 'application/json; charset=utf-8' -Method Post -Body $body -Headers @{Authorization = "Bearer $($token.access_token)" } - + try { + $Ticket = Invoke-RestMethod -Uri "$($Configuration.ResourceURL)/Tickets" -ContentType 'application/json; charset=utf-8' -Method Post -Body $body -Headers @{Authorization = "Bearer $($token.access_token)" } + } + catch { + Write-Host "Failed to send ticket to HaloPSA" + Write-Host $_.Exception.Message + } } \ No newline at end of file From 8718df5437190dbd672dbe7818c11eb0345a9d4a Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Wed, 15 Nov 2023 14:09:57 +0100 Subject: [PATCH 32/55] replace tenantfilter --- Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 b/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 index b327f7f9231c..0f0245bf704f 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 @@ -11,7 +11,7 @@ function Remove-CIPPMailboxPermissions { try { if ($userid -eq "AllUsers") { - $Mailboxes = New-ExoRequest -tenantid $QueueItem.TenantFilter -cmdlet "get-mailbox" + $Mailboxes = New-ExoRequest -tenantid $TenantFilter -cmdlet "get-mailbox" foreach ($Mailbox in $Mailboxes) { Remove-CIPPMailboxPermissions -PermissionsLevel @("FullAccess", "SendAs", "SendOnBehalf") -userid $Mailbox.UserPrincipalName -AccessUser $AccessUser -TenantFilter $TenantFilter -APIName $APINAME -ExecutingUser $ExecutingUser } From 3947fbfef746195c8782e3797c16a4b5f4856f03 Mon Sep 17 00:00:00 2001 From: Jr7468 Date: Wed, 15 Nov 2023 14:25:33 +0000 Subject: [PATCH 33/55] Parallel all the things v2 --- Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 b/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 index 0f0245bf704f..d49dcb1f618c 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 @@ -12,9 +12,9 @@ function Remove-CIPPMailboxPermissions { try { if ($userid -eq "AllUsers") { $Mailboxes = New-ExoRequest -tenantid $TenantFilter -cmdlet "get-mailbox" - foreach ($Mailbox in $Mailboxes) { - Remove-CIPPMailboxPermissions -PermissionsLevel @("FullAccess", "SendAs", "SendOnBehalf") -userid $Mailbox.UserPrincipalName -AccessUser $AccessUser -TenantFilter $TenantFilter -APIName $APINAME -ExecutingUser $ExecutingUser - } + $Mailboxes | ForEach-Object -Parallel { + Remove-CIPPMailboxPermissions -PermissionsLevel @("FullAccess", "SendAs", "SendOnBehalf") -userid $_.UserPrincipalName -AccessUser $using:AccessUser -TenantFilter $using:TenantFilter -APIName $using:APINAME -ExecutingUser $using:ExecutingUser + } -ThrottleLimit 10 } else { $Results = $PermissionsLevel | ForEach-Object { From db3940d4175046f97cbd5549c4e260bb52e07f09 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Wed, 15 Nov 2023 17:36:06 +0100 Subject: [PATCH 34/55] created new task scheduler to use in more locations --- AddScheduledItem/run.ps1 | 50 +---------------- .../CIPPCore/Public/Add-CIPPScheduledTask.ps1 | 55 +++++++++++++++++++ 2 files changed, 57 insertions(+), 48 deletions(-) create mode 100644 Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1 diff --git a/AddScheduledItem/run.ps1 b/AddScheduledItem/run.ps1 index 71d8c5bde9c2..6f64a255a725 100644 --- a/AddScheduledItem/run.ps1 +++ b/AddScheduledItem/run.ps1 @@ -2,54 +2,8 @@ using namespace System.Net param($Request, $TriggerMetadata) $APIName = $TriggerMetadata.FunctionName Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' -$task = $Request.Body -$Table = Get-CIPPTable -TableName 'ScheduledTasks' - -$propertiesToCheck = @('Webhook', 'Email', 'PSA') -$PostExecution = ($propertiesToCheck | Where-Object { $task.PostExecution.$_ -eq $true }) -join ',' - -$Parameters = [System.Collections.Hashtable]@{} -foreach ($Key in $task.Parameters.Keys) { - $Param = $task.Parameters.$Key - if ($Param.Key) { - $ht = @{} - foreach ($p in $Param) { - Write-Host $p.Key - $ht[$p.Key] = $p.Value - } - $Parameters[$Key] = [PSCustomObject]$ht - } else { - $Parameters[$Key] = $Param - } -} - -$Parameters = ($Parameters | ConvertTo-Json -Compress) - -$AdditionalProperties = [System.Collections.Hashtable]@{} -foreach ($Prop in $task.AdditionalProperties) { - $AdditionalProperties[$Prop.Key] = $Prop.Value -} -$AdditionalProperties = ([PSCustomObject]$AdditionalProperties | ConvertTo-Json -Compress) - - -if ($Parameters -eq 'null') { $Parameters = '' } -$entity = @{ - PartitionKey = [string]'ScheduledTask' - TaskState = [string]'Planned' - RowKey = [string]"$(New-Guid)" - Tenant = [string]$task.TenantFilter - Name = [string]$task.Name - Command = [string]$task.Command.value - Parameters = [string]$Parameters - ScheduledTime = [string]$task.ScheduledTime - Recurrence = [string]$task.Recurrence.value - PostExecution = [string]$PostExecution - AdditionalProperties = [string]$AdditionalProperties - Results = 'Planned' -} -Write-Host "entity: $($entity | ConvertTo-Json)" -Add-CIPPAzDataTableEntity @Table -Entity $entity +$Result = Add-CIPPScheduledTask -Task $Request.body -hidden $false Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK - Body = @{ Results = 'Task added successfully.' } + Body = @{ Results = $Result } }) \ No newline at end of file diff --git a/Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1 b/Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1 new file mode 100644 index 000000000000..511b04f1b1b3 --- /dev/null +++ b/Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1 @@ -0,0 +1,55 @@ +function Add-CIPPScheduledTask { + [CmdletBinding()] + param( + [pscustomobject]$Task, + [bool]$Hidden + ) + + $Table = Get-CIPPTable -TableName 'ScheduledTasks' + $propertiesToCheck = @('Webhook', 'Email', 'PSA') + $PostExecution = ($propertiesToCheck | Where-Object { $task.PostExecution.$_ -eq $true }) -join ',' + $Parameters = [System.Collections.Hashtable]@{} + foreach ($Key in $task.Parameters.Keys) { + $Param = $task.Parameters.$Key + if ($Param.Key) { + $ht = @{} + foreach ($p in $Param) { + Write-Host $p.Key + $ht[$p.Key] = $p.Value + } + $Parameters[$Key] = [PSCustomObject]$ht + } + else { + $Parameters[$Key] = $Param + } + } + $Parameters = ($Parameters | ConvertTo-Json -Compress) + $AdditionalProperties = [System.Collections.Hashtable]@{} + foreach ($Prop in $task.AdditionalProperties) { + $AdditionalProperties[$Prop.Key] = $Prop.Value + } + $AdditionalProperties = ([PSCustomObject]$AdditionalProperties | ConvertTo-Json -Compress) + if ($Parameters -eq 'null') { $Parameters = '' } + $entity = @{ + PartitionKey = [string]'ScheduledTask' + TaskState = [string]'Planned' + RowKey = [string]"$(New-Guid)" + Tenant = [string]$task.TenantFilter + Name = [string]$task.Name + Command = [string]$task.Command.value + Parameters = [string]$Parameters + ScheduledTime = [string]$task.ScheduledTime + Recurrence = [string]$task.Recurrence.value + PostExecution = [string]$PostExecution + AdditionalProperties = [string]$AdditionalProperties + Hidden = [bool]$Hidden + Results = 'Planned' + } + try { + Add-CIPPAzDataTableEntity @Table -Entity $entity + } + catch { + return "Could not add task: $($_.Exception.Message)" + } + return "Successfully added task" +} \ No newline at end of file From 8d620520e10399bcdd14eda541cb0688f2bfa29d Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Wed, 15 Nov 2023 20:26:56 +0100 Subject: [PATCH 35/55] updated offboard user --- ExecOffboardUser/run.ps1 | 75 ++-------------- .../Public/Invoke-CIPPOffboardingJob.ps1 | 87 +++++++++++++++++++ 2 files changed, 93 insertions(+), 69 deletions(-) create mode 100644 Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 diff --git a/ExecOffboardUser/run.ps1 b/ExecOffboardUser/run.ps1 index 5e701c996166..1925d0e827dc 100644 --- a/ExecOffboardUser/run.ps1 +++ b/ExecOffboardUser/run.ps1 @@ -6,75 +6,12 @@ try { Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" $Username = $request.body.user $Tenantfilter = $request.body.tenantfilter - if ($username -eq $null) { exit } - $userid = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($username)" -tenantid $Tenantfilter).id - Set-Location (Get-Item $PSScriptRoot).Parent.FullName - $ConvertTable = Import-Csv Conversiontable.csv | Sort-Object -Property 'guid' -Unique - - Write-Host ($request.body | ConvertTo-Json) - $results = switch ($request.body) { - { $_."ConvertToShared" -eq 'true' } { - Set-CIPPMailboxType -ExecutingUser $request.headers.'x-ms-client-principal' -tenantFilter $tenantFilter -userid $username -username $username -MailboxType "Shared" -APIName "ExecOffboardUser" - } - { $_.RevokeSessions -eq 'true' } { - Revoke-CIPPSessions -tenantFilter $tenantFilter -username $username -userid $userid -ExecutingUser $request.headers.'x-ms-client-principal' -APIName "ExecOffboardUser" - } - { $_.ResetPass -eq 'true' } { - Set-CIPPResetPassword -tenantFilter $tenantFilter -userid $username -ExecutingUser $request.headers.'x-ms-client-principal' -APIName "ExecOffboardUser" - } - { $_.RemoveGroups -eq 'true' } { - Remove-CIPPGroups -userid $userid -tenantFilter $Tenantfilter -ExecutingUser $request.headers.'x-ms-client-principal' -APIName "ExecOffboardUser" -Username "$Username" - } - - { $_."HideFromGAL" -eq 'true' } { - Set-CIPPHideFromGAL -tenantFilter $tenantFilter -userid $username -HideFromGAL $true -ExecutingUser $request.headers.'x-ms-client-principal' -APIName "ExecOffboardUser" - } - { $_."DisableSignIn" -eq 'true' } { - Set-CIPPSignInState -TenantFilter $tenantFilter -userid $username -AccountEnabled $false -ExecutingUser $request.headers.'x-ms-client-principal' -APIName "ExecOffboardUser" - } - - { $_."OnedriveAccess" -ne "" } { - $request.body.OnedriveAccess | ForEach-Object { Set-CIPPOnedriveAccess -tenantFilter $tenantFilter -userid $username -OnedriveAccessUser $_.value -ExecutingUser $request.headers.'x-ms-client-principal' -APIName "ExecOffboardUser" } - } - - { $_."AccessNoAutomap" -ne "" } { - $request.body.AccessNoAutomap | ForEach-Object { Set-CIPPMailboxAccess -tenantFilter $tenantFilter -userid $username -AccessUser $_.value -Automap $false -AccessRights @("FullAccess") -ExecutingUser $request.headers.'x-ms-client-principal' -APIName "ExecOffboardUser" } - } - { $_."AccessAutomap" -ne "" } { - $request.body.AccessAutomap | ForEach-Object { Set-CIPPMailboxAccess -tenantFilter $tenantFilter -userid $username -AccessUser $_.value -Automap $true -AccessRights @("FullAccess") -ExecutingUser $request.headers.'x-ms-client-principal' -APIName "ExecOffboardUser" } - } - - { $_."OOO" -ne "" } { - Set-CIPPOutOfOffice -tenantFilter $tenantFilter -userid $username -InternalMessage $request.body.OOO -ExternalMessage $request.body.OOO -ExecutingUser $request.headers.'x-ms-client-principal' -APIName "ExecOffboardUser" - } - { $_."forward" -ne "" } { - Set-CIPPForwarding -userid $userid -username $username -tenantFilter $Tenantfilter -Forward $request.body.forward -KeepCopy [bool]$request.body.keepCopy -ExecutingUser $request.headers.'x-ms-client-principal' -APIName "ExecOffboardUser" - } - { $_."RemoveLicenses" -eq 'true' } { - Remove-CIPPLicense -userid $userid -username $Username -tenantFilter $Tenantfilter -ExecutingUser $request.headers.'x-ms-client-principal' -APIName "ExecOffboardUser" - } - - { $_."Deleteuser" -eq 'true' } { - Remove-CIPPUser -userid $userid -username $Username -tenantFilter $Tenantfilter -ExecutingUser $request.headers.'x-ms-client-principal' -APIName "ExecOffboardUser" - } - - { $_."RemoveRules" -eq 'true' } { - Remove-CIPPRules -userid $userid -username $Username -tenantFilter $Tenantfilter -ExecutingUser $request.headers.'x-ms-client-principal' -APIName "ExecOffboardUser" - } - - { $_."RemoveMobile" -eq 'true' } { - Remove-CIPPMobileDevice -userid $userid -username $Username -tenantFilter $Tenantfilter -ExecutingUser $request.headers.'x-ms-client-principal' -APIName "ExecOffboardUser" - } - { $_."RemovePermissions" } { - $object = [PSCustomObject]@{ - TenantFilter = $tenantFilter - User = $username - executingUser = $request.headers.'x-ms-client-principal' - } - Push-OutputBinding -Name Msg -Value $object - "Removal of permissions queued. This task will run in the background and send it's results to the logbook." - } - + $Results = if ($Request.body.Scheduled) { + #Add scheduled task with all params. + "Offboarding scheduled for $($Request.body.Scheduled.Date)" + } + else { + Invoke-CIPPOffboardingJob -Username $Username -TenantFilter $Tenantfilter -Options $Request.body -APIName $APIName -ExecutingUser $request.headers.'x-ms-client-principal' } $StatusCode = [HttpStatusCode]::OK $body = [pscustomobject]@{"Results" = @($results) } diff --git a/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 b/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 new file mode 100644 index 000000000000..af1e97c83134 --- /dev/null +++ b/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 @@ -0,0 +1,87 @@ + +function Invoke-CIPPOffboardingJob { + [CmdletBinding()] + param ( + [string]$TenantFilter, + [string]$Username, + [switch]$RunScheduled, + $Options, + $APIName = 'Offboard user', + $ExecutingUser + ) + if ($Options -is [string]) { + $Options = $Options | ConvertFrom-Json + } + $userid = (New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($username)" -tenantid $Tenantfilter).id + $Return = switch ($Options) { + { $_."ConvertToShared" -eq 'true' } { + Set-CIPPMailboxType -ExecutingUser $ExecutingUser -tenantFilter $tenantFilter -userid $username -username $username -MailboxType "Shared" -APIName $APIName + } + { $_.RevokeSessions -eq 'true' } { + Revoke-CIPPSessions -tenantFilter $tenantFilter -username $username -userid $userid -ExecutingUser $ExecutingUser -APIName $APIName + } + { $_.ResetPass -eq 'true' } { + Set-CIPPResetPassword -tenantFilter $tenantFilter -userid $username -ExecutingUser $ExecutingUser -APIName $APIName + } + { $_.RemoveGroups -eq 'true' } { + Remove-CIPPGroups -userid $userid -tenantFilter $Tenantfilter -ExecutingUser $ExecutingUser -APIName $APIName -Username "$Username" + } + + { $_."HideFromGAL" -eq 'true' } { + Set-CIPPHideFromGAL -tenantFilter $tenantFilter -userid $username -HideFromGAL $true -ExecutingUser $ExecutingUser -APIName $APIName + } + { $_."DisableSignIn" -eq 'true' } { + Set-CIPPSignInState -TenantFilter $tenantFilter -userid $username -AccountEnabled $false -ExecutingUser $ExecutingUser -APIName $APIName + } + + { $_."OnedriveAccess" -ne "" } { + $Options.OnedriveAccess | ForEach-Object { Set-CIPPOnedriveAccess -tenantFilter $tenantFilter -userid $username -OnedriveAccessUser $_.value -ExecutingUser $ExecutingUser -APIName $APIName } + } + + { $_."AccessNoAutomap" -ne "" } { + $Options.AccessNoAutomap | ForEach-Object { Set-CIPPMailboxAccess -tenantFilter $tenantFilter -userid $username -AccessUser $_.value -Automap $false -AccessRights @("FullAccess") -ExecutingUser $ExecutingUser -APIName $APIName } + } + { $_."AccessAutomap" -ne "" } { + $Options.AccessAutomap | ForEach-Object { Set-CIPPMailboxAccess -tenantFilter $tenantFilter -userid $username -AccessUser $_.value -Automap $true -AccessRights @("FullAccess") -ExecutingUser $ExecutingUser -APIName $APIName } + } + + { $_."OOO" -ne "" } { + Set-CIPPOutOfOffice -tenantFilter $tenantFilter -userid $username -InternalMessage $Options.OOO -ExternalMessage $Options.OOO -ExecutingUser $ExecutingUser -APIName $APIName + } + { $_."forward" -ne "" } { + Set-CIPPForwarding -userid $userid -username $username -tenantFilter $Tenantfilter -Forward $Options.forward -KeepCopy [bool]$Options.keepCopy -ExecutingUser $ExecutingUser -APIName $APIName + } + { $_."RemoveLicenses" -eq 'true' } { + Remove-CIPPLicense -userid $userid -username $Username -tenantFilter $Tenantfilter -ExecutingUser $ExecutingUser -APIName $APIName + } + + { $_."Deleteuser" -eq 'true' } { + Remove-CIPPUser -userid $userid -username $Username -tenantFilter $Tenantfilter -ExecutingUser $ExecutingUser -APIName $APIName + } + + { $_."RemoveRules" -eq 'true' } { + Remove-CIPPRules -userid $userid -username $Username -tenantFilter $Tenantfilter -ExecutingUser $ExecutingUser -APIName $APIName + } + + { $_."RemoveMobile" -eq 'true' } { + Remove-CIPPMobileDevice -userid $userid -username $Username -tenantFilter $Tenantfilter -ExecutingUser $ExecutingUser -APIName $APIName + } + { $_."RemovePermissions" } { + if ($RunScheduled) { + Remove-CIPPMailboxPermissions #Finish this + } + else { + $object = [PSCustomObject]@{ + TenantFilter = $tenantFilter + User = $username + executingUser = $ExecutingUser + } + Push-OutputBinding -Name Msg -Value $object + "Removal of permissions queued. This task will run in the background and send it's results to the logbook." + } + } + + } + return $Return + +} \ No newline at end of file From 4875cf7af547c27ca2264877a0d0a42a6077bc7d Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Wed, 15 Nov 2023 23:13:49 +0100 Subject: [PATCH 36/55] add scheduler in offboarding --- ExecOffboardUser/run.ps1 | 25 ++++++++++++++++--- ExecScheduledCommand/run.ps1 | 16 +++++++++--- .../CIPPCore/Public/Add-CIPPScheduledTask.ps1 | 2 +- .../Public/Invoke-CIPPOffboardingJob.ps1 | 2 +- Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 | 2 +- .../CIPPCore/Public/Set-CIPPOutOfoffice.ps1 | 2 +- Scheduler_UserTasks/function.json | 2 +- 7 files changed, 39 insertions(+), 12 deletions(-) diff --git a/ExecOffboardUser/run.ps1 b/ExecOffboardUser/run.ps1 index 1925d0e827dc..53afa5424071 100644 --- a/ExecOffboardUser/run.ps1 +++ b/ExecOffboardUser/run.ps1 @@ -6,9 +6,27 @@ try { Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" $Username = $request.body.user $Tenantfilter = $request.body.tenantfilter - $Results = if ($Request.body.Scheduled) { - #Add scheduled task with all params. - "Offboarding scheduled for $($Request.body.Scheduled.Date)" + $Results = if ($Request.body.Scheduled.enabled) { + $taskObject = [PSCustomObject]@{ + TenantFilter = $Tenantfilter + Name = "Offboarding: $Username" + Command = @{ + value = "Invoke-CIPPOffboardingJob" + } + Parameters = @{ + Username = $Username + APIName = "Scheduled Offboarding" + options = $request.body + } + ScheduledTime = $Request.body.scheduled.date + PostExecution = @{ + Webhook = [bool]$Request.Body.PostExecution.webhook + Email = [bool]$Request.Body.PostExecution.email + PSA = [bool]$Request.Body.PostExecution.psa + } + } + + Add-CIPPScheduledTask -Task $taskObject -hidden $false } else { Invoke-CIPPOffboardingJob -Username $Username -TenantFilter $Tenantfilter -Options $Request.body -APIName $APIName -ExecutingUser $request.headers.'x-ms-client-principal' @@ -20,6 +38,7 @@ catch { $StatusCode = [HttpStatusCode]::Forbidden $body = $_.Exception.message } +$Request.Body.PostExecution Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = $StatusCode Body = $Body diff --git a/ExecScheduledCommand/run.ps1 b/ExecScheduledCommand/run.ps1 index fed27bba1579..615b6b8471cf 100644 --- a/ExecScheduledCommand/run.ps1 +++ b/ExecScheduledCommand/run.ps1 @@ -10,22 +10,29 @@ Write-Host 'started task' try { try { $results = & $QueueItem.command @commandParameters - } catch { + } + catch { $results = "Task Failed: $($_.Exception.Message)" } Write-Host 'ran the command' - if ($results.GetType() -eq [String]) { + if ($results -is [String]) { $results = @{ Results = $results } } + if ($results -is [array]) { + $results = $results | Where-Object { $_ -is [string] } + $results = $results | ForEach-Object { @{ Results = $_ } } + } + $results = $results | Select-Object * -ExcludeProperty RowKey, PartitionKey $StoredResults = $results | ConvertTo-Json -Compress -Depth 20 | Out-String if ($StoredResults.Length -gt 64000 -or $task.Tenant -eq 'AllTenants') { $StoredResults = @{ Results = 'The results for this query are too long to store in this table, or the query was meant for All Tenants. Please use the options to send the results to another target to be able to view the results. ' } | ConvertTo-Json -Compress } -} catch { +} +catch { $errorMessage = $_.Exception.Message if ($task.Recurrence -gt 0) { $State = 'Failed - Planned' } else { $State = 'Failed' } Update-AzDataTableEntity @Table -Entity @{ @@ -64,7 +71,8 @@ if ($task.Recurrence -le '0' -or $task.Recurrence -eq $null) { Results = "$StoredResults" TaskState = 'Completed' } -} else { +} +else { $nextRun = (Get-Date).AddDays($task.Recurrence) $nextRunUnixTime = [int64]($nextRun - (Get-Date '1/1/1970')).TotalSeconds Update-AzDataTableEntity @Table -Entity @{ diff --git a/Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1 b/Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1 index 511b04f1b1b3..04c5d358d599 100644 --- a/Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1 +++ b/Modules/CIPPCore/Public/Add-CIPPScheduledTask.ps1 @@ -23,7 +23,7 @@ function Add-CIPPScheduledTask { $Parameters[$Key] = $Param } } - $Parameters = ($Parameters | ConvertTo-Json -Compress) + $Parameters = ($Parameters | ConvertTo-Json -Depth 10 -Compress) $AdditionalProperties = [System.Collections.Hashtable]@{} foreach ($Prop in $task.AdditionalProperties) { $AdditionalProperties[$Prop.Key] = $Prop.Value diff --git a/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 b/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 index af1e97c83134..6fb164fe356c 100644 --- a/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 +++ b/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 @@ -46,7 +46,7 @@ function Invoke-CIPPOffboardingJob { } { $_."OOO" -ne "" } { - Set-CIPPOutOfOffice -tenantFilter $tenantFilter -userid $username -InternalMessage $Options.OOO -ExternalMessage $Options.OOO -ExecutingUser $ExecutingUser -APIName $APIName + Set-CIPPOutOfOffice -tenantFilter $tenantFilter -userid $username -InternalMessage $Options.OOO -ExternalMessage $Options.OOO -ExecutingUser $ExecutingUser -APIName $APIName -state "Enabled" } { $_."forward" -ne "" } { Set-CIPPForwarding -userid $userid -username $username -tenantFilter $Tenantfilter -Forward $Options.forward -KeepCopy [bool]$Options.keepCopy -ExecutingUser $ExecutingUser -APIName $APIName diff --git a/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 b/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 index ca673419332f..d94d71b2b611 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPGroups.ps1 @@ -42,5 +42,5 @@ function Remove-CIPPGroups { "Could not remove $($using:Username) from group $($Groupname): $($_.Exception.Message). This is likely because its a Dynamic Group or synched with active directory" } } - return ($Returnval | Out-String) + return $Returnval } diff --git a/Modules/CIPPCore/Public/Set-CIPPOutOfoffice.ps1 b/Modules/CIPPCore/Public/Set-CIPPOutOfoffice.ps1 index 0f7efc3dcc47..9d0eb4f40120 100644 --- a/Modules/CIPPCore/Public/Set-CIPPOutOfoffice.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPOutOfoffice.ps1 @@ -16,7 +16,7 @@ function Set-CIPPOutOfOffice { if ($State -ne "Scheduled") { $OutOfOffice = New-ExoRequest -tenantid $TenantFilter -cmdlet "Set-MailboxAutoReplyConfiguration" -cmdParams @{Identity = $userid; AutoReplyState = $State; InternalMessage = $InternalMessage; ExternalMessage = $ExternalMessage } -Anchor $userid Write-LogMessage -user $ExecutingUser -API $APIName -message "Set Out-of-office for $($userid) to $state" -Sev "Info" -tenant $TenantFilter - return "Set Out-of-office for $($userid) to $state" + return "Set Out-of-office for $($userid) to $state. Message is $InternalMessage" } else { $OutOfOffice = New-ExoRequest -tenantid $TenantFilter -cmdlet "Set-MailboxAutoReplyConfiguration" -cmdParams @{Identity = $userid; AutoReplyState = $State; InternalMessage = $InternalMessage; ExternalMessage = $ExternalMessage; StartTime = $StartTime; EndTime = $EndTime } -Anchor $userid diff --git a/Scheduler_UserTasks/function.json b/Scheduler_UserTasks/function.json index de2a7380d759..7aee7cc16aa5 100644 --- a/Scheduler_UserTasks/function.json +++ b/Scheduler_UserTasks/function.json @@ -2,7 +2,7 @@ "bindings": [ { "name": "Timer", - "schedule": "0 */15 * * * *", + "schedule": "0 */1 * * * *", "direction": "in", "type": "timerTrigger" }, From 57d5618c8250020c88c9a42dc2280465c9f879e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Thu, 16 Nov 2023 01:29:54 +0100 Subject: [PATCH 37/55] Add configurable mailbox plan tenant standard --- Standards_MailboxPlanTenant/function.json | 9 ++++ Standards_MailboxPlanTenant/run.ps1 | 54 +++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 Standards_MailboxPlanTenant/function.json create mode 100644 Standards_MailboxPlanTenant/run.ps1 diff --git a/Standards_MailboxPlanTenant/function.json b/Standards_MailboxPlanTenant/function.json new file mode 100644 index 000000000000..2d4ea9094b24 --- /dev/null +++ b/Standards_MailboxPlanTenant/function.json @@ -0,0 +1,9 @@ +{ + "bindings": [ + { + "name": "tenant", + "direction": "in", + "type": "activityTrigger" + } + ] +} \ No newline at end of file diff --git a/Standards_MailboxPlanTenant/run.ps1 b/Standards_MailboxPlanTenant/run.ps1 new file mode 100644 index 000000000000..421586cb3fa7 --- /dev/null +++ b/Standards_MailboxPlanTenant/run.ps1 @@ -0,0 +1,54 @@ +param($tenant) +# Get the tenant standards settings +$ConfigTable = Get-CippTable -tablename 'standards' +$Limits = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).standards.MailboxPlanTenant.SendReceiveLimit -split ',' +if (!$Limits) { + $Limits = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).standards.MailboxPlanTenant.SendReceiveLimit -split ',' +} + +# Parse the send limits and convert to bytes +if ($Limits[0] -like "*MB*") { + $MaxSendSize = [int]($Limits[0] -Replace "[a-zA-Z]", "") * 1MB +} +elseif ($Limits[0] -like "*KB*") { + $MaxSendSize = [int]($Limits[0] -Replace "[a-zA-Z]", "") * 1KB +} # Default to 35MB if invalid input +else { + $MaxSendSize = 35MB +} +# Test if the send limit is larger allowed and correct if needed +if ($MaxSendSize -gt 150MB) { + $MaxSendSize = 150MB +} + +# Parse the receive limits and convert to bytes +if ($Limits[1] -like "*MB*") { + $MaxReceiveSize = [int]($Limits[1] -Replace "[a-zA-Z]", "") * 1MB +} +elseif ($Limits[1] -like "*KB*") { + $MaxReceiveSize = [int]($Limits[1] -Replace "[a-zA-Z]", "") * 1KB +} # Default to 36MB if invalid input +else { + $MaxReceiveSize = 36MB +} +# Test if the receive limit is larger allowed and correct if needed +if ($MaxReceiveSize -gt 150MB) { + $MaxReceiveSize = 150MB +} + +try { + # Get all mailbox plans + $AllMailBoxPlans = New-ExoRequest -tenantid $Tenant -cmdlet "Get-MailboxPlan" | Select-Object DisplayName, MaxSendSize, MaxReceiveSize, GUID + + # Loop through all mailbox plans and set the send and receive limits for each if needed + foreach ($MailboxPlan in $AllMailBoxPlans) { + if ($MailboxPlan.MaxSendSize -ne $MaxSendSize -and $MailboxPlan.MaxReceiveSize -ne $MaxReceiveSize) { + New-ExoRequest -tenantid $Tenant -cmdlet "Set-MailboxPlan" -cmdParams @{Identity = $MailboxPlan.GUID; MaxSendSize = $MaxSendSize; MaxReceiveSize = $MaxReceiveSize } -useSystemMailbox $true + } + } + # Write to log on success + Write-LogMessage -API "Standards" -tenant $tenant -message "Successfully set the tenant send and receive limits " -sev Info +} +catch { + Write-LogMessage -API "Standards" -tenant $tenant -message "Failed to set the tenant send and receive limits. Error: $($_.exception.message)" -sev Error +} \ No newline at end of file From cc3419e9f9676655b1995b32691fae5611fe7a21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Bentsen=20Kj=C3=A6rg=C3=A5rd=20=28KBK=29?= Date: Thu, 16 Nov 2023 08:40:42 +0100 Subject: [PATCH 38/55] Fix SWA roles URL in ExecBackendURLS --- ExecBackendURLs/run.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ExecBackendURLs/run.ps1 b/ExecBackendURLs/run.ps1 index 0c557c1625ea..3789d17af8f9 100644 --- a/ExecBackendURLs/run.ps1 +++ b/ExecBackendURLs/run.ps1 @@ -18,7 +18,7 @@ $results = [PSCustomObject]@{ FunctionConfig = "https://portal.azure.com/#@Go/resource/subscriptions/$Subscription/resourceGroups/$ENV:Website_Resource_Group/providers/Microsoft.Web/sites/$($ENV:WEBSITE_SITE_NAME)/configuration" FunctionDeployment = "https://portal.azure.com/#@Go/resource/subscriptions/$Subscription/resourceGroups/$ENV:Website_Resource_Group/providers/Microsoft.Web/sites/$($ENV:WEBSITE_SITE_NAME)/vstscd" SWADomains = "https://portal.azure.com/#@Go/resource/subscriptions/$Subscription/resourceGroups/$ENV:Website_Resource_Group/providers/Microsoft.Web/staticSites/$SWAName/customDomains" - SWARoles = "https://portal.azure.com/#@Go/resource/subscriptions/$Subscription/resourceGroups/$ENV:Website_Resource_Group/providers/Microsoft.Web/staticSites/$SWAName/Roles" + SWARoles = "https://portal.azure.com/#@Go/resource/subscriptions/$Subscription/resourceGroups/$ENV:Website_Resource_Group/providers/Microsoft.Web/staticSites/$SWAName/roleManagement" Subscription = $Subscription RGName = $ENV:Website_Resource_Group FunctionName = $ENV:WEBSITE_SITE_NAME From ef90c186633dbc48951d94982a86344dd1548484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Bentsen=20Kj=C3=A6rg=C3=A5rd=20=28KBK=29?= Date: Thu, 16 Nov 2023 09:28:16 +0100 Subject: [PATCH 39/55] Standard namechange --- .../function.json | 0 .../run.ps1 | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename {Standards_MailboxPlanTenant => Standards_SendReceiveLimitTenant}/function.json (100%) rename {Standards_MailboxPlanTenant => Standards_SendReceiveLimitTenant}/run.ps1 (93%) diff --git a/Standards_MailboxPlanTenant/function.json b/Standards_SendReceiveLimitTenant/function.json similarity index 100% rename from Standards_MailboxPlanTenant/function.json rename to Standards_SendReceiveLimitTenant/function.json diff --git a/Standards_MailboxPlanTenant/run.ps1 b/Standards_SendReceiveLimitTenant/run.ps1 similarity index 93% rename from Standards_MailboxPlanTenant/run.ps1 rename to Standards_SendReceiveLimitTenant/run.ps1 index 421586cb3fa7..1b86b0756ddc 100644 --- a/Standards_MailboxPlanTenant/run.ps1 +++ b/Standards_SendReceiveLimitTenant/run.ps1 @@ -1,9 +1,9 @@ param($tenant) # Get the tenant standards settings $ConfigTable = Get-CippTable -tablename 'standards' -$Limits = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).standards.MailboxPlanTenant.SendReceiveLimit -split ',' +$Limits = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq '$tenant'").JSON | ConvertFrom-Json).standards.SendReceiveLimitTenant.SendReceiveLimit -split ',' if (!$Limits) { - $Limits = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).standards.MailboxPlanTenant.SendReceiveLimit -split ',' + $Limits = ((Get-CIPPAzDataTableEntity @ConfigTable -Filter "PartitionKey eq 'standards' and RowKey eq 'AllTenants'").JSON | ConvertFrom-Json).standards.SendReceiveLimitTenant.SendReceiveLimit -split ',' } # Parse the send limits and convert to bytes From 179ceb04eb34e32e668b563a7de7f2e620ad1e62 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Thu, 16 Nov 2023 10:33:18 +0100 Subject: [PATCH 40/55] do not show hidden tasks by default --- ListScheduledItems/run.ps1 | 2 +- Scheduler_UserTasks/function.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ListScheduledItems/run.ps1 b/ListScheduledItems/run.ps1 index ba8a12a139cc..748dbcfeafd3 100644 --- a/ListScheduledItems/run.ps1 +++ b/ListScheduledItems/run.ps1 @@ -6,7 +6,7 @@ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -m # Write to the Azure Functions log stream. Write-Host 'PowerShell HTTP trigger function processed a request.' $Table = Get-CIPPTable -TableName 'ScheduledTasks' -$ScheduledTasks = Get-CIPPAzDataTableEntity @Table -Filter "PartitionKey eq 'ScheduledTask'" +$ScheduledTasks = Get-CIPPAzDataTableEntity @Table -Filter "PartitionKey eq 'ScheduledTask' and Hidden ne 'True'" # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ diff --git a/Scheduler_UserTasks/function.json b/Scheduler_UserTasks/function.json index 7aee7cc16aa5..de2a7380d759 100644 --- a/Scheduler_UserTasks/function.json +++ b/Scheduler_UserTasks/function.json @@ -2,7 +2,7 @@ "bindings": [ { "name": "Timer", - "schedule": "0 */1 * * * *", + "schedule": "0 */15 * * * *", "direction": "in", "type": "timerTrigger" }, From 4b4df20fc56f94660f8285a8a10be2f8b1c74d04 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Thu, 16 Nov 2023 13:21:58 +0100 Subject: [PATCH 41/55] Improved bec checks --- Durable_BECRun/run.ps1 | 66 +++++++++++++++++----------------------- ExecBECCheck/run.ps1 | 3 +- ExecBECRemediate/run.ps1 | 34 ++++++++++++--------- 3 files changed, 50 insertions(+), 53 deletions(-) diff --git a/Durable_BECRun/run.ps1 b/Durable_BECRun/run.ps1 index 0476b1e9db00..49d358ff3fca 100644 --- a/Durable_BECRun/run.ps1 +++ b/Durable_BECRun/run.ps1 @@ -3,24 +3,20 @@ param($Context) $context = $Context | ConvertTo-Json | ConvertFrom-Json $APIName = $TriggerMetadata.FunctionName Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" -Write-Host "PowerShell HTTP trigger function processed a request." -Write-Host ($Context | ConvertTo-Json) $TenantFilter = $Context.input.tenantfilter $SuspectUser = $Context.input.userid -$GUID = $context.input.GUID - +$UserName = $Context.input.username +Write-Host "Working on $UserName" try { $startDate = (Get-Date).AddDays(-7) $endDate = (Get-Date) $auditLog = (New-ExoRequest -tenantid $Tenantfilter -cmdlet "Get-AdminAuditLogConfig").UnifiedAuditLogIngestionEnabled $7dayslog = if ($auditLog -eq $false) { - "AuditLog is disabled. Cannot perform full analysis" + $ExtractResult = "AuditLog is disabled. Cannot perform full analysis" } else { $sessionid = Get-Random -Minimum 10000 -Maximum 99999 $operations = @( - 'Add OAuth2PermissionGrant.', - 'Consent to application.', "New-InboxRule", "Set-InboxRule", "UpdateInboxRules", @@ -30,9 +26,6 @@ try { "AddFolderPermissions", "MailboxLogin", "UserLoggedIn" - "Add user.", - "Change user password.", - "Reset user password." ) $startDate = (Get-Date).AddDays(-7) $endDate = (Get-Date) @@ -44,35 +37,23 @@ try { endDate = $endDate } do { - New-ExoRequest -tenantid $Tenantfilter -cmdlet "Search-unifiedAuditLog" -cmdParams $SearchParam -Anchor $SuspectUser + New-ExoRequest -tenantid $Tenantfilter -cmdlet "Search-unifiedAuditLog" -cmdParams $SearchParam -Anchor $Username Write-Host "Retrieved $($logsTenant.count) logs" -ForegroundColor Yellow $logsTenant } while ($LogsTenant.count % 5000 -eq 0 -and $LogsTenant.count -ne 0) + $ExtractResult = "Succesfully extracted logs from auditlog" } - #Get user last logon - TRY { - $startDate = (Get-Date).AddDays(-7) - $endDate = (Get-Date) - $SearchParam = @{ - SessionCommand = "ReturnLargeSet" - Operations = @('UserLoggedIn', 'UserLoginFailed', 'TeamsSessionStarted', 'MailboxLogin') - sessionid = $sessionid - startDate = $startDate - endDate = $endDate - UserIds = @($SuspectUser) - } - $AuditlogsLogon = (New-ExoRequest -Anchor $SuspectUser -tenantid $Tenantfilter -cmdlet "Search-unifiedAuditLog" -cmdParams $SearchParam | Sort-Object -Property CreationDate | Select-Object -Last 1).auditdata | ConvertFrom-Json - $Appname = '[{"Application Name":"ACOM Azure Website","Application IDs":"23523755-3a2b-41ca-9315-f81f3f566a95"},{"Application Name":"AEM-DualAuth","Application IDs":"69893ee3-dd10-4b1c-832d-4870354be3d8"},{"Application Name":"ASM Campaign Servicing","Application IDs":"0cb7b9ec-5336-483b-bc31-b15b5788de71"},{"Application Name":"Azure Advanced Threat Protection","Application IDs":"7b7531ad-5926-4f2d-8a1d-38495ad33e17"},{"Application Name":"Azure Data Lake","Application IDs":"e9f49c6b-5ce5-44c8-925d-015017e9f7ad"},{"Application Name":"Azure Lab Services Portal","Application IDs":"835b2a73-6e10-4aa5-a979-21dfda45231c"},{"Application Name":"Azure Portal","Application IDs":"c44b4083-3bb0-49c1-b47d-974e53cbdf3c"},{"Application Name":"AzureSupportCenter","Application IDs":"37182072-3c9c-4f6a-a4b3-b3f91cacffce"},{"Application Name":"Bing","Application IDs":"9ea1ad79-fdb6-4f9a-8bc3-2b70f96e34c7"},{"Application Name":"CPIM Service","Application IDs":"bb2a2e3a-c5e7-4f0a-88e0-8e01fd3fc1f4"},{"Application Name":"CRM Power BI Integration","Application IDs":"e64aa8bc-8eb4-40e2-898b-cf261a25954f"},{"Application Name":"Dataverse","Application IDs":"00000007-0000-0000-c000-000000000000"},{"Application Name":"Enterprise Roaming and Backup","Application IDs":"60c8bde5-3167-4f92-8fdb-059f6176dc0f"},{"Application Name":"IAM Supportability","Application IDs":"a57aca87-cbc0-4f3c-8b9e-dc095fdc8978"},{"Application Name":"IrisSelectionFrontDoor","Application IDs":"16aeb910-ce68-41d1-9ac3-9e1673ac9575"},{"Application Name":"MCAPI Authorization Prod","Application IDs":"d73f4b35-55c9-48c7-8b10-651f6f2acb2e"},{"Application Name":"Media Analysis and Transformation Service","Application IDs":"944f0bd1-117b-4b1c-af26-804ed95e767e
0cd196ee-71bf-4fd6-a57c-b491ffd4fb1e"},{"Application Name":"Microsoft 365 Support Service","Application IDs":"ee272b19-4411-433f-8f28-5c13cb6fd407"},{"Application Name":"Microsoft App Access Panel","Application IDs":"0000000c-0000-0000-c000-000000000000"},{"Application Name":"Microsoft Approval Management","Application IDs":"65d91a3d-ab74-42e6-8a2f-0add61688c74
38049638-cc2c-4cde-abe4-4479d721ed44"},{"Application Name":"Microsoft Authentication Broker","Application IDs":"29d9ed98-a469-4536-ade2-f981bc1d605e"},{"Application Name":"Microsoft Azure CLI","Application IDs":"04b07795-8ddb-461a-bbee-02f9e1bf7b46"},{"Application Name":"Microsoft Azure PowerShell","Application IDs":"1950a258-227b-4e31-a9cf-717495945fc2"},{"Application Name":"Microsoft Bing Search","Application IDs":"cf36b471-5b44-428c-9ce7-313bf84528de"},{"Application Name":"Microsoft Bing Search for Microsoft Edge","Application IDs":"2d7f3606-b07d-41d1-b9d2-0d0c9296a6e8"},{"Application Name":"Microsoft Bing Default Search Engine","Application IDs":"1786c5ed-9644-47b2-8aa0-7201292175b6"},{"Application Name":"Microsoft Defender for Cloud Apps","Application IDs":"3090ab82-f1c1-4cdf-af2c-5d7a6f3e2cc7"},{"Application Name":"Microsoft Docs","Application IDs":"18fbca16-2224-45f6-85b0-f7bf2b39b3f3"},{"Application Name":"Microsoft Dynamics ERP","Application IDs":"00000015-0000-0000-c000-000000000000"},{"Application Name":"Microsoft Edge Insider Addons Prod","Application IDs":"6253bca8-faf2-4587-8f2f-b056d80998a7"},{"Application Name":"Microsoft Exchange Online Protection","Application IDs":"00000007-0000-0ff1-ce00-000000000000"},{"Application Name":"Microsoft Forms","Application IDs":"c9a559d2-7aab-4f13-a6ed-e7e9c52aec87"},{"Application Name":"Microsoft Graph","Application IDs":"00000003-0000-0000-c000-000000000000"},{"Application Name":"Microsoft Intune Web Company Portal","Application IDs":"74bcdadc-2fdc-4bb3-8459-76d06952a0e9"},{"Application Name":"Microsoft Intune Windows Agent","Application IDs":"fc0f3af4-6835-4174-b806-f7db311fd2f3"},{"Application Name":"Microsoft Learn","Application IDs":"18fbca16-2224-45f6-85b0-f7bf2b39b3f3"},{"Application Name":"Microsoft Office","Application IDs":"d3590ed6-52b3-4102-aeff-aad2292ab01c"},{"Application Name":"Microsoft Office 365 Portal","Application IDs":"00000006-0000-0ff1-ce00-000000000000"},{"Application Name":"Microsoft Office Web Apps Service","Application IDs":"67e3df25-268a-4324-a550-0de1c7f97287"},{"Application Name":"Microsoft Online Syndication Partner Portal","Application IDs":"d176f6e7-38e5-40c9-8a78-3998aab820e7"},{"Application Name":"Microsoft password reset service","Application IDs":"93625bc8-bfe2-437a-97e0-3d0060024faa"},{"Application Name":"Microsoft Power BI","Application IDs":"871c010f-5e61-4fb1-83ac-98610a7e9110"},{"Application Name":"Microsoft Storefronts","Application IDs":"28b567f6-162c-4f54-99a0-6887f387bbcc"},{"Application Name":"Microsoft Stream Portal","Application IDs":"cf53fce8-def6-4aeb-8d30-b158e7b1cf83"},{"Application Name":"Microsoft Substrate Management","Application IDs":"98db8bd6-0cc0-4e67-9de5-f187f1cd1b41"},{"Application Name":"Microsoft Support","Application IDs":"fdf9885b-dd37-42bf-82e5-c3129ef5a302"},{"Application Name":"Microsoft Teams","Application IDs":"1fec8e78-bce4-4aaf-ab1b-5451cc387264"},{"Application Name":"Microsoft Teams Services","Application IDs":"cc15fd57-2c6c-4117-a88c-83b1d56b4bbe"},{"Application Name":"Microsoft Teams Web Client","Application IDs":"5e3ce6c0-2b1f-4285-8d4b-75ee78787346"},{"Application Name":"Microsoft Whiteboard Services","Application IDs":"95de633a-083e-42f5-b444-a4295d8e9314"},{"Application Name":"O365 Suite UX","Application IDs":"4345a7b9-9a63-4910-a426-35363201d503"},{"Application Name":"Office 365 Exchange Online","Application IDs":"00000002-0000-0ff1-ce00-000000000000"},{"Application Name":"Office 365 Management","Application IDs":"00b41c95-dab0-4487-9791-b9d2c32c80f2"},{"Application Name":"Office 365 Search Service","Application IDs":"66a88757-258c-4c72-893c-3e8bed4d6899"},{"Application Name":"Office 365 SharePoint Online","Application IDs":"00000003-0000-0ff1-ce00-000000000000"},{"Application Name":"Office Delve","Application IDs":"94c63fef-13a3-47bc-8074-75af8c65887a"},{"Application Name":"Office Online Add-in SSO","Application IDs":"93d53678-613d-4013-afc1-62e9e444a0a5"},{"Application Name":"Office Online Client AAD- Augmentation Loop","Application IDs":"2abdc806-e091-4495-9b10-b04d93c3f040"},{"Application Name":"Office Online Client AAD- Loki","Application IDs":"b23dd4db-9142-4734-867f-3577f640ad0c"},{"Application Name":"Office Online Client AAD- Maker","Application IDs":"17d5e35f-655b-4fb0-8ae6-86356e9a49f5"},{"Application Name":"Office Online Client MSA- Loki","Application IDs":"b6e69c34-5f1f-4c34-8cdf-7fea120b8670"},{"Application Name":"Office Online Core SSO","Application IDs":"243c63a3-247d-41c5-9d83-7788c43f1c43"},{"Application Name":"Office Online Search","Application IDs":"a9b49b65-0a12-430b-9540-c80b3332c127"},{"Application Name":"Office.com","Application IDs":"4b233688-031c-404b-9a80-a4f3f2351f90"},{"Application Name":"Office365 Shell WCSS-Client","Application IDs":"89bee1f7-5e6e-4d8a-9f3d-ecd601259da7"},{"Application Name":"OfficeClientService","Application IDs":"0f698dd4-f011-4d23-a33e-b36416dcb1e6"},{"Application Name":"OfficeHome","Application IDs":"4765445b-32c6-49b0-83e6-1d93765276ca"},{"Application Name":"OfficeShredderWacClient","Application IDs":"4d5c2d63-cf83-4365-853c-925fd1a64357"},{"Application Name":"OMSOctopiPROD","Application IDs":"62256cef-54c0-4cb4-bcac-4c67989bdc40"},{"Application Name":"OneDrive SyncEngine","Application IDs":"ab9b8c07-8f02-4f72-87fa-80105867a763"},{"Application Name":"OneNote","Application IDs":"2d4d3d8e-2be3-4bef-9f87-7875a61c29de"},{"Application Name":"Outlook Mobile","Application IDs":"27922004-5251-4030-b22d-91ecd9a37ea4"},{"Application Name":"Partner Customer Delegated Admin Offline Processor","Application IDs":"a3475900-ccec-4a69-98f5-a65cd5dc5306"},{"Application Name":"Password Breach Authenticator","Application IDs":"bdd48c81-3a58-4ea9-849c-ebea7f6b6360"},{"Application Name":"Power BI Service","Application IDs":"00000009-0000-0000-c000-000000000000"},{"Application Name":"SharedWithMe","Application IDs":"ffcb16e8-f789-467c-8ce9-f826a080d987"},{"Application Name":"SharePoint Online Web Client Extensibility","Application IDs":"08e18876-6177-487e-b8b5-cf950c1e598c"},{"Application Name":"Signup","Application IDs":"b4bddae8-ab25-483e-8670-df09b9f1d0ea"},{"Application Name":"Skype for Business Online","Application IDs":"00000004-0000-0ff1-ce00-000000000000"},{"Application Name":"Sway","Application IDs":"905fcf26-4eb7-48a0-9ff0-8dcc7194b5ba"},{"Application Name":"Universal Store Native Client","Application IDs":"268761a2-03f3-40df-8a8b-c3db24145b6b"},{"Application Name":"Vortex [wsfed enabled]","Application IDs":"5572c4c0-d078-44ce-b81c-6cbf8d3ed39e"},{"Application Name":"Windows Azure Active Directory","Application IDs":"00000002-0000-0000-c000-000000000000"},{"Application Name":"Windows Azure Service Management API","Application IDs":"797f4846-ba00-4fd7-ba43-dac1f8f63013"},{"Application Name":"WindowsDefenderATP Portal","Application IDs":"a3b79187-70b2-4139-83f9-6016c58cd27b"},{"Application Name":"Windows Search","Application IDs":"26a7ee05-5602-4d76-a7ba-eae8b7b67941"},{"Application Name":"Windows Spotlight","Application IDs":"1b3c667f-cde3-4090-b60b-3d2abd0117f0"},{"Application Name":"Windows Store for Business","Application IDs":"45a330b1-b1ec-4cc1-9161-9f03992aa49f"},{"Application Name":"Yammer","Application IDs":"00000005-0000-0ff1-ce00-000000000000"},{"Application Name":"Yammer Web","Application IDs":"c1c74fed-04c9-4704-80dc-9f79a2e515cb"},{"Application Name":"Yammer Web Embed","Application IDs":"e1ef36fd-b883-4dbf-97f0-9ece4b576fc6"}]' | ConvertFrom-Json | Where-Object -Property 'Application IDs' -EQ $AuditlogsLogon.applicationId - $LastSignIn = [PSCustomObject]@{ - AppDisplayName = if ($AppName) { $AppName.'Application Name' } else { "$($AuditlogsLogon.Workload) - $($AuditlogsLogon.ApplicationId) " } - CreatedDateTime = $AuditlogsLogon.CreationTime - Id = $AuditlogsLogon.errorNumber - Status = $AuditlogsLogon.ResultStatus - } + Try { + $URI = "https://graph.microsoft.com/beta/auditLogs/signIns?`$filter=(userId eq '$SuspectUser')&`$top=1&`$orderby=createdDateTime desc" + $LastSignIn = New-GraphGetRequest -uri $URI -tenantid $TenantFilter -noPagination $true -verbose | Select-Object @{ Name = 'CreatedDateTime'; Expression = { $(($_.createdDateTime | Out-String) -replace '\r\n') } }, + id, + @{ Name = 'AppDisplayName'; Expression = { $_.resourceDisplayName } }, + @{ Name = 'Status'; Expression = { if (($_.conditionalAccessStatus -eq 'Success' -or 'Not Applied') -and $_.status.errorCode -eq 0) { 'Success' } else { 'Failed' } } }, + @{ Name = 'IPAddress'; Expression = { $_.ipAddress } } } catch { $LastSignIn = [PSCustomObject]@{ - AppDisplayName = "Unknown - could not retrieve information" + AppDisplayName = "Unknown - could not retrieve information. No access to sign-in logs" CreatedDateTime = "Unknown" Id = "0" Status = "Could not retrieve additional details" @@ -112,19 +93,28 @@ try { RuleCondition = ($_.OperationProperties | ForEach-Object { if ($_.Name -eq "RuleCondition") { $_.Value } }) } } - + $PasswordChanges = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users?`select=lastPasswordChangeDateTime,displayname,UserPrincipalName" -Tenantid $tenantfilter | Where-Object { $_.lastPasswordChangeDateTime -gt $startDate } + $NewUsers = New-GraphGetRequest -uri "https://graph.microsoft.com/v1.0/users?`$select=displayname,UserPrincipalName,CreatedDateTime" -Tenantid $tenantfilter | Where-Object { $_.CreatedDateTime -gt $startDate } + $MFADevices = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users/$($SuspectUser)/authentication/methods" -Tenantid $tenantfilter + $NewSPs = New-GraphGetRequest -uri "https://graph.microsoft.com/v1.0/servicePrincipals?`$select=displayName,createdDateTime,id,AppDisplayName&`$filter=createdDateTime ge $($startDate.ToString('yyyy-MM-ddTHH:mm:ssZ'))" -Tenantid $tenantfilter + $Last50Logons = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/auditLogs/signIns?`$top=50&`$orderby=createdDateTime desc" -tenantid $TenantFilter -noPagination $true -verbose | Select-Object @{ Name = 'CreatedDateTime'; Expression = { $(($_.createdDateTime | Out-String) -replace '\r\n') } }, + id, + @{ Name = 'AppDisplayName'; Expression = { $_.resourceDisplayName } }, + @{ Name = 'Status'; Expression = { if (($_.conditionalAccessStatus -eq 'Success' -or 'Not Applied') -and $_.status.errorCode -eq 0) { 'Success' } else { 'Failed' } } }, + @{ Name = 'IPAddress'; Expression = { $_.ipAddress } }, UserPrincipalName $Results = [PSCustomObject]@{ - AddedApps = @(($7dayslog | Where-Object -Property Operations -In 'Add OAuth2PermissionGrant.', 'Consent to application.').AuditData | ConvertFrom-Json) - SuspectUserMailboxLogons = @(($7dayslog | Where-Object -Property Operations -In "MailboxLogin" ).AuditData | ConvertFrom-Json) + AddedApps = $NewSPs + SuspectUserMailboxLogons = $Last50Logons LastSuspectUserLogon = @($LastSignIn) SuspectUserDevices = @($Devices) NewRules = @($RulesLog) MailboxPermissionChanges = @($PermissionsLog) - NewUsers = @(($7dayslog | Where-Object -Property Operations -In "Add user.").AuditData | ConvertFrom-Json) - ChangedPasswords = @(($7dayslog | Where-Object -Property Operations -In "Change user password.", "Reset user password.").AuditData | ConvertFrom-Json) + NewUsers = @($NewUsers) + MFADevices = $MFADevices + ChangedPasswords = $PasswordChanges ExtractedAt = (Get-Date).ToString('s') + ExtractResult = $ExtractResult } - } catch { diff --git a/ExecBECCheck/run.ps1 b/ExecBECCheck/run.ps1 index 87b7175980f1..6790917a0af7 100644 --- a/ExecBECCheck/run.ps1 +++ b/ExecBECCheck/run.ps1 @@ -5,7 +5,7 @@ param($Request, $TriggerMetadata) $body = if ($request.query.GUID) { $Table = Get-CippTable -tablename 'cachebec' - $Filter = "PartitionKey eq 'bec' and RowKey eq '$($request.query.GUID)'" + $Filter = "PartitionKey eq 'bec' and RowKey eq '$($request.query.GUID)'" $JSONOutput = Get-CIPPAzDataTableEntity @Table -Filter $Filter if (!$JSONOutput) { @{ Waiting = $true } @@ -18,6 +18,7 @@ else { $OrchRequest = [PSCustomObject]@{ TenantFilter = $request.query.tenantfilter UserID = $request.query.userid + userName = $request.query.userName } $InstanceId = Start-NewOrchestration -FunctionName 'Durable_BECRun' -InputObject $OrchRequest @{ GUID = $request.query.userid } diff --git a/ExecBECRemediate/run.ps1 b/ExecBECRemediate/run.ps1 index c47647d1c5ab..6f4a25eee516 100644 --- a/ExecBECRemediate/run.ps1 +++ b/ExecBECRemediate/run.ps1 @@ -8,22 +8,27 @@ Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME - Write-Host "PowerShell HTTP trigger function processed a request." $TenantFilter = $request.body.tenantfilter -$SuspectUser = $($request.body.userid) +$SuspectUser = $request.body.userid +$username = $request.body.username Write-Host $TenantFilter Write-Host $SuspectUser -try { - $password = New-PasswordString - $mustChange = 'true' - $passwordProfile = @" -{"passwordProfile": { "forceChangePasswordNextSignIn": $mustChange, "password": "$password" }}' -"@ - $GraphRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/v1.0/users/$SuspectUser" -tenantid $TenantFilter -type PATCH -body $passwordProfile -verbose - $GraphRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/v1.0/users/$SuspectUser" -tenantid $TenantFilter -type PATCH -body '{"accountEnabled":"false"}' -verbose - $GraphRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/v1.0/users/$SuspectUser/revokeSignInSessions" -tenantid $TenantFilter -type POST -body '{}' -verbose - $Mailboxes = New-ExoRequest -anchor $SuspectUser -tenantid $TenantFilter -cmdlet "get-inboxrule" -cmdParams @{Mailbox = $SuspectUser } | ForEach-Object { - New-ExoRequest -anchor $SuspectUser -tenantid $TenantFilter -cmdlet "Disable-InboxRule" -cmdParams @{Confirm = $false; Identity = $_.Identity } +$Results = try { + Set-CIPPResetPassword -userid $username -tenantFilter $TenantFilter -APIName $APINAME -ExecutingUser $request.headers.'x-ms-client-principal' + Set-CIPPSignInState -userid $username -AccountEnabled $false -tenantFilter $TenantFilter -APIName $APINAME -ExecutingUser $request.headers.'x-ms-client-principal' + Revoke-CIPPSessions -userid $SuspectUser -username $request.body.username -ExecutingUser $request.headers.'x-ms-client-principal' -APIName $APINAME -tenantFilter $TenantFilter + $RuleDisabled = 0 + New-ExoRequest -anchor $username -tenantid $TenantFilter -cmdlet "get-inboxrule" -cmdParams @{Mailbox = $username } | ForEach-Object { + $null = New-ExoRequest -anchor $username -tenantid $TenantFilter -cmdlet "Disable-InboxRule" -cmdParams @{Confirm = $false; Identity = $_.Identity } + "Disabled Inbox Rule $($_.Identity) for $username" + $RuleDisabled ++ } - $results = [pscustomobject]@{"Results" = "Executed Remediation for $SuspectUser and tenant $($TenantFilter). The temporary password is $password and must be changed at next logon." } + if ($RuleDisabled) { + "Disabled $RuleDisabled Inbox Rules for $username" + } + else { + "No Inbox Rules found for $username. We have not disabled any rules." + } + Write-LogMessage -API "BECRemediate" -tenant $tenantfilter -message "Executed Remediation for $SuspectUser" -sev "Info" } @@ -32,9 +37,10 @@ catch { $results = [pscustomobject]@{"Results" = "Failed to execute remediation. $($_.Exception.Message)" } Write-LogMessage -API "BECRemediate" -tenant $tenantfilter -message "Executed Remediation for $SuspectUser failed" -sev "Error" } +$results = [pscustomobject]@{"Results" = @($Results) } # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK - Body = ($Results) + Body = $Results }) From 99cb52bd286f3d442b42680a0d5d3a0c0bea372b Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Thu, 16 Nov 2023 13:48:47 +0100 Subject: [PATCH 42/55] mailbox list rules fixes --- ListMailboxRules/run.ps1 | 10 ++++++---- ListMailboxRulesAllTenants/run.ps1 | 5 +++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/ListMailboxRules/run.ps1 b/ListMailboxRules/run.ps1 index d2150d11e636..08cc420b409a 100644 --- a/ListMailboxRules/run.ps1 +++ b/ListMailboxRules/run.ps1 @@ -14,21 +14,23 @@ Write-Host 'PowerShell HTTP trigger function processed a request.' $TenantFilter = $Request.Query.TenantFilter $Table = Get-CIPPTable -TableName cachembxrules -$Rows = Get-CIPPAzDataTableEntity @Table | Where-Object -Property Timestamp -GT (Get-Date).AddMinutes(-15) +$Rows = Get-CIPPAzDataTableEntity @Table | Where-Object -Property Timestamp -GT (Get-Date).Addhours(-1) if (!$Rows) { Push-OutputBinding -Name Msg -Value $TenantFilter $GraphRequest = [PSCustomObject]@{ Tenant = 'Loading data. Please check back in 1 minute' Licenses = 'Loading data. Please check back in 1 minute' } -} else { +} +else { if ($TenantFilter -ne 'AllTenants') { $GraphRequest = $Rows | Where-Object -Property Tenant -EQ $TenantFilter | ForEach-Object { $NewObj = $_.Rules | ConvertFrom-Json $NewObj | Add-Member -NotePropertyName 'Tenant' -NotePropertyValue $TenantFilter $NewObj } - } else { + } + else { $GraphRequest = $Rows | ForEach-Object { $TenantName = $_.Tenant $NewObj = $_.Rules | ConvertFrom-Json @@ -38,7 +40,7 @@ if (!$Rows) { } } #Remove all old cache -Remove-AzDataTableEntity @Table -Entity (Get-CIPPAzDataTableEntity @Table -Property PartitionKey, RowKey, Timestamp | Where-Object -Property Timestamp -LT (Get-Date).AddMinutes(-15)) +#Remove-AzDataTableEntity @Table -Entity (Get-CIPPAzDataTableEntity @Table -Property PartitionKey, RowKey, Timestamp | Where-Object -Property Timestamp -LT (Get-Date).AddMinutes(-15)) Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ diff --git a/ListMailboxRulesAllTenants/run.ps1 b/ListMailboxRulesAllTenants/run.ps1 index 5c39385a1c52..f47e6b1b105a 100644 --- a/ListMailboxRulesAllTenants/run.ps1 +++ b/ListMailboxRulesAllTenants/run.ps1 @@ -14,10 +14,11 @@ else { $Tenants | ForEach-Object -Parallel { $domainName = $_.defaultDomainName Import-Module '.\GraphHelper.psm1' + Import-Module '.\Modules\CIPPcore' try { - $Rules = New-ExoRequest -tenantid $domainName -cmdlet "Get-Mailbox" | ForEach-Object { - New-ExoRequest -tenantid $domainName -cmdlet "Get-InboxRule" -cmdParams @{Mailbox = $_.GUID } + $Rules = New-ExoRequest -tenantid $domainName -cmdlet "Get-Mailbox" | ForEach-Object -Parallel { + New-ExoRequest -Anchor $_.UserPrincipalName -tenantid $domainName -cmdlet "Get-InboxRule" -cmdParams @{Mailbox = $_.GUID } } foreach ($Rule in $Rules) { $GraphRequest = @{ From 724ce9e7fdc8c03a5078b60a3a7040e1d4a1b305 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Thu, 16 Nov 2023 20:23:20 +0100 Subject: [PATCH 43/55] queue multitenantapp --- ExecAddMultiTenantApp/function.json | 18 --------- .../Invoke-ExecAddMultiTenantApp.ps1 | 38 +++++++++++-------- .../Public/Entrypoints/Invoke-TestResults.ps1 | 16 ++++++++ .../Push-ExecAddMultiTenantApp.ps1 | 19 ++++++++++ 4 files changed, 57 insertions(+), 34 deletions(-) delete mode 100644 ExecAddMultiTenantApp/function.json create mode 100644 Modules/CIPPCore/Public/Entrypoints/Invoke-TestResults.ps1 create mode 100644 Modules/CIPPCore/Public/Entrypoints/Push-ExecAddMultiTenantApp.ps1 diff --git a/ExecAddMultiTenantApp/function.json b/ExecAddMultiTenantApp/function.json deleted file mode 100644 index bf6c3ef0c49a..000000000000 --- a/ExecAddMultiTenantApp/function.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "scriptFile": "../Modules/CippEntryPoints/CippEntryPoints.psm1", - "entryPoint": "Receive-CippHttpTrigger", - "bindings": [ - { - "authLevel": "anonymous", - "type": "httpTrigger", - "direction": "in", - "name": "Request", - "methods": ["get", "post"] - }, - { - "type": "http", - "direction": "out", - "name": "Response" - } - ] -} diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecAddMultiTenantApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecAddMultiTenantApp.ps1 index 5ea4cacd9de0..d027158c7be7 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecAddMultiTenantApp.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-ExecAddMultiTenantApp.ps1 @@ -11,36 +11,42 @@ function Invoke-ExecAddMultiTenantApp { $ApplicationResourceAccess = @{ ResourceAppId = '00000003-0000-0000-c000-000000000000'; resourceAccess = $ApplicationResources } $Results = try { - #This needs to be moved to a queue. - if ('allTenants' -in $Request.body.SelectedTenants.defaultDomainName) { $TenantFilter = Get-Tenants } else { $TenantFilter = $Request.body.SelectedTenants.defaultDomainName } if ($request.body.CopyPermissions -eq $true) { try { $ExistingApp = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/applications(appId='$($Request.body.AppId)')" -tenantid $ENV:tenantid -NoAuthCheck $true $DelegateResourceAccess = $Existingapp.requiredResourceAccess $ApplicationResourceAccess = $Existingapp.requiredResourceAccess - } catch { + } + catch { 'Failed to get existing permissions. The app does not exist in the partner tenant.' } } + #This needs to be moved to a queue. + if ('allTenants' -in $Request.body.SelectedTenants.defaultDomainName) { + $TenantFilter = (Get-Tenants).defaultDomainName + } + else { + $TenantFilter = $Request.body.SelectedTenants.defaultDomainName + } foreach ($Tenant in $TenantFilter) { try { - $ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -tenantid $Tenant - if ($Request.body.AppId -Notin $ServicePrincipalList.appId) { - $PostResults = New-GraphPostRequest 'https://graph.microsoft.com/beta/servicePrincipals' -type POST -tenantid $tenant -body "{ `"appId`": `"$($Request.body.AppId)`" }" - "Added $($Request.body.AppId) to tenant $($Tenant)" - } else { - "This app already exists in tenant $($Tenant). We're adding the required permissions." - } - - Add-CIPPApplicationPermission -RequiredResourceAccess $applicationResourceAccess -ApplicationId $Request.body.AppId -Tenantfilter $Tenant - Add-CIPPDelegatedPermission -RequiredResourceAccess $DelegateResourceAccess -ApplicationId $Request.body.AppId -Tenantfilter $Tenant - } catch { - "Error adding application to tenant $Tenant - $($_.Exception.Message)" + Push-OutputBinding -Name QueueItem -Value ([pscustomobject]@{ + FunctionName = 'ExecAddMultiTenantApp' + Tenant = $tenant + appId = $Request.body.appid + applicationResourceAccess = $ApplicationResourceAccess + delegateResourceAccess = $DelegateResourceAccess + }) + "Queued application to tenant $Tenant. See the logbook for deployment details" + } + catch { + "Error queuing application to tenant $Tenant - $($_.Exception.Message)" } } $StatusCode = [HttpStatusCode]::OK - } catch { + } + catch { $ErrorMsg = Get-NormalizedError -message $($_.Exception.Message) $Results = "Function Error: $ErrorMsg" $StatusCode = [HttpStatusCode]::BadRequest diff --git a/Modules/CIPPCore/Public/Entrypoints/Invoke-TestResults.ps1 b/Modules/CIPPCore/Public/Entrypoints/Invoke-TestResults.ps1 new file mode 100644 index 000000000000..b8718793f559 --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/Invoke-TestResults.ps1 @@ -0,0 +1,16 @@ +function Invoke-TestResults { + + Push-OutputBinding -Name QueueItem -Value ([pscustomobject]@{ + FunctionName = 'TestResults' + Body = @{ + Permissions = $true + Tenants = $true + GDAP = $true + } + }) + Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ + StatusCode = [HttpStatusCode]::OK + Body = "yes" + }) + +} \ No newline at end of file diff --git a/Modules/CIPPCore/Public/Entrypoints/Push-ExecAddMultiTenantApp.ps1 b/Modules/CIPPCore/Public/Entrypoints/Push-ExecAddMultiTenantApp.ps1 new file mode 100644 index 000000000000..b3ccd8a704ee --- /dev/null +++ b/Modules/CIPPCore/Public/Entrypoints/Push-ExecAddMultiTenantApp.ps1 @@ -0,0 +1,19 @@ +function Push-ExecAddMultiTenantApp($QueueItem, $TriggerMetadata) { + try { + Write-Host $Queueitem + $ServicePrincipalList = New-GraphGETRequest -uri "https://graph.microsoft.com/beta/servicePrincipals?`$select=AppId,id,displayName&`$top=999" -tenantid $Queueitem.Tenant + if ($Queueitem.AppId -Notin $ServicePrincipalList.appId) { + $PostResults = New-GraphPostRequest 'https://graph.microsoft.com/beta/servicePrincipals' -type POST -tenantid $queueitem.tenant -body "{ `"appId`": `"$($Queueitem.appId)`" }" + Write-LogMessage -message "Added $($Queueitem.AppId) to tenant $($Queueitem.Tenant)" -tenant $Queueitem.Tenant -API "Add Multitenant App" -sev Info + } + else { + Write-LogMessage -message "This app already exists in tenant $($Queueitem.Tenant). We're adding the required permissions." -tenant $Queueitem.Tenant -API "Add Multitenant App" -sev Info + } + + Add-CIPPApplicationPermission -RequiredResourceAccess $queueitem.applicationResourceAccess -ApplicationId $queueitem.AppId -Tenantfilter $Queueitem.Tenant + Add-CIPPDelegatedPermission -RequiredResourceAccess $queueitem.DelegateResourceAccess -ApplicationId $queueitem.AppId -Tenantfilter $Queueitem.Tenant + } + catch { + Write-LogMessage -message "Error adding application to tenant $($Queueitem.Tenant) - $($_.Exception.Message)" -tenant $Queueitem.Tenant -API "Add Multitenant App" -sev Error + } +} \ No newline at end of file From bcdbb5f6bdb4cc44c56fd1497bac50f0cc3ff681 Mon Sep 17 00:00:00 2001 From: John Duprey Date: Fri, 17 Nov 2023 13:54:42 -0500 Subject: [PATCH 44/55] CPV tweaks --- ExecCPVPermissions/run.ps1 | 35 ++++++++++++++----- .../CIPPCore/Public/Set-CIPPCPVConsent.ps1 | 29 +++++++++------ 2 files changed, 45 insertions(+), 19 deletions(-) diff --git a/ExecCPVPermissions/run.ps1 b/ExecCPVPermissions/run.ps1 index 2801c3f1fca4..a015d769f4a2 100644 --- a/ExecCPVPermissions/run.ps1 +++ b/ExecCPVPermissions/run.ps1 @@ -4,24 +4,41 @@ using namespace System.Net param($Request, $TriggerMetadata) $APIName = $TriggerMetadata.FunctionName -Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" +Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message 'Accessed this API' -Sev 'Debug' # Write to the Azure Functions log stream. -Write-Host "PowerShell HTTP trigger function processed a request." +Write-Host 'PowerShell HTTP trigger function processed a request.' $TenantFilter = (get-tenants -IncludeAll -IncludeErrors | Where-Object -Property customerId -EQ $Request.query.Tenantfilter).defaultDomainName Write-Host "Our Tenantfilter is $TenantFilter" -$GraphRequest = try { - Set-CIPPCPVConsent -Tenantfilter $TenantFilter - Add-CIPPApplicationPermission -RequiredResourceAccess "CippDefaults" -ApplicationId $ENV:ApplicationID -tenantfilter $TenantFilter - Add-CIPPDelegatedPermission -RequiredResourceAccess "CippDefaults" -ApplicationId $ENV:ApplicationID -tenantfilter $TenantFilter + +$CPVConsentParams = @{ + Tenantfilter = $TenantFilter +} +if ($Request.Query.ResetSP -eq 'true') { + $CPVConsentParams.ResetSP = $true } -catch { - "Failed to update permissions for $($TenantFilter): $($_.Exception.Message)" + +$GraphRequest = try { + Set-CIPPCPVConsent @CPVConsentParams + Add-CIPPApplicationPermission -RequiredResourceAccess 'CippDefaults' -ApplicationId $ENV:ApplicationID -tenantfilter $TenantFilter + Add-CIPPDelegatedPermission -RequiredResourceAccess 'CippDefaults' -ApplicationId $ENV:ApplicationID -tenantfilter $TenantFilter + $Success = $true +} catch { + "Failed to update permissions for $($TenantFilter): $($_.Exception.Message)" + $Success = $false } +$Tenant = Get-Tenants -IncludeAll -IncludeErrors | Where-Object -Property defaultDomainName -EQ $Tenantfilter + # Associate values to output bindings by calling 'Push-OutputBinding'. Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK - Body = @{Results = $GraphRequest } + Body = @{ + Results = $GraphRequest + Metadata = @{ + Heading = 'CPV Permission - {0} ({1})' -f $Tenant.displayName, $Tenant.defaultDomainName + Success = $Success + } + } }) diff --git a/Modules/CIPPCore/Public/Set-CIPPCPVConsent.ps1 b/Modules/CIPPCore/Public/Set-CIPPCPVConsent.ps1 index a139e2484188..8b3c1bbd0f82 100644 --- a/Modules/CIPPCore/Public/Set-CIPPCPVConsent.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPCPVConsent.ps1 @@ -2,14 +2,24 @@ function Set-CIPPCPVConsent { [CmdletBinding()] param( $Tenantfilter, - $APIName = "CPV Consent", - $ExecutingUser + $APIName = 'CPV Consent', + $ExecutingUser, + [bool]$ResetSP = $false ) - $Results = [System.Collections.ArrayList]@() + $Results = [System.Collections.Generic.List[string]]::new() $Tenant = Get-Tenants -IncludeAll -IncludeErrors | Where-Object -Property defaultDomainName -EQ $Tenantfilter $TenantName = $Tenant.defaultDomainName $TenantFilter = $Tenant.customerId + if ($ResetSP) { + try { + $DeleteSP = New-GraphpostRequest -Type DELETE -noauthcheck $true -uri "https://api.partnercenter.microsoft.com/v1/customers/$($TenantFilter)/applicationconsents/$($ENV:applicationId)" -scope 'https://api.partnercenter.microsoft.com/.default' -tenantid $env:TenantID + $Results.add("Deleted Service Principal from $TenantName") + } catch { + $Results.add("Error deleting SP - $($_.Exception.Message)") + } + } + try { $AppBody = @" { @@ -17,26 +27,25 @@ function Set-CIPPCPVConsent { "ApplicationId": "$($ENV:applicationId)" } "@ - $CPVConsent = New-GraphpostRequest -body $AppBody -Type POST -noauthcheck $true -uri "https://api.partnercenter.microsoft.com/v1/customers/$($TenantFilter)/applicationconsents" -scope "https://api.partnercenter.microsoft.com/.default" -tenantid $env:TenantID + $CPVConsent = New-GraphpostRequest -body $AppBody -Type POST -noauthcheck $true -uri "https://api.partnercenter.microsoft.com/v1/customers/$($TenantFilter)/applicationconsents" -scope 'https://api.partnercenter.microsoft.com/.default' -tenantid $env:TenantID $Table = Get-CIPPTable -TableName cpvtenants - $unixtime = [int64](([datetime]::UtcNow) - (Get-Date "1/1/1970")).TotalSeconds + $unixtime = [int64](([datetime]::UtcNow) - (Get-Date '1/1/1970')).TotalSeconds $GraphRequest = @{ LastApply = "$unixtime" applicationId = "$($ENV:applicationId)" Tenant = "$($tenantfilter)" PartitionKey = 'Tenant' RowKey = "$($tenantfilter)" - } + } Add-CIPPAzDataTableEntity @Table -Entity $GraphRequest -Force $Results.add("Successfully added CPV Application to tenant $($TenantName)") | Out-Null - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Added our Service Principal to $($TenantName): $($_.Exception.message)" -Sev "Info" -tenant $($Tenantfilter) + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Added our Service Principal to $($TenantName): $($_.Exception.message)" -Sev 'Info' -tenant $($Tenantfilter) - } - catch { + } catch { $ErrorMessage = $_.Exception.Message if ($ErrorMessage -like '*409 (Conflict)*') { return @("We've already added our Service Principal to $($TenantName)") } - Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Could not add our Service Principal to the client tenant $($TenantName): $($_.Exception.message)" -Sev "Error" -tenant $($Tenantfilter) + Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Could not add our Service Principal to the client tenant $($TenantName): $($_.Exception.message)" -Sev 'Error' -tenant $($Tenantfilter) return @("Could not add our Service Principal to the client tenant $($TenantName): $($_.Exception.message)") } return $Results From 8c588c5542483291ee419a21ffcf16998b7d7e8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Kj=C3=A6rg=C3=A5rd?= Date: Fri, 17 Nov 2023 22:17:55 +0100 Subject: [PATCH 45/55] Change caldefaults to use FolderID - More descriptive error and succes log --- Standards_calDefault/run.ps1 | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Standards_calDefault/run.ps1 b/Standards_calDefault/run.ps1 index b3160913ad5b..49c2b9702549 100644 --- a/Standards_calDefault/run.ps1 +++ b/Standards_calDefault/run.ps1 @@ -11,15 +11,13 @@ $Mailboxes = New-ExoRequest -tenantid $Tenant -cmdlet "get-mailbox" foreach ($Mailbox in $Mailboxes) { try { New-ExoRequest -tenantid $Tenant -cmdlet "Get-MailboxFolderStatistics" -cmdParams @{identity = $Mailbox.UserPrincipalName; FolderScope = 'Calendar' } -Anchor $Mailbox.UserPrincipalName | ForEach-Object { - New-ExoRequest -tenantid $Tenant -cmdlet "Set-MailboxFolderPermission" -cmdparams @{Identity = ($_.identity).replace('\', ':\'); User = 'Default'; AccessRights = $setting.permissionlevel } -Anchor $Mailbox.UserPrincipalName - Write-LogMessage -API "Standards" -tenant $tenant -message "Set default folder permission for $($Mailbox.UserPrincipalName) to $($setting.permissionlevel)" -sev Error - + New-ExoRequest -tenantid $Tenant -cmdlet "Set-MailboxFolderPermission" -cmdparams @{Identity = "$($Mailbox.UserPrincipalName):$($_.FolderId)"; User = 'Default'; AccessRights = $setting.permissionlevel } -Anchor $Mailbox.UserPrincipalName + Write-LogMessage -API "Standards" -tenant $tenant -message "Set default folder permission for $($Mailbox.UserPrincipalName):\$($_.Name) to $($setting.permissionlevel)" -sev Error } } catch { - Write-LogMessage -API "Standards" -tenant $tenant -message "Could not set default calendar permissions. Error: $($_.exception.message)" -sev Error + Write-LogMessage -API "Standards" -tenant $tenant -message "Could not set default calendar permissions for $($Mailbox.UserPrincipalName). Error: $($_.exception.message)" -sev Error } } -Write-LogMessage -API "Standards" -tenant $tenant -message "Done setting default calendar permissions." -sev Info - +Write-LogMessage -API "Standards" -tenant $tenant -message "Done setting default calendar permissions." -sev Info \ No newline at end of file From 3259686d0592a16a1c597a202783f96dc48e7ff2 Mon Sep 17 00:00:00 2001 From: lwhitelock <79275328+lwhitelock@users.noreply.github.com> Date: Sat, 18 Nov 2023 10:10:19 +0000 Subject: [PATCH 46/55] Fixed a bug in New-GraphBulkRequest Additional pages were returning data from the partner tenant instead of the customer tenant. --- GraphHelper.psm1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GraphHelper.psm1 b/GraphHelper.psm1 index 576bee5a7bb9..c33ade784b86 100644 --- a/GraphHelper.psm1 +++ b/GraphHelper.psm1 @@ -792,7 +792,7 @@ function New-GraphBulkRequest { foreach ($MoreData in $ReturnedData.Responses | Where-Object { $_.body.'@odata.nextLink' }) { Write-Host 'Getting more' - $AdditionalValues = New-GraphGetRequest -ComplexFilter -uri $MoreData.body.'@odata.nextLink' -tenantid $TenantFilter -NoAuthCheck:$NoAuthCheck + $AdditionalValues = New-GraphGetRequest -ComplexFilter -uri $MoreData.body.'@odata.nextLink' -tenantid $tenantid -NoAuthCheck:$NoAuthCheck $NewValues = [System.Collections.Generic.List[PSCustomObject]]$MoreData.body.value $AdditionalValues | ForEach-Object { $NewValues.add($_) } $MoreData.body.value = $NewValues From c2bdef1f947f34712c9e05e06c64282fd3921a58 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Sat, 18 Nov 2023 16:45:53 +0100 Subject: [PATCH 47/55] added warnings to the exchange properties --- GraphHelper.psm1 | 5 ++++- .../Public/Remove-CIPPMailboxPermissions.ps1 | 22 ++++++++++++------- .../Public/Remove-CIPPMobileDevice.ps1 | 7 +++--- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/GraphHelper.psm1 b/GraphHelper.psm1 index c33ade784b86..7ce9c97e513c 100644 --- a/GraphHelper.psm1 +++ b/GraphHelper.psm1 @@ -528,7 +528,7 @@ function Get-Tenants { Add-CIPPAzDataTableEntity @TenantsTable -Entity $IncludedTenantsCache } } - return ($IncludedTenantsCache | Where-Object -Property defaultDomainName -ne $null | Sort-Object -Property displayName) + return ($IncludedTenantsCache | Where-Object -Property defaultDomainName -NE $null | Sort-Object -Property displayName) } @@ -599,6 +599,9 @@ function New-ExoRequest ($tenantid, $cmdlet, $cmdParams, $useSystemMailbox, $Anc } try { $ReturnedData = Invoke-RestMethod "https://outlook.office365.com/adminapi/beta/$($tenant)/InvokeCommand" -Method POST -Body $ExoBody -Headers $Headers -ContentType 'application/json; charset=utf-8' + if ($ReturnedData.'@adminapi.warnings') { + $ReturnedData.value = $ReturnedData.'@adminapi.warnings' + } } catch { $ErrorMess = $($_.Exception.Message) diff --git a/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 b/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 index d49dcb1f618c..f7379ce6e459 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 @@ -20,19 +20,25 @@ function Remove-CIPPMailboxPermissions { $Results = $PermissionsLevel | ForEach-Object { switch ($_) { "SendOnBehalf" { - $MailboxPerms = New-ExoRequest -Anchor $username -tenantid $Tenantfilter -cmdlet "Set-Mailbox" -cmdParams @{Identity = $userid; GrantSendonBehalfTo = @{'@odata.type' = '#Exchange.GenericHashTable'; remove = $AccessUser }; } - Write-LogMessage -user $ExecutingUser -API $APIName -message "Removed SendOnBehalf permissions for $($AccessUser) from $($userid)'s mailbox." -Sev "Info" -tenant $TenantFilter - "Removed SendOnBehalf permissions for $($AccessUser) from $($userid)'s mailbox." + $MailboxPerms = New-ExoRequest -Anchor $UserId -tenantid $Tenantfilter -cmdlet "Set-Mailbox" -cmdParams @{Identity = $userid; GrantSendonBehalfTo = @{'@odata.type' = '#Exchange.GenericHashTable'; remove = $AccessUser }; } + if ($MailboxPerms -notlike "* because the ACE doesn't exist on the object.*") { + Write-LogMessage -user $ExecutingUser -API $APIName -message "Removed SendOnBehalf permissions for $($AccessUser) from $($userid)'s mailbox." -Sev "Info" -tenant $TenantFilter + "Removed SendOnBehalf permissions for $($AccessUser) from $($userid)'s mailbox." + } } "SendAS" { - $MailboxPerms = New-ExoRequest -Anchor $username -tenantid $Tenantfilter -cmdlet "Remove-RecipientPermission" -cmdParams @{Identity = $userid; Trustee = $AccessUser; accessRights = @("SendAs") } - Write-LogMessage -user $ExecutingUser -API $APIName -message "Removed SendAs permissions for $($AccessUser) from $($userid)'s mailbox." -Sev "Info" -tenant $TenantFilter - "Removed SendAs permissions for $($AccessUser) from $($userid)'s mailbox." + $MailboxPerms = New-ExoRequest -Anchor $userId-tenantid $Tenantfilter -cmdlet "Remove-RecipientPermission" -cmdParams @{Identity = $userid; Trustee = $AccessUser; accessRights = @("SendAs") } + if ($MailboxPerms -notlike "* because the ACE doesn't exist on the object.*") { + Write-LogMessage -user $ExecutingUser -API $APIName -message "Removed SendAs permissions for $($AccessUser) from $($userid)'s mailbox." -Sev "Info" -tenant $TenantFilter + "Removed SendAs permissions for $($AccessUser) from $($userid)'s mailbox." + } } "FullAccess" { $permissions = New-ExoRequest -tenantid $TenantFilter -cmdlet "Remove-MailboxPermission" -cmdParams @{Identity = $userid; user = $AccessUser; accessRights = @("FullAccess") } -Anchor $userid - Write-LogMessage -user $ExecutingUser -API $APIName -message "Removed FullAccess permissions for $($AccessUser) from $($userid)'s mailbox." -Sev "Info" -tenant $TenantFilter - "Removed FullAccess permissions for $($AccessUser) from $($userid)'s mailbox." + if ($MailboxPerms -notlike "* because the ACE doesn't exist on the object.*") { + Write-LogMessage -user $ExecutingUser -API $APIName -message "Removed FullAccess permissions for $($AccessUser) from $($userid)'s mailbox." -Sev "Info" -tenant $TenantFilter + "Removed FullAccess permissions for $($AccessUser) from $($userid)'s mailbox." + } } } } diff --git a/Modules/CIPPCore/Public/Remove-CIPPMobileDevice.ps1 b/Modules/CIPPCore/Public/Remove-CIPPMobileDevice.ps1 index ad59e935e9d1..d5d6d6b73228 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPMobileDevice.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPMobileDevice.ps1 @@ -12,16 +12,15 @@ function Remove-CIPPMobileDevice { $devices = New-ExoRequest -tenantid $tenantFilter -cmdlet "Get-MobileDevice" -Anchor $username -cmdParams @{mailbox = $username } | ForEach-Object { try { New-ExoRequest -tenantid $tenantFilter -cmdlet "Remove-MobileDevice" -Anchor $username -cmdParams @{Identity = $_.Identity } - return "Removed device: $($_.FriendlyName)" + "Removed device: $($_.FriendlyName)" } catch { - return "Could not remove device: $($_.FriendlyName)" - continue + "Could not remove device: $($_.FriendlyName)" } } Write-LogMessage -user $ExecutingUser -API $APIName -message "Deleted mobile devices for $($username)" -Sev "Info" -tenant $tenantFilter - return "Deleted mobile devices for $($username)" + return $devices } catch { Write-LogMessage -user $ExecutingUser -API $APIName -message "Could not delete mobile devices for $($username): $($_.Exception.Message)" -Sev "Error" -tenant $tenantFilter From 86af7e7e97d39a674e55035c140a5b24a0197173 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Sat, 18 Nov 2023 16:48:19 +0100 Subject: [PATCH 48/55] fixes logging --- Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 b/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 index f7379ce6e459..6b27abd53884 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 @@ -21,21 +21,21 @@ function Remove-CIPPMailboxPermissions { switch ($_) { "SendOnBehalf" { $MailboxPerms = New-ExoRequest -Anchor $UserId -tenantid $Tenantfilter -cmdlet "Set-Mailbox" -cmdParams @{Identity = $userid; GrantSendonBehalfTo = @{'@odata.type' = '#Exchange.GenericHashTable'; remove = $AccessUser }; } - if ($MailboxPerms -notlike "* because the ACE doesn't exist on the object.*") { + if ($MailboxPerms -notlike "*because the ACE doesn't exist on the object.*") { Write-LogMessage -user $ExecutingUser -API $APIName -message "Removed SendOnBehalf permissions for $($AccessUser) from $($userid)'s mailbox." -Sev "Info" -tenant $TenantFilter "Removed SendOnBehalf permissions for $($AccessUser) from $($userid)'s mailbox." } } "SendAS" { $MailboxPerms = New-ExoRequest -Anchor $userId-tenantid $Tenantfilter -cmdlet "Remove-RecipientPermission" -cmdParams @{Identity = $userid; Trustee = $AccessUser; accessRights = @("SendAs") } - if ($MailboxPerms -notlike "* because the ACE doesn't exist on the object.*") { + if ($MailboxPerms -notlike "*because the ACE doesn't exist on the object.*") { Write-LogMessage -user $ExecutingUser -API $APIName -message "Removed SendAs permissions for $($AccessUser) from $($userid)'s mailbox." -Sev "Info" -tenant $TenantFilter "Removed SendAs permissions for $($AccessUser) from $($userid)'s mailbox." } } "FullAccess" { $permissions = New-ExoRequest -tenantid $TenantFilter -cmdlet "Remove-MailboxPermission" -cmdParams @{Identity = $userid; user = $AccessUser; accessRights = @("FullAccess") } -Anchor $userid - if ($MailboxPerms -notlike "* because the ACE doesn't exist on the object.*") { + if ($MailboxPerms -notlike "*because the ACE doesn't exist on the object.*") { Write-LogMessage -user $ExecutingUser -API $APIName -message "Removed FullAccess permissions for $($AccessUser) from $($userid)'s mailbox." -Sev "Info" -tenant $TenantFilter "Removed FullAccess permissions for $($AccessUser) from $($userid)'s mailbox." } From 110703953a19234c3ba450939d895bb61a218f7d Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Sat, 18 Nov 2023 17:11:50 +0100 Subject: [PATCH 49/55] spacing issue --- Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 b/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 index 6b27abd53884..d2bcdef824ca 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 @@ -27,7 +27,7 @@ function Remove-CIPPMailboxPermissions { } } "SendAS" { - $MailboxPerms = New-ExoRequest -Anchor $userId-tenantid $Tenantfilter -cmdlet "Remove-RecipientPermission" -cmdParams @{Identity = $userid; Trustee = $AccessUser; accessRights = @("SendAs") } + $MailboxPerms = New-ExoRequest -Anchor $userId -tenantid $Tenantfilter -cmdlet "Remove-RecipientPermission" -cmdParams @{Identity = $userid; Trustee = $AccessUser; accessRights = @("SendAs") } if ($MailboxPerms -notlike "*because the ACE doesn't exist on the object.*") { Write-LogMessage -user $ExecutingUser -API $APIName -message "Removed SendAs permissions for $($AccessUser) from $($userid)'s mailbox." -Sev "Info" -tenant $TenantFilter "Removed SendAs permissions for $($AccessUser) from $($userid)'s mailbox." From d4c297032c7799028e2c02d2218c214fcd54b56f Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Sat, 18 Nov 2023 17:15:27 +0100 Subject: [PATCH 50/55] fixes logging issues --- Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 b/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 index d2bcdef824ca..b11a1bfbe7d9 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 @@ -21,21 +21,21 @@ function Remove-CIPPMailboxPermissions { switch ($_) { "SendOnBehalf" { $MailboxPerms = New-ExoRequest -Anchor $UserId -tenantid $Tenantfilter -cmdlet "Set-Mailbox" -cmdParams @{Identity = $userid; GrantSendonBehalfTo = @{'@odata.type' = '#Exchange.GenericHashTable'; remove = $AccessUser }; } - if ($MailboxPerms -notlike "*because the ACE doesn't exist on the object.*") { + if ($MailboxPerms -notlike "*completed successfully but no settings of*") { Write-LogMessage -user $ExecutingUser -API $APIName -message "Removed SendOnBehalf permissions for $($AccessUser) from $($userid)'s mailbox." -Sev "Info" -tenant $TenantFilter "Removed SendOnBehalf permissions for $($AccessUser) from $($userid)'s mailbox." } } "SendAS" { $MailboxPerms = New-ExoRequest -Anchor $userId -tenantid $Tenantfilter -cmdlet "Remove-RecipientPermission" -cmdParams @{Identity = $userid; Trustee = $AccessUser; accessRights = @("SendAs") } - if ($MailboxPerms -notlike "*because the ACE doesn't exist on the object.*") { + if ($MailboxPerms -notlike "*because the ACE isn't present*") { Write-LogMessage -user $ExecutingUser -API $APIName -message "Removed SendAs permissions for $($AccessUser) from $($userid)'s mailbox." -Sev "Info" -tenant $TenantFilter "Removed SendAs permissions for $($AccessUser) from $($userid)'s mailbox." } } "FullAccess" { $permissions = New-ExoRequest -tenantid $TenantFilter -cmdlet "Remove-MailboxPermission" -cmdParams @{Identity = $userid; user = $AccessUser; accessRights = @("FullAccess") } -Anchor $userid - if ($MailboxPerms -notlike "*because the ACE doesn't exist on the object.*") { + if ($permissions -notlike "*because the ACE doesn't exist on the object.*") { Write-LogMessage -user $ExecutingUser -API $APIName -message "Removed FullAccess permissions for $($AccessUser) from $($userid)'s mailbox." -Sev "Info" -tenant $TenantFilter "Removed FullAccess permissions for $($AccessUser) from $($userid)'s mailbox." } From 823188ada68d9e5d5547c68df8b204504be73cbd Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Sat, 18 Nov 2023 17:21:26 +0100 Subject: [PATCH 51/55] remove properties no longer supported --- AddTransportRule/run.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AddTransportRule/run.ps1 b/AddTransportRule/run.ps1 index dfc36253ff85..173f2662cc3f 100644 --- a/AddTransportRule/run.ps1 +++ b/AddTransportRule/run.ps1 @@ -6,7 +6,7 @@ param($Request, $TriggerMetadata) $APIName = $TriggerMetadata.FunctionName Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -message "Accessed this API" -Sev "Debug" -$RequestParams = $Request.Body.PowerShellCommand | ConvertFrom-Json | Select-Object -Property * -ExcludeProperty GUID, Comments +$RequestParams = $Request.Body.PowerShellCommand | ConvertFrom-Json | Select-Object -Property * -ExcludeProperty GUID, Comments, HasSenderOverride, ExceptIfHasSenderOverride, ExceptIfMessageContainsDataClassifications, MessageContainsDataClassifications $Tenants = ($Request.body | Select-Object Select_*).psobject.properties.value $Result = foreach ($Tenantfilter in $tenants) { From 3ed3e7064c6a964ae29acc9af2164c68ea4cbe6c Mon Sep 17 00:00:00 2001 From: rvdwegen Date: Sat, 18 Nov 2023 21:24:16 +0100 Subject: [PATCH 52/55] Add option to add owners/members to certain groups --- AddGroup/run.ps1 | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/AddGroup/run.ps1 b/AddGroup/run.ps1 index cc6798edd0eb..88e9d50debda 100644 --- a/AddGroup/run.ps1 +++ b/AddGroup/run.ps1 @@ -16,7 +16,7 @@ $results = foreach ($tenant in $SelectedTenants) { try { $email = if ($groupobj.domain) { "$($groupobj.username)@$($groupobj.domain)" } else { "$($groupobj.username)@$($tenant)" } if ($groupobj.groupType -in "Generic", "azurerole", "dynamic") { - + $BodyToship = [pscustomobject] @{ "displayName" = $groupobj.Displayname "description" = $groupobj.Description @@ -24,13 +24,18 @@ $results = foreach ($tenant in $SelectedTenants) { mailEnabled = [bool]$false securityEnabled = [bool]$true isAssignableToRole = [bool]($groupobj | Where-Object -Property groupType -EQ "AzureRole") - - } + } if ($groupobj.membershipRules) { $BodyToship | Add-Member -NotePropertyName "membershipRule" -NotePropertyValue ($groupobj.membershipRules) $BodyToship | Add-Member -NotePropertyName "groupTypes" -NotePropertyValue @("DynamicMembership") $BodyToship | Add-Member -NotePropertyName "membershipRuleProcessingState" -NotePropertyValue "On" } + if ($groupobj.AddOwner -AND $groupobj.groupType -in "generic", "azurerole", "security") { + $BodyToship | Add-Member -NotePropertyName "owners@odata.bind" -NotePropertyValue (($groupobj.AddOwner) | ForEach-Object { "https://graph.microsoft.com/v1.0/users/$($_.value)" }) + } + if ($groupobj.AddMember -AND $groupobj.groupType -in "generic", "azurerole", "security") { + $BodyToship | Add-Member -NotePropertyName "members@odata.bind" -NotePropertyValue (($groupobj.AddMember) | ForEach-Object { "https://graph.microsoft.com/v1.0/users/$($_.value)" }) + } $GraphRequest = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/groups" -tenantid $tenant -type POST -body (ConvertTo-Json -InputObject $BodyToship -Depth 10) -verbose } else { @@ -43,6 +48,7 @@ $results = foreach ($tenant in $SelectedTenants) { RequireSenderAuthenticationEnabled = [bool]!$groupobj.AllowExternal } $GraphRequest = New-ExoRequest -tenantid $tenant -cmdlet "New-DistributionGroup" -cmdParams $params + # At some point add logic to use AddOwner/AddMember for New-DistributionGroup, but idk how we're going to brr that - rvdwegen } "Successfully created group $($groupobj.displayname) for $($tenant)" Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Created group $($groupobj.displayname) with id $($GraphRequest.id) " -Sev "Info" @@ -51,7 +57,6 @@ $results = foreach ($tenant in $SelectedTenants) { catch { Write-LogMessage -user $request.headers.'x-ms-client-principal' -API $APINAME -tenant $tenant -message "Group creation API failed. $($_.Exception.Message)" -Sev "Error" "Failed to create group. $($groupobj.displayname) for $($tenant) $($_.Exception.Message)" - } } $body = [pscustomobject]@{"Results" = @($results) } @@ -60,4 +65,4 @@ $body = [pscustomobject]@{"Results" = @($results) } Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ StatusCode = [HttpStatusCode]::OK Body = $Body - }) + }) \ No newline at end of file From 0e4da1331167fa245833c0f2202251c1cc89291f Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 20 Nov 2023 13:35:52 +0100 Subject: [PATCH 53/55] upped versions --- version_latest.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version_latest.txt b/version_latest.txt index 50021202769b..28446a5ea556 100644 --- a/version_latest.txt +++ b/version_latest.txt @@ -1 +1 @@ -4.5.5 \ No newline at end of file +4.6.0 \ No newline at end of file From 3bc50dad6f27d58bb5671afd0d4e073b7393ef31 Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 20 Nov 2023 23:36:27 +0100 Subject: [PATCH 54/55] Fixes scheduled offboarding bug. --- Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 b/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 index 6fb164fe356c..4232a71adaf4 100644 --- a/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 +++ b/Modules/CIPPCore/Public/Invoke-CIPPOffboardingJob.ps1 @@ -68,7 +68,8 @@ function Invoke-CIPPOffboardingJob { } { $_."RemovePermissions" } { if ($RunScheduled) { - Remove-CIPPMailboxPermissions #Finish this + Remove-CIPPMailboxPermissions -PermissionsLevel @("FullAccess", "SendAs", "SendOnBehalf") -userid "AllUsers" -AccessUser $UserName -TenantFilter $TenantFilter -APIName $APINAME -ExecutingUser $ExecutingUser + } else { $object = [PSCustomObject]@{ From d057aad260dd0a7882b3171de2e96835391c04eb Mon Sep 17 00:00:00 2001 From: KelvinTegelaar Date: Mon, 20 Nov 2023 23:46:12 +0100 Subject: [PATCH 55/55] fixes removal bug --- Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 | 4 ++++ version_latest.txt | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 b/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 index b11a1bfbe7d9..c9e480445056 100644 --- a/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 +++ b/Modules/CIPPCore/Public/Remove-CIPPMailboxPermissions.ps1 @@ -13,6 +13,10 @@ function Remove-CIPPMailboxPermissions { if ($userid -eq "AllUsers") { $Mailboxes = New-ExoRequest -tenantid $TenantFilter -cmdlet "get-mailbox" $Mailboxes | ForEach-Object -Parallel { + Import-Module ".\Modules\CIPPCore" + import-module ".\GraphHelper.psm1" + Import-Module ".\Modules\AzBobbyTables" + Write-Host "Removing permissions from mailbox $($_.UserPrincipalName)" Remove-CIPPMailboxPermissions -PermissionsLevel @("FullAccess", "SendAs", "SendOnBehalf") -userid $_.UserPrincipalName -AccessUser $using:AccessUser -TenantFilter $using:TenantFilter -APIName $using:APINAME -ExecutingUser $using:ExecutingUser } -ThrottleLimit 10 } diff --git a/version_latest.txt b/version_latest.txt index 28446a5ea556..f4fa8fcb995d 100644 --- a/version_latest.txt +++ b/version_latest.txt @@ -1 +1 @@ -4.6.0 \ No newline at end of file +4.6.1 \ No newline at end of file