-
Notifications
You must be signed in to change notification settings - Fork 5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1130 from JohnDuprey/dev
Audit logs
- Loading branch information
Showing
13 changed files
with
232 additions
and
100 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
23 changes: 23 additions & 0 deletions
23
Modules/CIPPCore/Public/AuditLogs/Get-CippAuditLogSearchResults.ps1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
function Get-CippAuditLogSearchResults { | ||
<# | ||
.SYNOPSIS | ||
Get the results of an audit log search | ||
.DESCRIPTION | ||
Get the results of an audit log search from the Graph API | ||
.PARAMETER TenantFilter | ||
The tenant to filter on. | ||
.PARAMETER QueryId | ||
The ID of the query to get the results for. | ||
#> | ||
param ( | ||
[Parameter(Mandatory = $true)] | ||
[string]$TenantFilter, | ||
[Parameter(ValueFromPipelineByPropertyName = $true, Mandatory = $true)] | ||
[Alias('id')] | ||
[string]$QueryId | ||
) | ||
|
||
process { | ||
New-GraphGetRequest -uri ('https://graph.microsoft.com/beta/security/auditLog/queries/{0}/records?$top=999' -f $QueryId) -AsApp $true -tenantid $TenantFilter | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
Modules/CIPPCore/Public/AuditLogs/Get-CippAuditLogSearches.ps1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
function Get-CippAuditLogSearches { | ||
<# | ||
.SYNOPSIS | ||
Get the available audit log searches | ||
.DESCRIPTION | ||
Query the Graph API for available audit log searches. | ||
.PARAMETER TenantFilter | ||
The tenant to filter on. | ||
#> | ||
param ( | ||
[Parameter(Mandatory = $true)] | ||
[string]$TenantFilter, | ||
[Parameter()] | ||
[switch]$ReadyToProcess | ||
) | ||
$Queries = New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/security/auditLog/queries' -AsApp $true -tenantid $TenantFilter | ||
if ($ReadyToProcess.IsPresent) { | ||
$AuditLogSearchesTable = Get-CippTable -TableName 'AuditLogSearches' | ||
$PendingQueries = Get-CIPPAzDataTableEntity @AuditLogSearchesTable -Filter "Tenant eq '$TenantFilter' and CippStatus eq 'Pending'" | ||
$Queries = $Queries | Where-Object { $PendingQueries.RowKey -contains $_.id -and $_.status -eq 'succeeded' } | ||
} | ||
return $Queries | ||
} |
19 changes: 19 additions & 0 deletions
19
Modules/CIPPCore/Public/AuditLogs/Get-CippLastAuditLogSearch.ps1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
function Get-CippLastAuditLogSearch { | ||
<# | ||
.SYNOPSIS | ||
Get the last audit log search | ||
.DESCRIPTION | ||
Query the Graph API for the last audit log search. | ||
.PARAMETER TenantFilter | ||
The tenant to filter on. | ||
#> | ||
param ( | ||
[Parameter(Mandatory = $true)] | ||
[string]$TenantFilter | ||
) | ||
|
||
$Table = Get-CIPPTable -TableName AuditLogSearches | ||
$LastHour = (Get-Date).AddHours(-1).ToString('yyyy-MM-ddTHH:mm:ssZ') | ||
$LastSearch = Get-AzDataTableEntity @Table -Filter "Tenant eq '$TenantFilter' and Timestamp ge datetime'$LastHour'" | Sort-Object Timestamp -Descending | Select-Object -First 1 | ||
return $LastSearch | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
100 changes: 41 additions & 59 deletions
100
Modules/CIPPCore/Public/Entrypoints/Activity Triggers/Webhooks/Push-AuditLogTenant.ps1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,78 +1,60 @@ | ||
function Push-AuditLogTenant { | ||
Param($Item) | ||
|
||
# Get Table contexts | ||
$AuditBundleTable = Get-CippTable -tablename 'AuditLogBundles' | ||
$SchedulerConfig = Get-CippTable -TableName 'SchedulerConfig' | ||
$WebhookTable = Get-CippTable -tablename 'webhookTable' | ||
$ConfigTable = Get-CippTable -TableName 'WebhookRules' | ||
#$Tenant = Get-Tenants -TenantFilter $Item.customerId -IncludeErrors | ||
$TenantFilter = $Item.TenantFilter | ||
|
||
Write-Information "Audit Logs: Processing $($TenantFilter)" | ||
# Query CIPPURL for linking | ||
$CIPPURL = Get-CIPPAzDataTableEntity @SchedulerConfig -Filter "PartitionKey eq 'webhookcreation'" | Select-Object -First 1 -ExpandProperty CIPPURL | ||
|
||
# Get all webhooks for the tenant | ||
$Webhooks = Get-CIPPAzDataTableEntity @WebhookTable -Filter "PartitionKey eq '$($Item.TenantFilter)' and Version eq '3'" | Where-Object { $_.Resource -match '^Audit' } | ||
|
||
# Get webhook rules | ||
$ConfigEntries = Get-CIPPAzDataTableEntity @ConfigTable | ||
$LogSearchesTable = Get-CippTable -TableName 'AuditLogSearches' | ||
|
||
# Date filter for existing bundles | ||
$LastHour = (Get-Date).AddHours(-1).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss') | ||
|
||
$NewBundles = [System.Collections.Generic.List[object]]::new() | ||
foreach ($Webhook in $Webhooks) { | ||
# only process webhooks that are configured in the webhookrules table | ||
$Configuration = $ConfigEntries | Where-Object { ($_.Tenants -match $TenantFilter -or $_.Tenants -match 'AllTenants') } | ||
if ($Configuration.Type -notcontains $Webhook.Resource) { | ||
continue | ||
} | ||
|
||
$TenantFilter = $Webhook.PartitionKey | ||
$LogType = $Webhook.Resource | ||
Write-Information "Querying for $LogType on $TenantFilter" | ||
$ContentBundleQuery = @{ | ||
TenantFilter = $TenantFilter | ||
ContentType = $LogType | ||
StartTime = $Item.StartTime | ||
EndTime = $Item.EndTime | ||
} | ||
$Configuration = $ConfigEntries | Where-Object { ($_.Tenants -match $TenantFilter -or $_.Tenants -match 'AllTenants') } | ||
if ($Configuration) { | ||
try { | ||
$LogBundles = Get-CIPPAuditLogContentBundles @ContentBundleQuery | ||
$ExistingBundles = Get-CIPPAzDataTableEntity @AuditBundleTable -Filter "PartitionKey eq '$($Item.TenantFilter)' and ContentType eq '$LogType' and Timestamp ge datetime'$($LastHour)'" | ||
|
||
foreach ($Bundle in $LogBundles) { | ||
if ($ExistingBundles.RowKey -notcontains $Bundle.contentId) { | ||
$NewBundles.Add([PSCustomObject]@{ | ||
PartitionKey = $TenantFilter | ||
RowKey = $Bundle.contentId | ||
DefaultDomainName = $TenantFilter | ||
ContentType = $Bundle.contentType | ||
ContentUri = $Bundle.contentUri | ||
ContentCreated = $Bundle.contentCreated | ||
ContentExpiration = $Bundle.contentExpiration | ||
CIPPURL = [string]$CIPPURL | ||
ProcessingStatus = 'Pending' | ||
MatchedRules = '' | ||
MatchedLogs = 0 | ||
}) | ||
$LogSearches = Get-CippAuditLogSearches -TenantFilter $TenantFilter -ReadyToProcess | ||
Write-Information ('Audit Logs: Found {0} searches, begin processing' -f $LogSearches.Count) | ||
foreach ($Search in $LogSearches) { | ||
$SearchEntity = Get-CIPPAzDataTableEntity @LogSearchesTable -Filter "Tenant eq '$($TenantFilter)' and RowKey eq '$($Search.id)'" | ||
$SearchEntity.CippStatus = 'Processing' | ||
Add-CIPPAzDataTableEntity @LogSearchesTable -Entity $SearchEntity -Force | ||
try { | ||
# Test the audit log rules against the search results | ||
$AuditLogTest = Test-CIPPAuditLogRules -TenantFilter $TenantFilter -SearchId $Search.id | ||
|
||
$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 | ||
} catch { | ||
$SearchEntity.CippStatus = 'Failed' | ||
Write-Information "Error processing audit log rules: $($_.Exception.Message)" | ||
$Exception = [string](ConvertTo-Json -Compress -InputObject (Get-CippException -Exception $_)) | ||
$SearchEntity | Add-Member -MemberType NoteProperty -Name Error -Value $Exception | ||
} | ||
Add-CIPPAzDataTableEntity @LogSearchesTable -Entity $SearchEntity -Force | ||
$DataToProcess = ($AuditLogTest).DataToProcess | ||
Write-Information "Audit Logs: Data to process found: $($DataToProcess.count) items" | ||
if ($DataToProcess) { | ||
foreach ($AuditLog in $DataToProcess) { | ||
Write-Information "Processing $($AuditLog.operation)" | ||
$Webhook = @{ | ||
Data = $AuditLog | ||
CIPPURL = [string]$CIPPURL | ||
TenantFilter = $TenantFilter | ||
} | ||
Invoke-CippWebhookProcessing @Webhook | ||
} | ||
} | ||
} | ||
} catch { | ||
Write-Information "Could not get audit log content bundles for $TenantFilter - $LogType, $($_.Exception.Message)" | ||
} | ||
} | ||
|
||
if (($NewBundles | Measure-Object).Count -gt 0) { | ||
Add-CIPPAzDataTableEntity @AuditBundleTable -Entity $NewBundles -Force | ||
Write-Information ($NewBundles | ConvertTo-Json -Depth 5 -Compress) | ||
|
||
$Batch = $NewBundles | Select-Object @{Name = 'ContentId'; Expression = { $_.RowKey } }, @{Name = 'TenantFilter'; Expression = { $_.PartitionKey } }, @{Name = 'FunctionName'; Expression = { 'AuditLogBundleProcessing' } } | ||
$InputObject = [PSCustomObject]@{ | ||
OrchestratorName = 'AuditLogs' | ||
Batch = @($Batch) | ||
SkipLog = $true | ||
Write-Information ( 'Audit Logs: Error {0} line {1} - {2}' -f $_.InvocationInfo.ScriptName, $_.InvocationInfo.ScriptLineNumber, $_.Exception.Message) | ||
} | ||
$InstanceId = Start-NewOrchestration -FunctionName 'CIPPOrchestrator' -InputObject ($InputObject | ConvertTo-Json -Depth 5 -Compress) | ||
Write-Host "Started orchestration with ID = '$InstanceId'" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
50 changes: 50 additions & 0 deletions
50
...Core/Public/Entrypoints/HTTP Functions/Teams-Sharepoint/Invoke-ListSharepointAdminUrl.ps1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
function Invoke-ListSharepointAdminUrl { | ||
<# | ||
.FUNCTIONALITY | ||
Entrypoint | ||
.ROLE | ||
CIPP.Core.Read | ||
#> | ||
[CmdletBinding()] | ||
param( | ||
$Request, | ||
$TriggerMetadata | ||
) | ||
|
||
if ($Request.Query.TenantFilter) { | ||
$TenantFilter = $Request.Query.TenantFilter | ||
|
||
$Tenant = Get-Tenants -TenantFilter $TenantFilter | ||
|
||
if ($Tenant.SharepointAdminUrl) { | ||
$AdminUrl = $Tenant.SharepointAdminUrl | ||
} else { | ||
$tenantName = (New-GraphGetRequest -uri 'https://graph.microsoft.com/beta/sites/root' -asApp $true -tenantid $TenantFilter).id.Split('.')[0] | ||
$AdminUrl = "https://$($tenantName)-admin.sharepoint.com" | ||
$Tenant | Add-Member -MemberType NoteProperty -Name SharepointAdminUrl -Value $AdminUrl | ||
$Table = Get-CIPPTable -TableName 'Tenants' | ||
Add-CIPPAzDataTableEntity @Table -Entity $Tenant -Force | ||
} | ||
|
||
if ($Request.Query.ReturnUrl) { | ||
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ | ||
StatusCode = [HttpStatusCode]::OK | ||
Body = @{ | ||
AdminUrl = $AdminUrl | ||
} | ||
}) | ||
} else { | ||
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ | ||
StatusCode = [HttpStatusCode]::Found | ||
Headers = @{ | ||
Location = $AdminUrl | ||
} | ||
}) | ||
} | ||
} else { | ||
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{ | ||
StatusCode = [HttpStatusCode]::BadRequest | ||
Body = 'TenantFilter is required' | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.