Skip to content

Commit 3ce368b

Browse files
committed
Manual Audit Log Search Fixes
1 parent 0b72ea5 commit 3ce368b

3 files changed

Lines changed: 86 additions & 0 deletions

File tree

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
function Add-CippAuditLogCoverageManualEntry {
2+
<#
3+
.SYNOPSIS
4+
Bridge a manually-created audit log search into the V2 AuditLogCoverage ledger so the
5+
pipeline downloads and processes it automatically (Option B).
6+
.DESCRIPTION
7+
Manual searches live in the AuditLogSearches table, which the (now V2-only) pipeline no
8+
longer scans. When alert processing is requested for a manual search, this writes a ledger
9+
row keyed 'MANUAL-<searchId>' in State 'Created' so Start-AuditLogIngestionV2 /
10+
Push-AuditLogDownloadV2 poll, download and process it like any other search - it inherits
11+
retries, the orphan sweep, SearchStatus tracking and the coverage UI.
12+
13+
The RowKey prefix keeps these out of the window planner: Get-CippAuditLogPlannedWindows only
14+
considers 14-digit RowKeys and Get-CippAuditLogReconciliationWindows only 'RECON-*', so a
15+
'MANUAL-*' row is never treated as a window, gap or reconciliation block. Type 'Manual' lets
16+
the UI exclude them from the window heatmap/charts.
17+
18+
Idempotent (UpsertMerge): re-queuing the same search resets State to 'Created' to reprocess.
19+
.PARAMETER TenantFilter
20+
Tenant default domain (becomes the ledger PartitionKey).
21+
.PARAMETER SearchId
22+
The Graph audit-log search id.
23+
.PARAMETER StartTime
24+
Search start (datetime / DateTimeOffset / ISO string). Stored as WindowStart.
25+
.PARAMETER EndTime
26+
Search end. Stored as WindowEnd.
27+
.PARAMETER SearchStatus
28+
Graph search status at creation (e.g. notStarted); refreshed on each poll.
29+
.PARAMETER TenantId
30+
Tenant customerId. Resolved from TenantFilter if not supplied.
31+
.FUNCTIONALITY
32+
Internal
33+
#>
34+
[CmdletBinding()]
35+
param(
36+
[Parameter(Mandatory = $true)][string]$TenantFilter,
37+
[Parameter(Mandatory = $true)][string]$SearchId,
38+
$StartTime,
39+
$EndTime,
40+
[string]$SearchStatus,
41+
[string]$TenantId
42+
)
43+
44+
try {
45+
if (-not $TenantId) {
46+
try { $TenantId = Get-Tenants -TenantFilter $TenantFilter | Select-Object -First 1 -ExpandProperty customerId } catch {}
47+
}
48+
49+
$Now = (Get-Date).ToUniversalTime()
50+
$Ledger = Get-CippTable -TableName 'AuditLogCoverage'
51+
$Entity = @{
52+
PartitionKey = [string]$TenantFilter
53+
RowKey = 'MANUAL-' + [string]$SearchId
54+
TenantId = [string]$TenantId
55+
Type = 'Manual'
56+
State = 'Created'
57+
SearchId = [string]$SearchId
58+
SearchStatus = [string]$SearchStatus
59+
Attempts = 0
60+
RetryCount = 0
61+
ThrottleCount = 0
62+
CreatedUtc = $Now
63+
LastPolledUtc = $Now
64+
LastError = ''
65+
}
66+
if ($StartTime) { try { $Entity.WindowStart = ([datetimeoffset]$StartTime).UtcDateTime } catch {} }
67+
if ($EndTime) { try { $Entity.WindowEnd = ([datetimeoffset]$EndTime).UtcDateTime } catch {} }
68+
69+
Add-CIPPAzDataTableEntity @Ledger -Entity $Entity -OperationType UpsertMerge
70+
Write-Information "AuditLogV2: bridged manual search $SearchId for $TenantFilter into coverage ledger (MANUAL-$SearchId)"
71+
} catch {
72+
Write-Information ('Add-CippAuditLogCoverageManualEntry error for {0} / {1}: {2}' -f $TenantFilter, $SearchId, $_.Exception.Message)
73+
}
74+
}

Modules/CIPPCore/Public/AuditLogs/New-CippAuditLogSearch.ps1

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,13 @@ function New-CippAuditLogSearch {
269269
}
270270
$Table = Get-CIPPTable -TableName 'AuditLogSearches'
271271
Add-CIPPAzDataTableEntity @Table -Entity $Entity -Force | Out-Null
272+
273+
# When alert processing is requested, bridge the search into the V2 AuditLogCoverage
274+
# ledger so the pipeline downloads + processes it automatically (the V2 pipeline does
275+
# not scan the AuditLogSearches table).
276+
if ($ProcessLogs.IsPresent) {
277+
Add-CippAuditLogCoverageManualEntry -TenantFilter $TenantFilter -SearchId $Query.id -StartTime $StartTime -EndTime $EndTime -SearchStatus $Query.status
278+
}
272279
}
273280

274281
return $Query

Modules/CIPPHTTP/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ExecAuditLogSearch.ps1

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ function Invoke-ExecAuditLogSearch {
5050

5151
Add-CIPPAzDataTableEntity @Table -Entity $Entity -Force | Out-Null
5252

53+
# Bridge into the V2 AuditLogCoverage ledger so the pipeline picks it up automatically
54+
# (re-queuing resets it to State 'Created' to reprocess).
55+
$ManualStatus = if ($Search) { [string]$Search.status } else { '' }
56+
Add-CippAuditLogCoverageManualEntry -TenantFilter $TenantFilter -SearchId $SearchId -StartTime $Entity.StartTime -EndTime $Entity.EndTime -SearchStatus $ManualStatus
57+
5358
$DisplayName = $Entity.DisplayName
5459
Write-LogMessage -headers $Headers -API $APIName -message "Queued search for processing: $($Search.displayName)" -Sev 'Info' -tenant $TenantFilter
5560

0 commit comments

Comments
 (0)