Skip to content

Commit a69844a

Browse files
committed
audit log tweaks
guid expansion allow search downloads
1 parent 77cc79b commit a69844a

File tree

6 files changed

+283
-107
lines changed

6 files changed

+283
-107
lines changed

Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenantDownload.ps1

Lines changed: 30 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
function Push-AuditLogTenantDownload {
2-
Param($Item)
3-
$ConfigTable = Get-CippTable -TableName 'WebhookRules'
2+
param($Item)
43
$TenantFilter = $Item.TenantFilter
54

65
try {
@@ -37,47 +36,43 @@ function Push-AuditLogTenantDownload {
3736
} else { $CIPPURL = 'https://{0}' -f $CippConfig.Value }
3837
}
3938

40-
# Get webhook rules
41-
$ConfigEntries = Get-CIPPAzDataTableEntity @ConfigTable
4239
$LogSearchesTable = Get-CippTable -TableName 'AuditLogSearches'
4340

44-
$Configuration = $ConfigEntries | Where-Object { ($_.Tenants -match $TenantFilter -or $_.Tenants -match 'AllTenants') }
45-
if ($Configuration) {
46-
try {
47-
$LogSearches = Get-CippAuditLogSearches -TenantFilter $TenantFilter -ReadyToProcess | Select-Object -First 10
48-
Write-Information ('Audit Logs: Found {0} searches, begin downloading' -f $LogSearches.Count)
49-
foreach ($Search in $LogSearches) {
50-
$SearchEntity = Get-CIPPAzDataTableEntity @LogSearchesTable -Filter "Tenant eq '$($TenantFilter)' and RowKey eq '$($Search.id)'"
51-
$SearchEntity.CippStatus = 'Processing'
52-
Add-CIPPAzDataTableEntity @LogSearchesTable -Entity $SearchEntity -Force
53-
try {
54-
Write-Information "Audit Log search: Processing search ID: $($Search.id) for tenant: $TenantFilter"
55-
$Downloads = New-CIPPAuditLogSearchResultsCache -TenantFilter $TenantFilter -searchId $Search.id
56-
$SearchEntity.CippStatus = 'Downloaded'
57-
} catch {
58-
if ($_.Exception.Message -match 'Request rate is large. More Request Units may be needed, so no changes were made. Please retry this request later.') {
59-
$SearchEntity.CippStatus = 'Pending'
60-
Write-Information "Audit Log search: Rate limit hit for $($SearchEntity.RowKey)."
61-
if ($SearchEntity.PSObject.Properties.Name -contains 'RetryCount') {
62-
$SearchEntity.RetryCount++
63-
} else {
64-
$SearchEntity | Add-Member -MemberType NoteProperty -Name RetryCount -Value 1
65-
}
41+
try {
42+
$LogSearches = Get-CippAuditLogSearches -TenantFilter $TenantFilter -ReadyToProcess | Select-Object -First 10
43+
Write-Information ('Audit Logs: Found {0} searches, begin downloading' -f $LogSearches.Count)
44+
foreach ($Search in $LogSearches) {
45+
$SearchEntity = Get-CIPPAzDataTableEntity @LogSearchesTable -Filter "Tenant eq '$($TenantFilter)' and RowKey eq '$($Search.id)'"
46+
$SearchEntity.CippStatus = 'Processing'
47+
Add-CIPPAzDataTableEntity @LogSearchesTable -Entity $SearchEntity -Force
48+
try {
49+
Write-Information "Audit Log search: Processing search ID: $($Search.id) for tenant: $TenantFilter"
50+
$Downloads = New-CIPPAuditLogSearchResultsCache -TenantFilter $TenantFilter -searchId $Search.id
51+
$SearchEntity.CippStatus = 'Downloaded'
52+
} catch {
53+
if ($_.Exception.Message -match 'Request rate is large. More Request Units may be needed, so no changes were made. Please retry this request later.') {
54+
$SearchEntity.CippStatus = 'Pending'
55+
Write-Information "Audit Log search: Rate limit hit for $($SearchEntity.RowKey)."
56+
if ($SearchEntity.PSObject.Properties.Name -contains 'RetryCount') {
57+
$SearchEntity.RetryCount++
6658
} else {
67-
$Exception = [string](ConvertTo-Json -Compress -InputObject (Get-CippException -Exception $_))
68-
$SearchEntity | Add-Member -MemberType NoteProperty -Name Error -Value $Exception
69-
$SearchEntity.CippStatus = 'Failed'
70-
Write-Information "Error processing audit log rules: $($_.Exception.Message)"
59+
$SearchEntity | Add-Member -MemberType NoteProperty -Name RetryCount -Value 1
7160
}
72-
61+
} else {
62+
$Exception = [string](ConvertTo-Json -Compress -InputObject (Get-CippException -Exception $_))
63+
$SearchEntity | Add-Member -MemberType NoteProperty -Name Error -Value $Exception
64+
$SearchEntity.CippStatus = 'Failed'
65+
Write-Information "Error processing audit log rules: $($_.Exception.Message)"
7366
}
74-
Add-CIPPAzDataTableEntity @LogSearchesTable -Entity $SearchEntity -Force
67+
7568
}
76-
} catch {
77-
Write-Information ('Audit Log search: Error {0} line {1} - {2}' -f $_.InvocationInfo.ScriptName, $_.InvocationInfo.ScriptLineNumber, $_.Exception.Message)
78-
exit 0
69+
Add-CIPPAzDataTableEntity @LogSearchesTable -Entity $SearchEntity -Force
7970
}
71+
} catch {
72+
Write-Information ('Audit Log search: Error {0} line {1} - {2}' -f $_.InvocationInfo.ScriptName, $_.InvocationInfo.ScriptLineNumber, $_.Exception.Message)
73+
exit 0
8074
}
75+
8176
} catch {
8277
Write-Information ('Push-AuditLogTenant: Error {0} line {1} - {2}' -f $_.InvocationInfo.ScriptName, $_.InvocationInfo.ScriptLineNumber, $_.Exception.Message)
8378
exit 0

Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenantProcess.ps1

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
function Push-AuditLogTenantProcess {
2-
Param($Item)
2+
param($Item)
33
$TenantFilter = $Item.TenantFilter
44
$RowIds = $Item.RowIds
55

@@ -20,12 +20,13 @@ function Push-AuditLogTenantProcess {
2020
if ($Rows.Count -gt 0) {
2121
Write-Information "Retrieved $($Rows.Count) rows from cache for processing"
2222
Test-CIPPAuditLogRules -TenantFilter $TenantFilter -Rows $Rows
23-
exit 0
23+
return $true
2424
} else {
2525
Write-Information 'No rows found in cache for the provided row IDs'
26-
exit 0
26+
return $false
2727
}
2828
} catch {
2929
Write-Information ('Push-AuditLogTenant: Error {0} line {1} - {2}' -f $_.InvocationInfo.ScriptName, $_.InvocationInfo.ScriptLineNumber, $_.Exception.Message)
30+
return $false
3031
}
3132
}

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

Lines changed: 102 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -10,78 +10,119 @@ function Invoke-ExecAuditLogSearch {
1010

1111
$APIName = $Request.Params.CIPPEndpoint
1212
$Headers = $Request.Headers
13+
$Action = $Request.Query.Action ?? $Request.Body.Action
14+
1315
Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug'
1416

15-
$Query = $Request.Body
16-
if (!$Query.TenantFilter) {
17-
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
18-
StatusCode = [HttpStatusCode]::BadRequest
19-
Body = 'TenantFilter is required'
20-
})
21-
return
22-
}
23-
if (!$Query.StartTime -or !$Query.EndTime) {
24-
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
25-
StatusCode = [HttpStatusCode]::BadRequest
26-
Body = 'StartTime and EndTime are required'
27-
})
28-
return
29-
}
17+
switch ($Action) {
18+
'ProcessLogs' {
19+
$SearchId = $Request.Query.SearchId ?? $Request.Body.SearchId
20+
$TenantFilter = $Request.Query.tenantFilter ?? $Request.Body.tenantFilter
21+
if (!$SearchId) {
22+
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
23+
StatusCode = [HttpStatusCode]::BadRequest
24+
Body = 'SearchId is required'
25+
})
26+
return
27+
}
3028

31-
# Convert StartTime and EndTime to DateTime from unixtime
32-
if ($Query.StartTime -match '^\d+$') {
33-
$Query.StartTime = [DateTime]::UnixEpoch.AddSeconds([long]$Query.StartTime)
34-
} else {
35-
$Query.StartTime = [DateTime]$Query.StartTime
36-
}
29+
$Search = New-GraphGetRequest -Uri "https://graph.microsoft.com/beta/security/auditLog/queries/$SearchId" -AsApp $true -TenantId $TenantFilter
30+
Write-Information ($Search | ConvertTo-Json -Depth 10)
3731

38-
if ($Query.EndTime -match '^\d+$') {
39-
$Query.EndTime = [DateTime]::UnixEpoch.AddSeconds([long]$Query.EndTime)
40-
} else {
41-
$Query.EndTime = [DateTime]$Query.EndTime
42-
}
32+
$Entity = [PSCustomObject]@{
33+
PartitionKey = [string]'Search'
34+
RowKey = [string]$SearchId
35+
Tenant = [string]$TenantFilter
36+
DisplayName = [string]$Search.displayName
37+
StartTime = [datetime]$Search.filterStartDateTime
38+
EndTime = [datetime]$Search.filterEndDateTime
39+
Query = [string]($Search | ConvertTo-Json -Compress)
40+
CippStatus = [string]'Pending'
41+
}
42+
$Table = Get-CIPPTable -TableName 'AuditLogSearches'
43+
Add-CIPPAzDataTableEntity @Table -Entity $Entity -Force | Out-Null
4344

44-
$Command = Get-Command New-CippAuditLogSearch
45-
$AvailableParameters = $Command.Parameters.Keys
46-
$BadProps = foreach ($Prop in $Query.PSObject.Properties.Name) {
47-
if ($AvailableParameters -notcontains $Prop) {
48-
$Prop
45+
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
46+
StatusCode = [HttpStatusCode]::OK
47+
Body = @{
48+
resultText = "Search '$($Search.displayName)' queued for processing."
49+
state = 'success'
50+
} | ConvertTo-Json -Depth 10 -Compress
51+
})
4952
}
50-
}
51-
if ($BadProps) {
52-
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
53-
StatusCode = [HttpStatusCode]::BadRequest
54-
Body = "Invalid parameters: $($BadProps -join ', ')"
55-
})
56-
return
57-
}
53+
default {
54+
$Query = $Request.Body
55+
if (!$Query.TenantFilter) {
56+
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
57+
StatusCode = [HttpStatusCode]::BadRequest
58+
Body = 'TenantFilter is required'
59+
})
60+
return
61+
}
62+
if (!$Query.StartTime -or !$Query.EndTime) {
63+
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
64+
StatusCode = [HttpStatusCode]::BadRequest
65+
Body = 'StartTime and EndTime are required'
66+
})
67+
return
68+
}
5869

59-
try {
60-
Write-Information "Executing audit log search with parameters: $($Query | ConvertTo-Json -Depth 10)"
70+
# Convert StartTime and EndTime to DateTime from unixtime
71+
if ($Query.StartTime -match '^\d+$') {
72+
$Query.StartTime = [DateTime]::UnixEpoch.AddSeconds([long]$Query.StartTime)
73+
} else {
74+
$Query.StartTime = [DateTime]$Query.StartTime
75+
}
6176

62-
$Query = $Query | ConvertTo-Json -Depth 10 | ConvertFrom-Json -AsHashtable
63-
$NewSearch = New-CippAuditLogSearch @Query
77+
if ($Query.EndTime -match '^\d+$') {
78+
$Query.EndTime = [DateTime]::UnixEpoch.AddSeconds([long]$Query.EndTime)
79+
} else {
80+
$Query.EndTime = [DateTime]$Query.EndTime
81+
}
6482

65-
if ($NewSearch) {
66-
$Results = @{
67-
resultText = "Created audit log search: $($NewSearch.displayName)"
68-
state = 'success'
69-
details = $NewSearch
83+
$Command = Get-Command New-CippAuditLogSearch
84+
$AvailableParameters = $Command.Parameters.Keys
85+
$BadProps = foreach ($Prop in $Query.PSObject.Properties.Name) {
86+
if ($AvailableParameters -notcontains $Prop) {
87+
$Prop
88+
}
7089
}
71-
} else {
72-
$Results = @{
73-
resultText = 'Failed to initiate search'
74-
state = 'error'
90+
if ($BadProps) {
91+
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
92+
StatusCode = [HttpStatusCode]::BadRequest
93+
Body = "Invalid parameters: $($BadProps -join ', ')"
94+
})
95+
return
96+
}
97+
98+
try {
99+
Write-Information "Executing audit log search with parameters: $($Query | ConvertTo-Json -Depth 10)"
100+
101+
$Query = $Query | ConvertTo-Json -Depth 10 | ConvertFrom-Json -AsHashtable
102+
$NewSearch = New-CippAuditLogSearch @Query
103+
104+
if ($NewSearch) {
105+
$Results = @{
106+
resultText = "Created audit log search: $($NewSearch.displayName)"
107+
state = 'success'
108+
details = $NewSearch
109+
}
110+
} else {
111+
$Results = @{
112+
resultText = 'Failed to initiate search'
113+
state = 'error'
114+
}
115+
}
116+
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
117+
StatusCode = [HttpStatusCode]::OK
118+
Body = $Results
119+
})
120+
} catch {
121+
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
122+
StatusCode = [HttpStatusCode]::BadRequest
123+
Body = $_.Exception.Message
124+
})
75125
}
76126
}
77-
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
78-
StatusCode = [HttpStatusCode]::OK
79-
Body = $Results
80-
})
81-
} catch {
82-
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
83-
StatusCode = [HttpStatusCode]::BadRequest
84-
Body = $_.Exception.Message
85-
})
86127
}
87128
}

Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Tenant/Administration/Alerts/Invoke-ListAuditLogSearches.ps1

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ function Invoke-ListAuditLogSearches {
1818
$Days = $Request.Query.Days
1919
$Type = $Request.Query.Type
2020

21-
2221
if ($TenantFilter) {
2322
switch ($Type) {
2423
'Searches' {

Modules/CIPPCore/Public/Entrypoints/Orchestrator Functions/Start-AuditLogOrchestrator.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ function Start-AuditLogOrchestrator {
1616

1717
if (($AuditLogSearches | Measure-Object).Count -eq 0) {
1818
Write-Information 'No audit log searches available'
19-
} elseif (($WebhookRules | Measure-Object).Count -eq 0) {
19+
} elseif (($AuditLogSearches | Measure-Object).Count -eq 0 -and ($WebhookRules | Measure-Object).Count -eq 0) {
2020
Write-Information 'No webhook rules defined'
2121
} else {
2222
Write-Information "Audit Logs: Downloading $($AuditLogSearches.Count) searches"

0 commit comments

Comments
 (0)