Skip to content

Commit

Permalink
Merge pull request #1132 from JohnDuprey/dev
Browse files Browse the repository at this point in the history
Audit logs
  • Loading branch information
JohnDuprey authored Oct 3, 2024
2 parents fe528b7 + 8d27543 commit b8b7981
Show file tree
Hide file tree
Showing 9 changed files with 52 additions and 90 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
function Push-AuditLogBundleProcessing {
Param($Item)

return # Disabled for now, as it's not used

try {
$AuditBundleTable = Get-CippTable -tablename 'AuditLogBundles'
$AuditLogBundle = Get-CIPPAzDataTableEntity @AuditBundleTable -Filter "PartitionKey eq '$($Item.TenantFilter)' and RowKey eq '$($Item.ContentId)'"
Expand Down Expand Up @@ -37,4 +39,4 @@ function Push-AuditLogBundleProcessing {
} catch {
Write-Host ( 'Audit log error {0} line {1} - {2}' -f $_.InvocationInfo.ScriptName, $_.InvocationInfo.ScriptLineNumber, $_.Exception.Message)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ function Push-AuditLogTenant {

$SearchEntity.CippStatus = 'Completed'
$MatchedRules = [string](ConvertTo-Json -Compress -InputObject $AuditLogTest.MatchedRules)
$SearchEntity | Add-Member -MemberType NoteProperty -Name MatchedRules -Value $MatchedRules
$SearchEntity | Add-Member -MemberType NoteProperty -Name MatchedLogs -Value $AuditLogTest.MatchedLogs
$SearchEntity | Add-Member -MemberType NoteProperty -Name TotalLogs -Value $AuditLogTest.TotalLogs
$SearchEntity | Add-Member -MemberType NoteProperty -Name MatchedRules -Value $MatchedRules -Force
$SearchEntity | Add-Member -MemberType NoteProperty -Name MatchedLogs -Value $AuditLogTest.MatchedLogs -Force
$SearchEntity | Add-Member -MemberType NoteProperty -Name TotalLogs -Value $AuditLogTest.TotalLogs -Force
} catch {
$SearchEntity.CippStatus = 'Failed'
Write-Information "Error processing audit log rules: $($_.Exception.Message)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ function Push-Schedulerwebhookcreation {
param (
$item
)
$Table = Get-CIPPTable -TableName 'SchedulerConfig'
<#$Table = Get-CIPPTable -TableName 'SchedulerConfig'
$WebhookTable = Get-CIPPTable -TableName 'webhookTable'
$Tenant = $Item.Tenant
$Row = Get-CIPPAzDataTableEntity @Table -Filter "RowKey eq '$($item.SchedulerRow)'"
Expand Down Expand Up @@ -42,6 +42,6 @@ function Push-Schedulerwebhookcreation {
Write-Information "Failed to create webhook for $Tenant - $($Row.webhookType): $($_.Exception.Message)"
}
}
}
}#>

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ function Start-AuditLogOrchestrator {
try {
$AuditLogSearchesTable = Get-CIPPTable -TableName 'AuditLogSearches'
$AuditLogSearches = Get-CIPPAzDataTableEntity @AuditLogSearchesTable -Filter "CippStatus eq 'Pending'"

$ConfigTable = Get-CippTable -TableName 'WebhookRules'
$ConfigEntries = Get-CIPPAzDataTableEntity @ConfigTable

$TenantList = Get-Tenants -IncludeErrors
# Round time down to nearest minute
$Now = Get-Date
Expand All @@ -32,11 +36,22 @@ function Start-AuditLogOrchestrator {

Write-Information 'Audit Logs: Creating new searches'
foreach ($Tenant in $TenantList) {
try {
$NewSearch = New-CippAuditLogSearch -TenantFilter $Tenant.defaultDomainName -StartTime $StartTime -EndTime $EndTime -ProcessLogs
Write-Information "Created audit log search $($Tenant.defaultDomainName) - $($NewSearch.displayName)"
} catch {
Write-Information "Error creating audit log search $($Tenant.defaultDomainName) - $($_.Exception.Message)"
$Configuration = $ConfigEntries | Where-Object { ($_.Tenants -match $TenantFilter -or $_.Tenants -match 'AllTenants') }
if ($Configuration) {
$ServiceFilters = $Configuration | Select-Object -Property type | Sort-Object -Property type -Unique | ForEach-Object { $_.type.split('.')[1] }
try {
$LogSearch = @{
StartTime = $StartTime
EndTime = $EndTime
ServiceFilters = $ServiceFilters
TenantFilter = $Tenant.defaultDomainName
ProcessLogs = $true
}
$NewSearch = New-CippAuditLogSearch @LogSearch
Write-Information "Created audit log search $($Tenant.defaultDomainName) - $($NewSearch.displayName)"
} catch {
Write-Information "Error creating audit log search $($Tenant.defaultDomainName) - $($_.Exception.Message)"
}
}
}
} catch {
Expand Down
2 changes: 1 addition & 1 deletion Modules/CIPPCore/Public/Get-CIPPTimerFunctions.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ function Get-CIPPTimerFunctions {
}
Add-CIPPAzDataTableEntity @Table -Entity $Status
} else {
if ($Orchestrator.IsSystem -or $ResetToDefault.IsPresent) {
if ($Orchestrator.IsSystem -eq $true -or $ResetToDefault.IsPresent) {
$Status.Cron = $CronString
}
$Status.NextOccurrence = $NextOccurrence.ToUniversalTime()
Expand Down
5 changes: 3 additions & 2 deletions Modules/CIPPCore/Public/Send-CIPPAlert.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ function Send-CIPPAlert {
$TenantFilter,
$APIName = 'Send Alert',
$ExecutingUser,
$TableName
$TableName,
$RowKey = [string][guid]::NewGuid()
)
Write-Information 'Shipping Alert'
$Table = Get-CIPPTable -TableName SchedulerConfig
Expand Down Expand Up @@ -52,7 +53,7 @@ function Send-CIPPAlert {
$Table = Get-CIPPTable -TableName $TableName
$Alert = @{
PartitionKey = $TenantFilter ?? 'Alert'
RowKey = [string][guid]::NewGuid()
RowKey = $RowKey
Title = $Title
Data = [string]$JSONContent
Tenant = $TenantFilter
Expand Down
11 changes: 11 additions & 0 deletions Modules/CIPPCore/Public/Webhooks/Invoke-CIPPWebhookProcessing.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ function Invoke-CippWebhookProcessing {
$ExecutingUser
)

$AuditLogTable = Get-CIPPTable -TableName 'AuditLogs'
$AuditLog = Get-CIPPAzDataTableEntity @AuditLogTable -Filter "PartitionKey eq '$TenantFilter' and RowKey eq '$($Data.Id)'"

if ($AuditLog) {
Write-Host "Audit Log already exists for $($Data.Id). Skipping processing."
return
}

$Tenant = Get-Tenants -IncludeErrors | Where-Object { $_.defaultDomainName -eq $TenantFilter }
Write-Host "Received data. Our Action List is $($data.CIPPAction)"

Expand Down Expand Up @@ -54,6 +62,7 @@ function Invoke-CippWebhookProcessing {

# Save audit log entry to table
$LocationInfo = $Data.CIPPLocationInfo | ConvertFrom-Json -ErrorAction SilentlyContinue
$AuditRecord = $Data.AuditRecord | ConvertFrom-Json -ErrorAction SilentlyContinue
$GenerateJSON = New-CIPPAlertTemplate -format 'json' -data $Data -ActionResults $ActionResults -CIPPURL $CIPPURL
$JsonContent = @{
Title = $GenerateJSON.Title
Expand All @@ -63,6 +72,7 @@ function Invoke-CippWebhookProcessing {
IP = $data.ClientIP
PotentialLocationInfo = $LocationInfo
ActionsTaken = $ActionResults
AuditRecord = $AuditRecord
} | ConvertTo-Json -Depth 15 -Compress

$CIPPAlert = @{
Expand All @@ -71,6 +81,7 @@ function Invoke-CippWebhookProcessing {
JSONContent = $JsonContent
TenantFilter = $TenantFilter
TableName = 'AuditLogs'
RowKey = $Data.Id
}
$LogId = Send-CIPPAlert @CIPPAlert

Expand Down
67 changes: 2 additions & 65 deletions Modules/CIPPCore/Public/Webhooks/New-CIPPGraphSubscription.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ function New-CIPPGraphSubscription {
[CmdletBinding()]
param (
$TenantFilter,
[bool]$auditLogAPI = $false,
$TypeofSubscription,
$AllowedLocations,
$BaseURL,
Expand All @@ -17,69 +16,7 @@ function New-CIPPGraphSubscription {
$WebhookTable = Get-CIPPTable -TableName 'webhookTable'

try {
if ($auditLogAPI) {
$CIPPID = (New-Guid).GUID
$Resource = $EventType
$WebhookFilter = "PartitionKey eq '$($TenantFilter)' and Resource eq '$Resource' and Version eq '3'"
$ExistingWebhooks = Get-CIPPAzDataTableEntity @WebhookTable -Filter $WebhookFilter
$MatchedWebhook = $ExistingWebhooks
try {
if (!$MatchedWebhook -or ($Recreate.IsPresent)) {
if (!$MatchedWebhook) {
$WebhookRow = [PSCustomObject]@{
PartitionKey = [string]$TenantFilter
RowKey = [string]$CIPPID
Status = 'Enabled'
Error = ''
Resource = [string]$Resource
Expiration = [string]'Does Not Expire'
Version = [string]'3'
}
Add-CIPPAzDataTableEntity @WebhookTable -Entity $WebhookRow
} else {
Write-Host 'Setting webhook back to enabled'
Write-Host ($MatchedWebhook | ConvertTo-Json)
$MatchedWebhook | Add-Member -MemberType NoteProperty -Name Status -Value 'Enabled' -Force
$MatchedWebhook | Add-Member -MemberType NoteProperty -Name Error -Value '' -Force

$null = Add-CIPPAzDataTableEntity @WebhookTable -Entity $MatchedWebhook -Force
$WebhookRow = $MatchedWebhook
}
Write-Host "Creating webhook subscription for $EventType"

$AuditLog = New-GraphPOSTRequest -type POST -uri "https://manage.office.com/api/v1.0/$($TenantFilter)/activity/feed/subscriptions/start?contentType=$EventType&PublisherIdentifier=$($env:TenantID)" -tenantid $TenantFilter -scope 'https://manage.office.com/.default' -body '{}' -verbose
Write-LogMessage -user $ExecutingUser -API $APIName -message "Created Webhook subscription for $($TenantFilter) for the log $($EventType)" -Sev 'Info' -tenant $TenantFilter
return @{ Success = $true; message = "Created Webhook subscription for $($TenantFilter) for the log $($EventType)" }
} else {
if ($MatchedWebhook.Status -eq 'Disabled') {
return @{ success = $false; message = "Webhook subscription for $($TenantFilter) is disabled due to an error"; WebhookID = $MatchedWebhook.RowKey }
} else {
return @{ success = $true; message = "Webhook exists for $($TenantFilter) for the log $($EventType)"; WebhookID = $MatchedWebhook.RowKey }
}
}
} catch {
if ($_.Exception.Message -eq 'The subscription is already enabled. No property change.' -or $_.Exception.Message -like '*already exists*') {
Write-LogMessage -user $ExecutingUser -API $APIName -message "Webhook subscription for $($TenantFilter) already exists" -Sev 'Info' -tenant $TenantFilter
return @{ success = $true; message = "Webhook exists for $($TenantFilter) for the log $($EventType)" }
} elseif ($_.Exception.Message -match "The service principal for resource 'https://manage.office.com' is disabled") {
Write-LogMessage -user $ExecutingUser -API $APIName -message "Failed to create Webhook Subscription for $($TenantFilter): This tenant may not have an Exchange Online license. Audit Log subscription disabled." -Sev 'Error' -tenant $TenantFilter -LogData (Get-CippException -Exception $_)
$WebhookRow.Status = 'Disabled'
$WebhookRow.Error = $_.Exception.Message
$null = Add-CIPPAzDataTableEntity @WebhookTable -Entity $WebhookRow -Force
return @{ success = $false; message = "Failed to create Webhook Subscription for $($TenantFilter): $($_.Exception.Message)" }
} elseif ($_.Exception.Message -match 'Retry the request.') {
Remove-AzDataTableEntity @WebhookTable -Entity @{ PartitionKey = $TenantFilter; RowKey = [string]$CIPPID } | Out-Null
Write-LogMessage -user $ExecutingUser -API $APIName -message "Failed to create Webhook Subscription for $($TenantFilter): $($_.Exception.Message)" -Sev 'Error' -tenant $TenantFilter -LogData (Get-CippException -Exception $_)
return @{ success = $false; message = "Failed to create Webhook Subscription for $($TenantFilter): A temporary error occurred, we will try to subscribe again later" }
} else {
$WebhookRow.Status = 'Disabled'
$WebhookRow.Error = $_.Exception.Message
$null = Add-CIPPAzDataTableEntity @WebhookTable -Entity $WebhookRow -Force
Write-LogMessage -user $ExecutingUser -API $APIName -message "Failed to create Webhook Subscription for $($TenantFilter): $($_.Exception.Message)" -Sev 'Error' -tenant $TenantFilter -LogData (Get-CippException -Exception $_)
return @{ success = $false; message = "Failed to create Webhook Subscription for $($TenantFilter): $($_.Exception.Message). Audit log subscription disabled." }
}
}
} elseif ($PartnerCenter.IsPresent) {
if ($PartnerCenter.IsPresent) {
$WebhookFilter = "PartitionKey eq '$($env:TenantID)'"
$ExistingWebhooks = Get-CIPPAzDataTableEntity @WebhookTable -Filter $WebhookFilter
$CIPPID = $env:TenantID
Expand Down Expand Up @@ -143,7 +80,7 @@ function New-CIPPGraphSubscription {
}

} else {
# First check if there is an exsiting Webhook in place
# First check if there is an existing Webhook in place
$WebhookFilter = "PartitionKey eq '$($TenantFilter)'"
$ExistingWebhooks = Get-CIPPAzDataTableEntity @WebhookTable -Filter $WebhookFilter
$MatchedWebhook = $ExistingWebhooks | Where-Object { $_.Resource -eq $Resource }
Expand Down
18 changes: 7 additions & 11 deletions Modules/CIPPCore/Public/Webhooks/Test-CIPPAuditLogRules.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,16 @@ function Test-CIPPAuditLogRules {
LogType = $_.Type
}
}
#$AuditLogQuery = @{
# TenantFilter = $TenantFilter
# ContentUri = $ContentUri
#}
#Write-Information 'Getting data from Office 365 Management Activity API'
#$Data = Get-CIPPAuditLogContent @AuditLogQuery
Write-Information 'Getting audit records from Graph API'
$Data = Get-CippAuditLogSearchResults -TenantFilter $TenantFilter -QueryId $SearchId
$LogCount = ($Data | Measure-Object).Count
$SearchResults = Get-CippAuditLogSearchResults -TenantFilter $TenantFilter -QueryId $SearchId
$LogCount = ($SearchResults | Measure-Object).Count
Write-Information "Logs to process: $LogCount"
$Results.TotalLogs = $LogCount
if ($LogCount -gt 0) {
$PreProcessedData = $Data.auditData | Select-Object *, CIPPAction, CIPPClause, CIPPGeoLocation, CIPPBadRepIP, CIPPHostedIP, CIPPIPDetected, CIPPLocationInfo, CIPPExtendedProperties, CIPPDeviceProperties, CIPPParameters, CIPPModifiedProperties -ErrorAction SilentlyContinue
$LocationTable = Get-CIPPTable -TableName 'knownlocationdb'
$ProcessedData = foreach ($Data in $PreProcessedData) {
$ProcessedData = foreach ($AuditRecord in $SearchResults) {
$RootProperties = $AuditRecord | Select-Object * -ExcludeProperty auditData
$Data = $AuditRecord.auditData | Select-Object *, CIPPAction, CIPPClause, CIPPGeoLocation, CIPPBadRepIP, CIPPHostedIP, CIPPIPDetected, CIPPLocationInfo, CIPPExtendedProperties, CIPPDeviceProperties, CIPPParameters, CIPPModifiedProperties, AuditRecord -ErrorAction SilentlyContinue
try {
if ($Data.ExtendedProperties) {
$Data.CIPPExtendedProperties = ($Data.ExtendedProperties | ConvertTo-Json)
Expand Down Expand Up @@ -134,6 +129,7 @@ function Test-CIPPAuditLogRules {
$Data.CIPPHostedIP = $hosting
$Data.CIPPIPDetected = $IP
$Data.CIPPLocationInfo = ($Location | ConvertTo-Json)
$Data.AuditRecord = ($RootProperties | ConvertTo-Json)
}
$Data | Select-Object * -ExcludeProperty ExtendedProperties, DeviceProperties, parameters
} catch {
Expand Down Expand Up @@ -185,7 +181,7 @@ function Test-CIPPAuditLogRules {
}
$ReturnedData
}
$Results.MatchedRules = $MatchedRules | Select-Object -Unique
$Results.MatchedRules = @($MatchedRules | Select-Object -Unique)
$Results.MatchedLogs = ($DataToProcess | Measure-Object).Count
$Results.DataToProcess = $DataToProcess
}
Expand Down

0 comments on commit b8b7981

Please sign in to comment.