Skip to content

Commit ccf8fe6

Browse files
authored
Merge pull request #981 from KelvinTegelaar/dev
[pull] dev from KelvinTegelaar:dev
2 parents 26ef3da + dd8952e commit ccf8fe6

7 files changed

Lines changed: 156 additions & 198 deletions

File tree

Modules/CIPPActivityTriggers/Public/Entrypoints/Activity Triggers/CIPPDBCache/Push-ExecCIPPDBCache.ps1

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,7 @@ function Push-ExecCIPPDBCache {
4444

4545
# Build the full function name
4646
$FullFunctionName = "Set-CIPPDBCache$Name"
47-
48-
# Cache the resolved command per process so back-to-back HTTP-driven refreshes
49-
# don't repeat the module command-table walk.
50-
if (-not $script:CIPPDBCacheFunctionLookup) {
51-
$script:CIPPDBCacheFunctionLookup = [System.Collections.Generic.Dictionary[string, object]]::new([System.StringComparer]::OrdinalIgnoreCase)
52-
Write-Information "[CacheInit] CIPPDBCacheFunctionLookup initialized in PID $PID"
53-
}
54-
if ($script:CIPPDBCacheFunctionLookup.ContainsKey($FullFunctionName)) {
55-
Write-Information "[CacheHit] CIPPDBCacheFunctionLookup PID=$PID Key=$FullFunctionName Size=$($script:CIPPDBCacheFunctionLookup.Count)"
56-
} else {
57-
Write-Information "[CacheMiss] CIPPDBCacheFunctionLookup PID=$PID Key=$FullFunctionName Size=$($script:CIPPDBCacheFunctionLookup.Count) - resolving via Get-Command"
58-
$script:CIPPDBCacheFunctionLookup[$FullFunctionName] = Get-Command -Name $FullFunctionName -ErrorAction SilentlyContinue
59-
}
60-
$Function = $script:CIPPDBCacheFunctionLookup[$FullFunctionName]
47+
$Function = Get-Command -Name $FullFunctionName -ErrorAction SilentlyContinue
6148
if (-not $Function) {
6249
throw "Function $FullFunctionName does not exist"
6350
}

Modules/CIPPActivityTriggers/Public/Entrypoints/Activity Triggers/Push-SchedulerCIPPNotifications.ps1

Lines changed: 89 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -17,84 +17,86 @@ function Push-SchedulerCIPPNotifications {
1717

1818
$severity = $Config.Severity -split ','
1919
if (!$severity) {
20-
$severity = [System.Collections.ArrayList]@('Info', 'Error', 'Warning', 'Critical', 'Alert')
20+
$severity = @('Info', 'Error', 'Warning', 'Critical', 'Alert')
2121
}
2222
Write-Information "Our Severity table is: $severity"
2323

24-
$Table = Get-CIPPTable
25-
$PartitionKey = Get-Date -UFormat '%Y%m%d'
26-
$Filter = "PartitionKey eq '{0}'" -f $PartitionKey
27-
$Currentlog = Get-CIPPAzDataTableEntity @Table -Filter $Filter | Where-Object {
28-
$_.API -in $Settings -and $_.sentAsAlert -ne $true -and $_.Severity -in $severity
29-
}
24+
$LogTable = Get-CIPPTable
3025
$StandardsTable = Get-CIPPTable -tablename CippStandardsAlerts
31-
$CurrentStandardsLogs = Get-CIPPAzDataTableEntity @StandardsTable -Filter $Filter | Where-Object {
32-
$_.sentAsAlert -ne $true
33-
}
34-
Write-Information "Alerts: $($Currentlog.count) found"
35-
Write-Information "Standards: $($CurrentStandardsLogs.count) found"
26+
$PartitionKey = Get-Date -UFormat '%Y%m%d'
27+
28+
# Server-side: sentAsAlert + severity (small fixed set). API is filtered client-side
29+
# because the API list is open-ended and OR-expanding it can exceed the OData filter limit.
30+
$sevOr = ($severity | ForEach-Object { "Severity eq '$($_ -replace "'", "''")'" }) -join ' or '
31+
$LogFilter = "PartitionKey eq '$PartitionKey' and sentAsAlert eq false and ($sevOr)"
32+
$StandardsFilter = "PartitionKey eq '$PartitionKey' and sentAsAlert eq false"
33+
34+
$Currentlog = @(Get-CIPPAzDataTableEntity @LogTable -Filter $LogFilter | Where-Object { $_.API -in $Settings })
35+
$CurrentStandardsLogs = @(Get-CIPPAzDataTableEntity @StandardsTable -Filter $StandardsFilter)
36+
37+
Write-Information "Alerts: $($Currentlog.Count) found"
38+
Write-Information "Standards: $($CurrentStandardsLogs.Count) found"
3639

3740
# Get the CIPP URL
3841
$CippConfigTable = Get-CippTable -tablename Config
3942
$CippConfig = Get-CIPPAzDataTableEntity @CippConfigTable -Filter "PartitionKey eq 'InstanceProperties' and RowKey eq 'CIPPURL'"
4043
$CIPPURL = 'https://{0}' -f $CippConfig.Value
4144

42-
#email try
45+
$LogsByTenant = @($Currentlog | Group-Object -Property Tenant)
46+
$StandardsByTenant = @($CurrentStandardsLogs | Group-Object -Property Tenant)
47+
48+
$MarkSent = {
49+
param($Entities, $TargetTable)
50+
if (-not $Entities -or $Entities.Count -eq 0) { return }
51+
$batch = [System.Collections.Generic.List[object]]::new()
52+
foreach ($e in $Entities) {
53+
if ($e.PSObject.Properties.Name -contains 'sentAsAlert') {
54+
$e.sentAsAlert = $true
55+
} else {
56+
$e | Add-Member -MemberType NoteProperty -Name sentAsAlert -Value $true -Force
57+
}
58+
$batch.Add($e)
59+
if ($batch.Count -ge 100) {
60+
Add-CIPPAzDataTableEntity @TargetTable -Entity $batch -Force
61+
$batch.Clear()
62+
}
63+
}
64+
if ($batch.Count -gt 0) {
65+
Add-CIPPAzDataTableEntity @TargetTable -Entity $batch -Force
66+
}
67+
}
68+
4369
try {
4470
if ($Config.email -like '*@*') {
45-
#Normal logs
46-
if ($Currentlog) {
71+
if ($Currentlog.Count -gt 0) {
4772
if ($config.onePerTenant) {
48-
foreach ($tenant in ($CurrentLog.Tenant | Sort-Object -Unique)) {
49-
$Data = ($CurrentLog | Select-Object Message, API, Tenant, Username, Severity | Where-Object -Property tenant -EQ $tenant)
50-
$Subject = "$($Tenant): CIPP Alert: Alerts found starting at $((Get-Date).AddMinutes(-15))"
73+
foreach ($g in $LogsByTenant) {
74+
$tenant = $g.Name
75+
$Data = $g.Group | Select-Object Message, API, Tenant, Username, Severity
76+
$Subject = "$($tenant): CIPP Alert: Alerts found starting at $((Get-Date).AddMinutes(-15))"
5177
$HTMLContent = New-CIPPAlertTemplate -Data $Data -Format 'html' -InputObject 'table' -CIPPURL $CIPPURL
5278
Send-CIPPAlert -Type 'email' -Title $Subject -HTMLContent $HTMLContent.htmlcontent -TenantFilter $tenant -APIName 'Alerts'
53-
$UpdateLogs = $CurrentLog | ForEach-Object {
54-
if ($_.PSObject.Properties.Name -contains 'sentAsAlert') {
55-
$_.sentAsAlert = $true
56-
} else {
57-
$_ | Add-Member -MemberType NoteProperty -Name sentAsAlert -Value $true -Force
58-
}
59-
$_
60-
}
61-
if ($UpdateLogs) {
62-
Add-CIPPAzDataTableEntity @Table -Entity $UpdateLogs -Force
63-
}
79+
& $MarkSent $g.Group $LogTable
80+
$Data = $null; $HTMLContent = $null
6481
}
6582
} else {
66-
$Data = ($CurrentLog | Select-Object Message, API, Tenant, Username, Severity)
83+
$Data = $CurrentLog | Select-Object Message, API, Tenant, Username, Severity
6784
$Subject = "CIPP Alert: Alerts found starting at $((Get-Date).AddMinutes(-15))"
6885
$HTMLContent = New-CIPPAlertTemplate -Data $Data -Format 'html' -InputObject 'table' -CIPPURL $CIPPURL
6986
Send-CIPPAlert -Type 'email' -Title $Subject -HTMLContent $HTMLContent.htmlcontent -TenantFilter 'AllTenants' -APIName 'Alerts'
70-
$UpdateLogs = $CurrentLog | ForEach-Object {
71-
if ($_.PSObject.Properties.Name -contains 'sentAsAlert') {
72-
$_.sentAsAlert = $true
73-
} else {
74-
$_ | Add-Member -MemberType NoteProperty -Name sentAsAlert -Value $true -Force
75-
}
76-
$_
77-
}
78-
if ($UpdateLogs) {
79-
Add-CIPPAzDataTableEntity @Table -Entity $UpdateLogs -Force
80-
}
87+
& $MarkSent $CurrentLog $LogTable
88+
$Data = $null; $HTMLContent = $null
8189
}
8290
}
83-
if ($CurrentStandardsLogs) {
84-
foreach ($tenant in ($CurrentStandardsLogs.Tenant | Sort-Object -Unique)) {
85-
$Data = ($CurrentStandardsLogs | Where-Object -Property tenant -EQ $tenant)
86-
$Subject = "$($Tenant): Standards are out of sync for $tenant"
91+
if ($CurrentStandardsLogs.Count -gt 0) {
92+
foreach ($g in $StandardsByTenant) {
93+
$tenant = $g.Name
94+
$Data = $g.Group
95+
$Subject = "$($tenant): Standards are out of sync for $tenant"
8796
$HTMLContent = New-CIPPAlertTemplate -Data $Data -Format 'html' -InputObject 'standards' -CIPPURL $CIPPURL
8897
Send-CIPPAlert -Type 'email' -Title $Subject -HTMLContent $HTMLContent.htmlcontent -TenantFilter $tenant -APIName 'Alerts'
89-
$updateStandards = $CurrentStandardsLogs | ForEach-Object {
90-
if ($_.PSObject.Properties.Name -contains 'sentAsAlert') {
91-
$_.sentAsAlert = $true
92-
} else {
93-
$_ | Add-Member -MemberType NoteProperty -Name sentAsAlert -Value $true -Force
94-
}
95-
$_
96-
}
97-
if ($updateStandards) { Add-CIPPAzDataTableEntity @StandardsTable -Entity $updateStandards -Force }
98+
& $MarkSent $g.Group $StandardsTable
99+
$Data = $null; $HTMLContent = $null
98100
}
99101
}
100102
}
@@ -104,67 +106,61 @@ function Push-SchedulerCIPPNotifications {
104106
}
105107

106108
try {
107-
Write-Information $($config | ConvertTo-Json)
108109
Write-Information $config.webhook
109110
if (![string]::IsNullOrEmpty($config.webhook)) {
110-
if ($Currentlog) {
111-
$JSONContent = $Currentlog | ConvertTo-Json -Compress
111+
$ChunkSize = 500
112+
if ($Currentlog.Count -gt 0) {
112113
$Title = "Logbook Notification: Alerts found starting at $((Get-Date).AddMinutes(-15))"
113-
Send-CIPPAlert -Type 'webhook' -Title $Title -JSONContent $JSONContent -TenantFilter 'AllTenants' -APIName 'Alerts' -SchemaSource 'Logbook Notification' -InvokingCommand 'Push-SchedulerCIPPNotifications' -UseStandardizedSchema:$([boolean]$Config.UseStandardizedSchema)
114-
$UpdateLogs = $CurrentLog | ForEach-Object { $_.sentAsAlert = $true; $_ }
115-
if ($UpdateLogs) { Add-CIPPAzDataTableEntity @Table -Entity $UpdateLogs -Force }
114+
for ($i = 0; $i -lt $Currentlog.Count; $i += $ChunkSize) {
115+
$end = [math]::Min($i + $ChunkSize - 1, $Currentlog.Count - 1)
116+
$chunk = $Currentlog[$i..$end]
117+
$JSONContent = $chunk | ConvertTo-Json -Compress
118+
Send-CIPPAlert -Type 'webhook' -Title $Title -JSONContent $JSONContent -TenantFilter 'AllTenants' -APIName 'Alerts' -SchemaSource 'Logbook Notification' -InvokingCommand 'Push-SchedulerCIPPNotifications' -UseStandardizedSchema:$([boolean]$Config.UseStandardizedSchema)
119+
& $MarkSent $chunk $LogTable
120+
$JSONContent = $null; $chunk = $null
121+
}
116122
}
117123

118-
if ($CurrentStandardsLogs) {
119-
$Data = $CurrentStandardsLogs
120-
$JSONContent = New-CIPPAlertTemplate -Data $Data -Format 'json' -InputObject 'table' -CIPPURL $CIPPURL
121-
$CurrentStandardsLogs | ConvertTo-Json -Compress
122-
$Title = "Standards Notification: Out of sync standards detected"
123-
Send-CIPPAlert -Type 'webhook' -Title $Title -JSONContent $JSONContent -TenantFilter 'AllTenants' -APIName 'Alerts' -SchemaSource 'Standards Notification' -InvokingCommand 'Push-SchedulerCIPPNotifications' -UseStandardizedSchema:$([boolean]$Config.UseStandardizedSchema)
124-
$updateStandards = $CurrentStandardsLogs | ForEach-Object {
125-
if ($_.PSObject.Properties.Name -contains 'sentAsAlert') {
126-
$_.sentAsAlert = $true
127-
} else {
128-
$_ | Add-Member -MemberType NoteProperty -Name sentAsAlert -Value $true -Force
129-
}
130-
$_
124+
if ($CurrentStandardsLogs.Count -gt 0) {
125+
$Title = 'Standards Notification: Out of sync standards detected'
126+
for ($i = 0; $i -lt $CurrentStandardsLogs.Count; $i += $ChunkSize) {
127+
$end = [math]::Min($i + $ChunkSize - 1, $CurrentStandardsLogs.Count - 1)
128+
$chunk = $CurrentStandardsLogs[$i..$end]
129+
$JSONContent = New-CIPPAlertTemplate -Data $chunk -Format 'json' -InputObject 'table' -CIPPURL $CIPPURL
130+
Send-CIPPAlert -Type 'webhook' -Title $Title -JSONContent $JSONContent -TenantFilter 'AllTenants' -APIName 'Alerts' -SchemaSource 'Standards Notification' -InvokingCommand 'Push-SchedulerCIPPNotifications' -UseStandardizedSchema:$([boolean]$Config.UseStandardizedSchema)
131+
& $MarkSent $chunk $StandardsTable
132+
$JSONContent = $null; $chunk = $null
131133
}
132134
}
133-
134135
}
135136
} catch {
136137
Write-Information "Could not send alerts to webhook $($config.webhook): $($_.Exception.message)"
137-
Write-LogMessage -API 'Alerts' -message "Could not send alerts to webhook $($config.webhook): $($_.Exception.message)" -tenant $Tenant -sev error -LogData (Get-CippException -Exception $_)
138+
Write-LogMessage -API 'Alerts' -message "Could not send alerts to webhook $($config.webhook): $($_.Exception.message)" -tenant 'AllTenants' -sev error -LogData (Get-CippException -Exception $_)
138139
}
139140

140141
if ($config.sendtoIntegration) {
141142
try {
142-
foreach ($tenant in ($CurrentLog.Tenant | Sort-Object -Unique)) {
143-
$Data = ($CurrentLog | Select-Object Message, API, Tenant, Username, Severity | Where-Object -Property tenant -EQ $tenant)
143+
foreach ($g in $LogsByTenant) {
144+
$tenant = $g.Name
145+
$Data = $g.Group | Select-Object Message, API, Tenant, Username, Severity
144146
$HTMLContent = New-CIPPAlertTemplate -Data $Data -Format 'html' -InputObject 'table' -CIPPURL $CIPPURL
145147
$Title = "$tenant CIPP Alert: Alerts found starting at $((Get-Date).AddMinutes(-15))"
146148
Send-CIPPAlert -Type 'psa' -Title $Title -HTMLContent $HTMLContent.htmlcontent -TenantFilter $tenant -APIName 'Alerts'
147-
$UpdateLogs = $CurrentLog | ForEach-Object { $_.SentAsAlert = $true; $_ }
148-
if ($UpdateLogs) { Add-CIPPAzDataTableEntity @Table -Entity $UpdateLogs -Force }
149+
& $MarkSent $g.Group $LogTable
150+
$Data = $null; $HTMLContent = $null
149151
}
150-
foreach ($standardsTenant in ($CurrentStandardsLogs.Tenant | Sort-Object -Unique)) {
151-
$Data = ($CurrentStandardsLogs | Where-Object -Property tenant -EQ $standardsTenant)
152-
$Subject = "$($standardsTenant): Standards are out of sync for $standardsTenant"
152+
foreach ($g in $StandardsByTenant) {
153+
$tenant = $g.Name
154+
$Data = $g.Group
155+
$Subject = "$($tenant): Standards are out of sync for $tenant"
153156
$HTMLContent = New-CIPPAlertTemplate -Data $Data -Format 'html' -InputObject 'standards' -CIPPURL $CIPPURL
154-
Send-CIPPAlert -Type 'psa' -Title $Subject -HTMLContent $HTMLContent.htmlcontent -TenantFilter $standardsTenant -APIName 'Alerts'
155-
$updateStandards = $CurrentStandardsLogs | ForEach-Object {
156-
if ($_.PSObject.Properties.Name -contains 'sentAsAlert') {
157-
$_.sentAsAlert = $true
158-
} else {
159-
$_ | Add-Member -MemberType NoteProperty -Name sentAsAlert -Value $true -Force
160-
}
161-
$_
162-
}
157+
Send-CIPPAlert -Type 'psa' -Title $Subject -HTMLContent $HTMLContent.htmlcontent -TenantFilter $tenant -APIName 'Alerts'
158+
& $MarkSent $g.Group $StandardsTable
159+
$Data = $null; $HTMLContent = $null
163160
}
164161
} catch {
165162
Write-Information "Could not send alerts to ticketing system: $($_.Exception.message)"
166-
Write-LogMessage -API 'Alerts' -tenant $Tenant -message "Could not send alerts to ticketing system: $($_.Exception.message)" -sev Error
163+
Write-LogMessage -API 'Alerts' -tenant 'AllTenants' -message "Could not send alerts to ticketing system: $($_.Exception.message)" -sev Error
167164
}
168165
}
169-
170166
}

Modules/CIPPActivityTriggers/Public/Entrypoints/Activity Triggers/Tests/Push-CIPPTest.ps1

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,6 @@ function Push-CIPPTest {
1212

1313
Write-Information "Running test $TestId for tenant $TenantFilter"
1414

15-
# Per-process cache of resolved test function commands so that a flat orchestrator
16-
# firing thousands of activities doesn't repeat the module command-table walk
17-
# for every task.
18-
if (-not $script:CIPPTestFunctionLookup) {
19-
$script:CIPPTestFunctionLookup = [System.Collections.Generic.Dictionary[string, object]]::new([System.StringComparer]::OrdinalIgnoreCase)
20-
Write-Information "[CacheInit] CIPPTestFunctionLookup initialized in PID $PID"
21-
}
22-
2315
try {
2416
if ($TestId -like 'CustomScript-*') {
2517
$ScriptGuid = $TestId -replace '^CustomScript-', ''
@@ -30,14 +22,7 @@ function Push-CIPPTest {
3022
}
3123

3224
$FunctionName = "Invoke-CippTest$TestId"
33-
34-
if ($script:CIPPTestFunctionLookup.ContainsKey($FunctionName)) {
35-
Write-Information "[CacheHit] CIPPTestFunctionLookup PID=$PID Key=$FunctionName Size=$($script:CIPPTestFunctionLookup.Count)"
36-
} else {
37-
Write-Information "[CacheMiss] CIPPTestFunctionLookup PID=$PID Key=$FunctionName Size=$($script:CIPPTestFunctionLookup.Count) - resolving via Get-Command"
38-
$script:CIPPTestFunctionLookup[$FunctionName] = Get-Command $FunctionName -Module CIPPTests -ErrorAction SilentlyContinue
39-
}
40-
$TestCommand = $script:CIPPTestFunctionLookup[$FunctionName]
25+
$TestCommand = Get-Command -Name $FunctionName -Module CIPPTests -ErrorAction SilentlyContinue
4126
if (-not $TestCommand) {
4227
Write-LogMessage -API 'Tests' -tenant $TenantFilter -message "Test function not found: $FunctionName" -sev Error
4328
return @{ testRun = $false }

0 commit comments

Comments
 (0)