diff --git a/.github/workflows/publish_release.yml b/.github/workflows/publish_release.yml index 81acfa86790f..ed540c3ac714 100644 --- a/.github/workflows/publish_release.yml +++ b/.github/workflows/publish_release.yml @@ -48,11 +48,36 @@ jobs: echo "tag_exists=false" >> $GITHUB_ENV fi + # Get Previous Tag + - name: Get Previous Tag + id: previous_tag + if: env.tag_exists == 'false' + run: | + PREV_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") + echo "previous_tag=$PREV_TAG" >> $GITHUB_OUTPUT + echo "Previous tag: $PREV_TAG" + # Generate Release Notes - name: Generate Release Notes id: changelog if: env.tag_exists == 'false' - uses: mikepenz/release-changelog-builder-action@v5.0.0 + uses: actions/github-script@v7 + with: + script: | + const params = { + owner: context.repo.owner, + repo: context.repo.repo, + tag_name: '${{ steps.get_version.outputs.version }}', + target_commitish: context.sha + }; + + const previousTag = '${{ steps.previous_tag.outputs.previous_tag }}'; + if (previousTag) { + params.previous_tag_name = previousTag; + } + + const { data } = await github.rest.repos.generateReleaseNotes(params); + core.setOutput('changelog', data.body); env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -75,10 +100,6 @@ jobs: if: env.tag_exists == 'false' run: | mkdir -p src/releases - zip -r src/releases/release_${{ steps.get_version.outputs.version }}.zip . \ - --exclude "./src/releases/*" \ - --exclude ".*" \ - --exclude ".*/**" zip -r src/releases/latest.zip . \ --exclude "./src/releases/*" \ --exclude ".*" \ diff --git a/Modules/CIPPCore/Public/Add-CIPPDbItem.ps1 b/Modules/CIPPCore/Public/Add-CIPPDbItem.ps1 index 88b630bdf701..bd9c4d733eff 100644 --- a/Modules/CIPPCore/Public/Add-CIPPDbItem.ps1 +++ b/Modules/CIPPCore/Public/Add-CIPPDbItem.ps1 @@ -69,23 +69,55 @@ function Add-CIPPDbItem { if ($ExistingEntities) { Remove-AzDataTableEntity @Table -Entity $ExistingEntities -Force | Out-Null } - $Entities = foreach ($Item in $Data) { - $ItemId = $Item.id ?? $Item.ExternalDirectoryObjectId ?? $Item.Identity ?? $Item.skuId - @{ - PartitionKey = $TenantFilter - RowKey = Format-RowKey "$Type-$ItemId" - Data = [string]($Item | ConvertTo-Json -Depth 10 -Compress) - Type = $Type + + # Calculate batch size based on available memory + $AvailableMemory = [System.GC]::GetTotalMemory($false) + $AvailableMemoryMB = [math]::Round($AvailableMemory / 1MB, 2) + + # Estimate item size from first item (with fallback) + $EstimatedItemSizeBytes = 1KB # Default assumption + if ($Data.Count -gt 0) { + $SampleJson = $Data[0] | ConvertTo-Json -Depth 10 -Compress + $EstimatedItemSizeBytes = [System.Text.Encoding]::UTF8.GetByteCount($SampleJson) + } + + # Use 25% of available memory for batch processing, with min/max bounds + $TargetBatchMemoryMB = [Math]::Max(50, $AvailableMemoryMB * 0.25) + $CalculatedBatchSize = [Math]::Floor(($TargetBatchMemoryMB * 1MB) / $EstimatedItemSizeBytes) + # Reduce max to 500 to prevent OOM with large datasets + $BatchSize = [Math]::Max(100, [Math]::Min(500, $CalculatedBatchSize)) + + $TotalCount = $Data.Count + $ProcessedCount = 0 + Write-Information "Adding $TotalCount items of type $Type to CIPP Reporting DB for tenant $TenantFilter | Available Memory: ${AvailableMemoryMB}MB | Target Memory: ${TargetBatchMemoryMB}MB | Calculated: $CalculatedBatchSize | Batch Size: $BatchSize (est. item size: $([math]::Round($EstimatedItemSizeBytes/1KB, 2))KB)" + for ($i = 0; $i -lt $TotalCount; $i += $BatchSize) { + $BatchEnd = [Math]::Min($i + $BatchSize, $TotalCount) + $Batch = $Data[$i..($BatchEnd - 1)] + + $Entities = foreach ($Item in $Batch) { + $ItemId = $Item.id ?? $Item.ExternalDirectoryObjectId ?? $Item.Identity ?? $Item.skuId + @{ + PartitionKey = $TenantFilter + RowKey = Format-RowKey "$Type-$ItemId" + Data = [string]($Item | ConvertTo-Json -Depth 10 -Compress) + Type = $Type + } } + + Add-CIPPAzDataTableEntity @Table -Entity $Entities -Force | Out-Null + $ProcessedCount += $Batch.Count + + # Clear batch variables to free memory + $Entities = $null + $Batch = $null + [System.GC]::Collect() } - Add-CIPPAzDataTableEntity @Table -Entity $Entities -Force | Out-Null } - Write-LogMessage -API 'CIPPDbItem' -tenant $TenantFilter -message "Added $($Data.Count) items of type $Type$(if ($Count) { ' (count mode)' })" -sev Debug } catch { - Write-LogMessage -API 'CIPPDbItem' -tenant $TenantFilter -message "Failed to add items of type $Type : $($_.Exception.Message)" -sev Error + Write-LogMessage -API 'CIPPDbItem' -tenant $TenantFilter -message "Failed to add items of type $Type : $($_.Exception.Message)" -sev Error -LogData (Get-CippException -Exception $_) throw } } diff --git a/Modules/CIPPCore/Public/Add-CippTestResult.ps1 b/Modules/CIPPCore/Public/Add-CippTestResult.ps1 index a4bee90dae78..37007ff93508 100644 --- a/Modules/CIPPCore/Public/Add-CippTestResult.ps1 +++ b/Modules/CIPPCore/Public/Add-CippTestResult.ps1 @@ -48,7 +48,7 @@ function Add-CippTestResult { [string]$TestId, [Parameter(Mandatory = $false)] - [string]$testType = 'Identity', + [string]$TestType = 'Identity', [Parameter(Mandatory = $true)] [string]$Status, diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Mailbox Permissions/Push-StoreMailboxPermissions.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Mailbox Permissions/Push-StoreMailboxPermissions.ps1 index 911745c1b06b..c7b22a576847 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Mailbox Permissions/Push-StoreMailboxPermissions.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Mailbox Permissions/Push-StoreMailboxPermissions.ps1 @@ -44,15 +44,21 @@ function Push-StoreMailboxPermissions { # Results are grouped by cmdlet name due to ReturnWithCommand if ($ActualResult['Get-MailboxPermission']) { Write-Information "Adding $($ActualResult['Get-MailboxPermission'].Count) mailbox permissions" - $AllMailboxPermissions.AddRange($ActualResult['Get-MailboxPermission']) + foreach ($perm in $ActualResult['Get-MailboxPermission']) { + $AllMailboxPermissions.Add($perm) + } } if ($ActualResult['Get-RecipientPermission']) { Write-Information "Adding $($ActualResult['Get-RecipientPermission'].Count) recipient permissions" - $AllRecipientPermissions.AddRange($ActualResult['Get-RecipientPermission']) + foreach ($perm in $ActualResult['Get-RecipientPermission']) { + $AllRecipientPermissions.Add($perm) + } } if ($ActualResult['Get-MailboxFolderPermission']) { Write-Information "Adding $($ActualResult['Get-MailboxFolderPermission'].Count) calendar permissions" - $AllCalendarPermissions.AddRange($ActualResult['Get-MailboxFolderPermission']) + foreach ($perm in $ActualResult['Get-MailboxFolderPermission']) { + $AllCalendarPermissions.Add($perm) + } } } else { Write-Information "Skipping non-hashtable result: $($ActualResult.GetType().Name)" @@ -61,30 +67,47 @@ function Push-StoreMailboxPermissions { # Combine all permissions (mailbox and recipient) into a single collection $AllPermissions = [System.Collections.Generic.List[object]]::new() - $AllPermissions.AddRange($AllMailboxPermissions) - $AllPermissions.AddRange($AllRecipientPermissions) + foreach ($perm in $AllMailboxPermissions) { + $AllPermissions.Add($perm) + } + foreach ($perm in $AllRecipientPermissions) { + $AllPermissions.Add($perm) + } Write-Information "Aggregated $($AllPermissions.Count) total permissions ($($AllMailboxPermissions.Count) mailbox + $($AllRecipientPermissions.Count) recipient)" Write-Information "Aggregated $($AllCalendarPermissions.Count) calendar permissions" # Store all permissions together as MailboxPermissions if ($AllPermissions.Count -gt 0) { - Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'MailboxPermissions' -Data $AllPermissions - Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'MailboxPermissions' -Data $AllPermissions -Count + Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'MailboxPermissions' -Data $AllPermissions.ToArray() + Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'MailboxPermissions' -Data @{ Count = $AllPermissions.Count } -Count Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message "Cached $($AllPermissions.Count) mailbox permission records" -sev Info } else { Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message 'No mailbox permissions found to cache' -sev Info } + # Clear to free memory before processing calendar permissions + $AllMailboxPermissions.Clear() + $AllRecipientPermissions.Clear() + $AllPermissions.Clear() + $AllMailboxPermissions = $null + $AllRecipientPermissions = $null + $AllPermissions = $null + # Store calendar permissions separately if ($AllCalendarPermissions.Count -gt 0) { - Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'CalendarPermissions' -Data $AllCalendarPermissions - Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'CalendarPermissions' -Data $AllCalendarPermissions -Count + Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'CalendarPermissions' -Data $AllCalendarPermissions.ToArray() + Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'CalendarPermissions' -Data @{ Count = $AllCalendarPermissions.Count } -Count Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message "Cached $($AllCalendarPermissions.Count) calendar permission records" -sev Info } else { Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message 'No calendar permissions found to cache' -sev Info } + # Final cleanup + $AllCalendarPermissions.Clear() + $AllCalendarPermissions = $null + [System.GC]::Collect() + return } catch { diff --git a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-CIPPDBCacheData.ps1 b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-CIPPDBCacheData.ps1 index 69c88b742398..dca6a6e87de8 100644 --- a/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-CIPPDBCacheData.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Push-CIPPDBCacheData.ps1 @@ -99,6 +99,7 @@ function Push-CIPPDBCacheData { 'ExoPresetSecurityPolicy' 'ExoTenantAllowBlockList' 'Mailboxes' + 'CASMailboxes' 'MailboxUsage' 'OneDriveUsage' ) @@ -178,7 +179,6 @@ function Push-CIPPDBCacheData { OrchestratorName = "CIPPDBCacheTenant_$TenantFilter" Batch = @($Batch) SkipLog = $true - DurableMode = 'Sequence' } if ($Item.TestRun -eq $true) { diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListMailboxCAS.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListMailboxCAS.ps1 index e90ed122fc89..2e66a472ddab 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListMailboxCAS.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Email-Exchange/Reports/Invoke-ListMailboxCAS.ps1 @@ -1,4 +1,4 @@ -Function Invoke-ListMailboxCAS { +function Invoke-ListMailboxCAS { <# .FUNCTIONALITY Entrypoint @@ -10,7 +10,7 @@ Function Invoke-ListMailboxCAS { # Interact with query parameters or the body of the request. $TenantFilter = $Request.Query.TenantFilter try { - $GraphRequest = New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($tenantfilter)/CasMailbox" -Tenantid $tenantfilter -scope ExchangeOnline | Select-Object @{ Name = 'displayName'; Expression = { $_.'DisplayName' } }, + $GraphRequest = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-CasMailbox' | Select-Object @{ Name = 'displayName'; Expression = { $_.'DisplayName' } }, @{ Name = 'primarySmtpAddress'; Expression = { $_.'PrimarySMTPAddress' } }, @{ Name = 'ecpenabled'; Expression = { $_.'ECPEnabled' } }, @{ Name = 'owaenabled'; Expression = { $_.'OWAEnabled' } }, diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Invoke-ListAvailableTests.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Invoke-ListAvailableTests.ps1 index ceee5d026d31..15c26f800b8f 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Invoke-ListAvailableTests.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Invoke-ListAvailableTests.ps1 @@ -1,7 +1,7 @@ function Invoke-ListAvailableTests { <# .FUNCTIONALITY - Entrypoint + Entrypoint,AnyTenant .ROLE CIPP.Dashboard.Read #> diff --git a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Invoke-ListTestReports.ps1 b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Invoke-ListTestReports.ps1 index eae3538134ce..a0d0f4ee5869 100644 --- a/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Invoke-ListTestReports.ps1 +++ b/Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Invoke-ListTestReports.ps1 @@ -4,7 +4,7 @@ function Invoke-ListTestReports { Lists all available test reports from JSON files and database .FUNCTIONALITY - Entrypoint + Entrypoint,AnyTenant .ROLE Tenant.Reports.Read diff --git a/Modules/CIPPCore/Public/Get-CippDbRoleMembers.ps1 b/Modules/CIPPCore/Public/Get-CippDbRoleMembers.ps1 index 907917fa69d7..d51612448da5 100644 --- a/Modules/CIPPCore/Public/Get-CippDbRoleMembers.ps1 +++ b/Modules/CIPPCore/Public/Get-CippDbRoleMembers.ps1 @@ -10,6 +10,7 @@ function Get-CippDbRoleMembers { $RoleAssignments = New-CIPPDbRequest -TenantFilter $TenantFilter -Type 'RoleAssignmentScheduleInstances' $RoleEligibilities = New-CIPPDbRequest -TenantFilter $TenantFilter -Type 'RoleEligibilitySchedules' + $DirectRoleAssignments = New-CIPPDbRequest -TenantFilter $TenantFilter -Type 'Roles' | Where-Object { $_.roleTemplateId -eq $RoleTemplateId } | Select-Object -ExpandProperty members $ActiveMembers = $RoleAssignments | Where-Object { $_.roleDefinitionId -eq $RoleTemplateId -and $_.assignmentType -eq 'Assigned' @@ -45,5 +46,18 @@ function Get-CippDbRoleMembers { } } + foreach ($member in $DirectRoleAssignments) { + if ($AllMembers.id -notcontains $member.id) { + $memberObj = [PSCustomObject]@{ + id = $member.id + displayName = $member.displayName + userPrincipalName = $member.userPrincipalName + '@odata.type' = $member.'@odata.type' + AssignmentType = 'Direct' + } + $AllMembers.Add($memberObj) + } + } + return $AllMembers } diff --git a/Modules/CIPPCore/Public/Set-CIPPDBCacheApps.ps1 b/Modules/CIPPCore/Public/Set-CIPPDBCacheApps.ps1 index 22200d76dbf3..a0f1c667be2f 100644 --- a/Modules/CIPPCore/Public/Set-CIPPDBCacheApps.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPDBCacheApps.ps1 @@ -16,6 +16,7 @@ function Set-CIPPDBCacheApps { Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message 'Caching applications' -sev Debug $Apps = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/applications?$top=999&expand=owners' -tenantid $TenantFilter + if (!$Apps) { $Apps = @() } Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'Apps' -Data $Apps Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'Apps' -Data $Apps -Count $Apps = $null diff --git a/Modules/CIPPCore/Public/Set-CIPPDBCacheCASMailboxes.ps1 b/Modules/CIPPCore/Public/Set-CIPPDBCacheCASMailboxes.ps1 new file mode 100644 index 000000000000..283b056f9ba6 --- /dev/null +++ b/Modules/CIPPCore/Public/Set-CIPPDBCacheCASMailboxes.ps1 @@ -0,0 +1,38 @@ +function Set-CIPPDBCacheCASMailboxes { + <# + .SYNOPSIS + Caches all CAS mailboxes for a tenant + + .PARAMETER TenantFilter + The tenant to cache CAS mailboxes for + #> + [CmdletBinding()] + param( + [Parameter(Mandatory = $true)] + [string]$TenantFilter + ) + + try { + Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message 'Caching CAS mailboxes' -sev Debug + + # Use Generic List for better memory efficiency with large datasets + $CASMailboxList = [System.Collections.Generic.List[PSObject]]::new() + $CASMailboxesResponse = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-CasMailbox' + foreach ($Mailbox in $CASMailboxesResponse) { + $CASMailboxList.Add($Mailbox) + } + + Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'CASMailbox' -Data $CASMailboxList.ToArray() + Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'CASMailbox' -Data @{ Count = $CASMailboxList.Count } -Count + + $CASMailboxesResponse = $null + $CASMailboxList.Clear() + $CASMailboxList = $null + [System.GC]::Collect() + + Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message 'Cached CAS mailboxes successfully' -sev Debug + + } catch { + Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message "Failed to cache CAS mailboxes: $($_.Exception.Message)" -sev Error + } +} diff --git a/Modules/CIPPCore/Public/Set-CIPPDBCacheDevices.ps1 b/Modules/CIPPCore/Public/Set-CIPPDBCacheDevices.ps1 index 2953483d47a7..63996ee51294 100644 --- a/Modules/CIPPCore/Public/Set-CIPPDBCacheDevices.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPDBCacheDevices.ps1 @@ -16,6 +16,7 @@ function Set-CIPPDBCacheDevices { Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message 'Caching Azure AD devices' -sev Debug $Devices = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/devices?$top=999&$select=id,displayName,operatingSystem,operatingSystemVersion,trustType,accountEnabled,approximateLastSignInDateTime' -tenantid $TenantFilter + if (!$Devices) { $Devices = @() } Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'Devices' -Data $Devices Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'Devices' -Data $Devices -Count $Devices = $null diff --git a/Modules/CIPPCore/Public/Set-CIPPDBCacheGuests.ps1 b/Modules/CIPPCore/Public/Set-CIPPDBCacheGuests.ps1 index 0fc9a324ef6a..36abaabef11d 100644 --- a/Modules/CIPPCore/Public/Set-CIPPDBCacheGuests.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPDBCacheGuests.ps1 @@ -16,6 +16,7 @@ function Set-CIPPDBCacheGuests { Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message 'Caching guest users' -sev Debug $Guests = New-GraphGetRequest -uri "https://graph.microsoft.com/beta/users?`$filter=userType eq 'Guest'&`$expand=sponsors&`$top=999" -tenantid $TenantFilter + if (!$Guests) { $Guests = @() } Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'Guests' -Data $Guests Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'Guests' -Data $Guests -Count $Guests = $null diff --git a/Modules/CIPPCore/Public/Set-CIPPDBCacheMailboxes.ps1 b/Modules/CIPPCore/Public/Set-CIPPDBCacheMailboxes.ps1 index 350d97a32af7..8c78abbdab4b 100644 --- a/Modules/CIPPCore/Public/Set-CIPPDBCacheMailboxes.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPDBCacheMailboxes.ps1 @@ -23,33 +23,36 @@ function Set-CIPPDBCacheMailboxes { cmdParams = @{} Select = $Select } - $Mailboxes = (New-ExoRequest @ExoRequest) | Select-Object id, ExchangeGuid, ArchiveGuid, WhenSoftDeleted, - @{ Name = 'UPN'; Expression = { $_.'UserPrincipalName' } }, - @{ Name = 'displayName'; Expression = { $_.'DisplayName' } }, - @{ Name = 'primarySmtpAddress'; Expression = { $_.'PrimarySMTPAddress' } }, - @{ Name = 'recipientType'; Expression = { $_.'RecipientType' } }, - @{ Name = 'recipientTypeDetails'; Expression = { $_.'RecipientTypeDetails' } }, - @{ Name = 'AdditionalEmailAddresses'; Expression = { ($_.'EmailAddresses' | Where-Object { $_ -clike 'smtp:*' }).Replace('smtp:', '') -join ', ' } }, - @{ Name = 'ForwardingSmtpAddress'; Expression = { $_.'ForwardingSmtpAddress' -replace 'smtp:', '' } }, - @{ Name = 'InternalForwardingAddress'; Expression = { $_.'ForwardingAddress' } }, - DeliverToMailboxAndForward, - HiddenFromAddressListsEnabled, - ExternalDirectoryObjectId, - MessageCopyForSendOnBehalfEnabled, - MessageCopyForSentAsEnabled + # Use Generic List for better memory efficiency with large datasets + $MailboxList = [System.Collections.Generic.List[PSObject]]::new() + $RawMailboxes = New-ExoRequest @ExoRequest + + foreach ($Mailbox in $RawMailboxes) { + $MailboxList.Add(($Mailbox | Select-Object id, ExchangeGuid, ArchiveGuid, WhenSoftDeleted, + @{ Name = 'UPN'; Expression = { $_.'UserPrincipalName' } }, + @{ Name = 'displayName'; Expression = { $_.'DisplayName' } }, + @{ Name = 'primarySmtpAddress'; Expression = { $_.'PrimarySMTPAddress' } }, + @{ Name = 'recipientType'; Expression = { $_.'RecipientType' } }, + @{ Name = 'recipientTypeDetails'; Expression = { $_.'RecipientTypeDetails' } }, + @{ Name = 'AdditionalEmailAddresses'; Expression = { ($_.'EmailAddresses' | Where-Object { $_ -clike 'smtp:*' }).Replace('smtp:', '') -join ', ' } }, + @{ Name = 'ForwardingSmtpAddress'; Expression = { $_.'ForwardingSmtpAddress' -replace 'smtp:', '' } }, + @{ Name = 'InternalForwardingAddress'; Expression = { $_.'ForwardingAddress' } }, + DeliverToMailboxAndForward, + HiddenFromAddressListsEnabled, + ExternalDirectoryObjectId, + MessageCopyForSendOnBehalfEnabled, + MessageCopyForSentAsEnabled)) + } + + $Mailboxes = $MailboxList.ToArray() + $RawMailboxes = $null + $MailboxList.Clear() + $MailboxList = $null Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'Mailboxes' -Data $Mailboxes Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'Mailboxes' -Data $Mailboxes -Count Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message "Cached $($Mailboxes.Count) mailboxes successfully" -sev Debug - # Get CAS mailboxes - Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message 'Caching CAS mailboxes' -sev Debug - $CASMailboxes = New-GraphGetRequest -uri "https://outlook.office365.com/adminapi/beta/$($TenantFilter)/CasMailbox" -Tenantid $TenantFilter -scope 'ExchangeOnline' -noPagination $true - Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'CASMailbox' -Data $CASMailboxes - Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'CASMailbox' -Data $CASMailboxes -Count - $CASMailboxes = $null - Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message 'Cached CAS mailboxes successfully' -sev Debug - # Start orchestrator to cache mailbox permissions in batches $MailboxCount = ($Mailboxes | Measure-Object).Count if ($MailboxCount -gt 0) { @@ -94,7 +97,6 @@ function Set-CIPPDBCacheMailboxes { $InputObject = [PSCustomObject]@{ Batch = @($Batches) OrchestratorName = "MailboxPermissions_$TenantFilter" - DurableMode = 'Sequence' PostExecution = @{ FunctionName = 'StoreMailboxPermissions' Parameters = @{ @@ -108,6 +110,10 @@ function Set-CIPPDBCacheMailboxes { Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message 'No mailboxes found to cache permissions for' -sev Debug } + # Clear mailbox data to free memory + $Mailboxes = $null + [System.GC]::Collect() + } catch { Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message "Failed to cache mailboxes: $($_.Exception.Message)" -sev Error } diff --git a/Modules/CIPPCore/Public/Set-CIPPDBCacheSettings.ps1 b/Modules/CIPPCore/Public/Set-CIPPDBCacheSettings.ps1 index 08aee0f383a7..76c682ba3adb 100644 --- a/Modules/CIPPCore/Public/Set-CIPPDBCacheSettings.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPDBCacheSettings.ps1 @@ -16,12 +16,12 @@ function Set-CIPPDBCacheSettings { Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message 'Caching directory settings' -sev Debug $Settings = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/settings?$top=999' -tenantid $TenantFilter + if(!$Settings){ $Settings = @()} Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'Settings' -Data $Settings $Settings = $null Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message 'Cached directory settings successfully' -sev Debug } catch { - Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter ` - -message "Failed to cache directory settings: $($_.Exception.Message)" -sev Error + Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message "Failed to cache directory settings: $($_.Exception.Message)" -sev Error } } diff --git a/Modules/CIPPCore/Public/Set-CIPPDBCacheUsers.ps1 b/Modules/CIPPCore/Public/Set-CIPPDBCacheUsers.ps1 index a1ffd11ef337..3355fbdd9f33 100644 --- a/Modules/CIPPCore/Public/Set-CIPPDBCacheUsers.ps1 +++ b/Modules/CIPPCore/Public/Set-CIPPDBCacheUsers.ps1 @@ -15,13 +15,23 @@ function Set-CIPPDBCacheUsers { try { Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message 'Caching users' -sev Debug - $Users = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/users?$top=999' -tenantid $TenantFilter - Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'Users' -Data $Users - Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'Users' -Data $Users -Count + $Users = [System.Collections.Generic.List[PSObject]]::new() + $UsersResponse = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/users?$top=999' -tenantid $TenantFilter + foreach ($User in $UsersResponse) { + $Users.Add($User) + } + + Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'Users' -Data $Users.ToArray() + Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'Users' -Data @{ Count = $Users.Count } -Count + + $Users.Clear() $Users = $null + $UsersResponse = $null + [System.GC]::Collect() + Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message 'Cached users successfully' -sev Debug } catch { - Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message "Failed to cache users: $($_.Exception.Message)" -sev Error + Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message "Failed to cache users: $($_.Exception.Message)" -sev Error -LogData (Get-CippException -Exception $_) } } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeployMailContact.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeployMailContact.ps1 index 4ee810e1f85a..8dc3df011a96 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeployMailContact.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDeployMailContact.ps1 @@ -103,8 +103,19 @@ function Invoke-CIPPStandardDeployMailContact { # Report if ($Settings.report -eq $true) { $ReportData = $ContactData.Clone() + $ContactData = @{ + DisplayName = $Settings.DisplayName + ExternalEmailAddress = $Settings.ExternalEmailAddress + FirstName = $Settings.FirstName + LastName = $Settings.LastName + } $CurrentValue = $ExistingContact | Select-Object DisplayName, ExternalEmailAddress, FirstName, LastName - $ReportData.Exists = [bool]$ExistingContact + $currentValue = @{ + DisplayName = $ExistingContact.displayName + ExternalEmailAddress = ($ExistingContact.ExternalEmailAddress -replace 'SMTP:', '') + FirstName = $ExistingContact.firstName + LastName = $ExistingContact.lastName + } Add-CIPPBPAField -FieldName 'DeployMailContact' -FieldValue $ReportData -StoreAs json -Tenant $Tenant Set-CIPPStandardsCompareField -FieldName 'standards.DeployMailContact' -CurrentValue $CurrentValue -ExpectedValue $ReportData -Tenant $Tenant } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 index adefbeb157ca..d648b2d8589b 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardDisableBasicAuthSMTP.ps1 @@ -45,7 +45,7 @@ function Invoke-CIPPStandardDisableBasicAuthSMTP { try { $CurrentInfo = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-TransportConfig' - $SMTPusers = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-CASMailbox' -cmdParams @{ ResultSize = 'Unlimited' } | + $SMTPusers = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-CASMailbox' | Where-Object { ($_.SmtpClientAuthenticationDisabled -eq $false) } } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableAppConsentRequests.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableAppConsentRequests.ps1 index 21a52e52dda7..5fbbb936a4c1 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableAppConsentRequests.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardEnableAppConsentRequests.ps1 @@ -121,7 +121,7 @@ function Invoke-CIPPStandardEnableAppConsentRequests { if ($Settings.report -eq $true) { $CurrentValue = [PSCustomObject]@{ - EnableAppConsentRequests = $CurrentInfo.isEnabled + EnableAppConsentRequests = [bool]$CurrentInfo.isEnabled ReviewerCount = $CurrentInfo.reviewers.count } $ExpectedValue = [PSCustomObject]@{ diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 index 0024b7d7a5ee..a7539fe40fd1 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardGroupTemplate.ps1 @@ -242,12 +242,10 @@ function Invoke-CIPPStandardGroupTemplate { } $CurrentValue = @{ - ExistingGroups = $existingGroups.displayName - MissingGroups = @($MissingGroups) + MissingGroups = $MissingGroups ? @($MissingGroups) : @() } $ExpectedValue = @{ - ExistingGroups = $GroupTemplates.displayName - MissingGroups = @() + MissingGroups = @() } Set-CIPPStandardsCompareField -FieldName 'standards.GroupTemplate' -CurrentValue $CurrentValue -ExpectedValue $ExpectedValue -TenantFilter $Tenant diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMDMScope.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMDMScope.ps1 index b0e67306cc6a..e01b2616abe1 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMDMScope.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardMDMScope.ps1 @@ -144,18 +144,12 @@ function Invoke-CIPPStandardMDMScope { if ($Settings.report -eq $true) { $CurrentValue = @{ - termsOfUseUrl = $CurrentInfo.termsOfUseUrl - discoveryUrl = $CurrentInfo.discoveryUrl - complianceUrl = $CurrentInfo.complianceUrl - appliesTo = $CurrentInfo.appliesTo - customGroup = $CurrentInfo.includedGroups.displayName + appliesTo = $CurrentInfo.appliesTo + customGroup = $CurrentInfo.includedGroups.displayName ?? '' } $ExpectedValue = @{ - termsOfUseUrl = $Settings.termsOfUseUrl - discoveryUrl = $Settings.discoveryUrl - complianceUrl = $Settings.complianceUrl - appliesTo = $Settings.appliesTo - customGroup = $Settings.customGroup + appliesTo = $Settings.appliesTo + customGroup = $Settings.customGroup ?? '' } Set-CIPPStandardsCompareField -FieldName 'standards.MDMScope' -CurrentValue $CurrentValue -ExpectedValue $ExpectedValue -TenantFilter $Tenant Add-CIPPBPAField -FieldName 'MDMScope' -FieldValue $StateIsCorrect -StoreAs bool -Tenant $tenant diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 index d4eee69db7a6..adc90a5a342d 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardOauthConsent.ps1 @@ -104,7 +104,7 @@ function Invoke-CIPPStandardOauthConsent { permissionGrantPolicyIdsAssignedToDefaultUserRole = $State.permissionGrantPolicyIdsAssignedToDefaultUserRole } $ExpectedValue = @{ - permissionGrantPolicyIdsAssignedToDefaultUserRole = @('managePermissionGrantsForSelf.cipp-consent-policy') + permissionGrantPolicyIdsAssignedToDefaultUserRole = @('ManagePermissionGrantsForSelf.cipp-consent-policy') } Set-CIPPStandardsCompareField -FieldName 'standards.OauthConsent' -CurrentValue $CurrentValue -ExpectedValue $ExpectedValue -Tenant $tenant } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 index 1627aaceaa5d..f23855cbbeee 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSafeAttachmentPolicy.ps1 @@ -76,8 +76,8 @@ function Invoke-CIPPStandardSafeAttachmentPolicy { try { $CurrentState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-SafeAttachmentPolicy' | - Where-Object -Property Name -EQ $PolicyName | - Select-Object Name, Enable, Action, QuarantineTag, Redirect, RedirectAddress + Where-Object -Property Name -EQ $PolicyName | + Select-Object Name, Enable, Action, QuarantineTag, Redirect, RedirectAddress } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Could not get the SafeAttachmentPolicy state for $Tenant. Error: $ErrorMessage" -Sev Error @@ -94,8 +94,8 @@ function Invoke-CIPPStandardSafeAttachmentPolicy { $AcceptedDomains = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-AcceptedDomain' $RuleState = New-ExoRequest -tenantid $Tenant -cmdlet 'Get-SafeAttachmentRule' | - Where-Object -Property Name -EQ $RuleName | - Select-Object Name, SafeAttachmentPolicy, Priority, RecipientDomainIs + Where-Object -Property Name -EQ $RuleName | + Select-Object Name, SafeAttachmentPolicy, Priority, RecipientDomainIs $RuleStateIsCorrect = ($RuleState.Name -eq $RuleName) -and ($RuleState.SafeAttachmentPolicy -eq $PolicyName) -and @@ -186,13 +186,13 @@ function Invoke-CIPPStandardSafeAttachmentPolicy { redirectAddress = $CurrentState.RedirectAddress } - $ExpectedValue = @{ + $ExpectedValue = [pscustomobject]@{ name = $PolicyName enable = $true action = $Settings.SafeAttachmentAction quarantineTag = $Settings.QuarantineTag redirect = $Settings.Redirect - redirectAddress = $Settings.RedirectAddress + redirectAddress = "$($Settings.RedirectAddress)" } Set-CIPPStandardsCompareField -FieldName 'standards.SafeAttachmentPolicy' -CurrentValue $CurrentValue -ExpectedValue $ExpectedValue -Tenant $Tenant } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 index 5a9fd298f25c..32a9cb7f22b1 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpamFilterPolicy.ps1 @@ -64,8 +64,8 @@ function Invoke-CIPPStandardSpamFilterPolicy { try { $CurrentState = New-ExoRequest -TenantId $Tenant -cmdlet 'Get-HostedContentFilterPolicy' | - Where-Object -Property Name -EQ $PolicyName | - Select-Object -Property * + Where-Object -Property Name -EQ $PolicyName | + Select-Object -Property * } catch { $ErrorMessage = Get-NormalizedError -Message $_.Exception.Message Write-LogMessage -API 'Standards' -Tenant $Tenant -Message "Could not get the SpamFilterPolicy state for $Tenant. Error: $ErrorMessage" -Sev Error @@ -136,8 +136,8 @@ function Invoke-CIPPStandardSpamFilterPolicy { $AcceptedDomains = New-ExoRequest -TenantId $Tenant -cmdlet 'Get-AcceptedDomain' $RuleState = New-ExoRequest -TenantId $Tenant -cmdlet 'Get-HostedContentFilterRule' | - Where-Object -Property Name -EQ $PolicyName | - Select-Object -Property * + Where-Object -Property Name -EQ $PolicyName | + Select-Object -Property * $RuleStateIsCorrect = ($RuleState.Name -eq $PolicyName) -and ($RuleState.HostedContentFilterPolicy -eq $PolicyName) -and @@ -284,7 +284,7 @@ function Invoke-CIPPStandardSpamFilterPolicy { RegionBlockList = $CurrentState.RegionBlockList AllowedSenderDomains = $CurrentState.AllowedSenderDomains } - $ExpectedValue = @{ + $ExpectedValue = [pscustomobject]@{ Name = $PolicyName SpamAction = $SpamAction SpamQuarantineTag = $SpamQuarantineTag @@ -305,10 +305,10 @@ function Invoke-CIPPStandardSpamFilterPolicy { MarkAsSpamWebBugsInHtml = $MarkAsSpamWebBugsInHtml MarkAsSpamSensitiveWordList = $MarkAsSpamSensitiveWordList EnableLanguageBlockList = $Settings.EnableLanguageBlockList - LanguageBlockList = if ($Settings.EnableLanguageBlockList -eq $true) { $Settings.LanguageBlockList.value } else { @() } + LanguageBlockList = $Settings.EnableLanguageBlockList ? @($Settings.EnableLanguageBlockList) : @() EnableRegionBlockList = $Settings.EnableRegionBlockList - RegionBlockList = if ($Settings.EnableRegionBlockList -eq $true) { $Settings.RegionBlockList.value } else { @() } - AllowedSenderDomains = $Settings.AllowedSenderDomains.value ?? @() + RegionBlockList = $Settings.RegionBlockList.value ? @($Settings.RegionBlockList.value) : @() + AllowedSenderDomains = $Settings.AllowedSenderDomains.value ? @($Settings.AllowedSenderDomains.value) : @() } Set-CIPPStandardsCompareField -FieldName 'standards.SpamFilterPolicy' -CurrentValue $CurrentValue -ExpectedValue $ExpectedValue -Tenant $Tenant } diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 index c07e9e96fb3f..fc1989311104 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardSpoofWarn.ps1 @@ -133,13 +133,13 @@ function Invoke-CIPPStandardSpoofWarn { Add-CIPPBPAField -FieldName 'SpoofingWarnings' -FieldValue $CurrentInfo.Enabled -StoreAs bool -Tenant $Tenant $CurrentValue = @{ - Enabled = $CurrentInfo.Enabled - AllowList = $CurrentInfo.AllowList + Enabled = $CurrentInfo.Enabled + AllowList = $CurrentInfo.AllowList IsCompliant = $CurrentInfo.Enabled -eq $IsEnabled -and $AllowListCorrect } $ExpectedValue = @{ - Enabled = $IsEnabled - AllowList = $Settings.AllowListAdd.value ?? $Settings.AllowListAdd + Enabled = $IsEnabled + AllowList = $Settings.AllowListAdd.value ? @($Settings.AllowListAdd.value) : @() IsCompliant = $true } Set-CIPPStandardsCompareField -FieldName 'standards.SpoofWarn' -CurrentValue $CurrentValue -ExpectedValue $ExpectedValue -Tenant $Tenant diff --git a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 index f2867357c2f8..d0653e4d2c8f 100644 --- a/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 +++ b/Modules/CIPPCore/Public/Standards/Invoke-CIPPStandardUserSubmissions.ps1 @@ -225,9 +225,9 @@ function Invoke-CIPPStandardUserSubmissions { ReportJunkToCustomizedAddress = if ([string]::IsNullOrWhiteSpace($Email)) { $false } else { $true } ReportNotJunkToCustomizedAddress = if ([string]::IsNullOrWhiteSpace($Email)) { $false } else { $true } ReportPhishToCustomizedAddress = if ([string]::IsNullOrWhiteSpace($Email)) { $false } else { $true } - ReportJunkAddresses = if ([string]::IsNullOrWhiteSpace($Email)) { $null } else { $Email } - ReportNotJunkAddresses = if ([string]::IsNullOrWhiteSpace($Email)) { $null } else { $Email } - ReportPhishAddresses = if ([string]::IsNullOrWhiteSpace($Email)) { $null } else { $Email } + ReportJunkAddresses = if ([string]::IsNullOrWhiteSpace($Email)) { $null } else { @($Email) } + ReportNotJunkAddresses = if ([string]::IsNullOrWhiteSpace($Email)) { $null } else { @($Email) } + ReportPhishAddresses = if ([string]::IsNullOrWhiteSpace($Email)) { $null } else { @($Email) } RuleState = if ([string]::IsNullOrWhiteSpace($Email)) { @{ State = 'Disabled' @@ -236,7 +236,7 @@ function Invoke-CIPPStandardUserSubmissions { } else { @{ State = 'Enabled' - SentTo = $Email + SentTo = @($Email) } } } diff --git a/Modules/CIPPCore/Public/TenantGroups/Get-TenantGroups.ps1 b/Modules/CIPPCore/Public/TenantGroups/Get-TenantGroups.ps1 index 0b15f3f62402..74a0f4a65ef6 100644 --- a/Modules/CIPPCore/Public/TenantGroups/Get-TenantGroups.ps1 +++ b/Modules/CIPPCore/Public/TenantGroups/Get-TenantGroups.ps1 @@ -159,6 +159,7 @@ function Get-TenantGroups { if ($GroupMembers) { foreach ($Member in $GroupMembers) { # Use indexed lookup instead of Where-Object + if (!$Member.customerId) { continue } $Tenant = $TenantByCustomerId[$Member.customerId] if ($Tenant) { $MembersList.Add(@{ diff --git a/Modules/CIPPCore/Public/Tests/ORCA/Identity/Invoke-CippTestORCA119.ps1 b/Modules/CIPPCore/Public/Tests/ORCA/Identity/Invoke-CippTestORCA119.ps1 index 8f8cbbca6ece..c751816a320d 100644 --- a/Modules/CIPPCore/Public/Tests/ORCA/Identity/Invoke-CippTestORCA119.ps1 +++ b/Modules/CIPPCore/Public/Tests/ORCA/Identity/Invoke-CippTestORCA119.ps1 @@ -6,7 +6,7 @@ function Invoke-CippTestORCA119 { param($Tenant) try { - $Policies = New-CIPPDbRequest -TenantFilter $Tenant -TestType 'ExoAntiPhishPolicies' + $Policies = New-CIPPDbRequest -TenantFilter $Tenant -Type 'ExoAntiPhishPolicies' if (-not $Policies) { Add-CippTestResult -TenantFilter $Tenant -TestId 'ORCA119' -TestType 'Identity' -Status 'Skipped' -ResultMarkdown 'No data found in database. This may be due to missing required licenses or data collection not yet completed.' -Risk 'Medium' -Name 'Similar Domains Safety Tips is enabled' -UserImpact 'Low' -ImplementationEffort 'Low' -Category 'Anti-Phish' diff --git a/Modules/CIPPCore/Public/Tests/ZTNA/Identity/Invoke-CippTestZTNA21836.ps1 b/Modules/CIPPCore/Public/Tests/ZTNA/Identity/Invoke-CippTestZTNA21836.ps1 index e6129bd4a135..8253e3737d3d 100644 --- a/Modules/CIPPCore/Public/Tests/ZTNA/Identity/Invoke-CippTestZTNA21836.ps1 +++ b/Modules/CIPPCore/Public/Tests/ZTNA/Identity/Invoke-CippTestZTNA21836.ps1 @@ -20,7 +20,7 @@ function Invoke-CippTestZTNA21836 { $WorkloadIdentitiesWithPrivilegedRoles = [System.Collections.Generic.List[object]]::new() foreach ($Role in $PrivilegedRoles) { - $RoleMembers = Get-CippDbRoleMembers -TenantFilter $Tenant -RoleId $Role.id + $RoleMembers = Get-CippDbRoleMembers -TenantFilter $Tenant -RoleTemplateId $Role.id foreach ($Member in $RoleMembers) { if ($Member.'@odata.type' -eq '#microsoft.graph.servicePrincipal') { diff --git a/host.json b/host.json index fcd66850583e..03a1061b6423 100644 --- a/host.json +++ b/host.json @@ -16,7 +16,7 @@ "distributedTracingEnabled": false, "version": "None" }, - "defaultVersion": "10.0.3", + "defaultVersion": "10.0.4", "versionMatchStrategy": "Strict", "versionFailureStrategy": "Fail" } diff --git a/version_latest.txt b/version_latest.txt index 6a7144d3047f..6b48f258c7a4 100644 --- a/version_latest.txt +++ b/version_latest.txt @@ -1 +1 @@ -10.0.3 +10.0.4