Public/AuditLog.ps1
|
<# .SYNOPSIS Retrieves audit log entries from the Keepit platform .DESCRIPTION Gets audit log records from the Keepit platform with optional filtering by date range. Audit logs contain the history of actions made by Keepit users and are never cleared. Returns human-readable audit log entries with action details, user information, and metadata. .PARAMETER StartTime Start of the time window for audit log entries. If not specified along with EndTime, defaults to the last 14 days. .PARAMETER EndTime End of the time window for audit log entries. If not specified along with StartTime, defaults to the last 14 days. .PARAMETER ResultSize Maximum number of audit log entries to return. Default is 100. Maximum is 10000. .PARAMETER Area Filter by audit log area. Valid values: 'User events', 'Backup/Restore', 'Account events', 'Subaccount events'. .EXAMPLE Get-KeepitAuditLog Retrieves the last 100 audit log entries from the past 14 days .EXAMPLE Get-KeepitAuditLog -ResultSize 500 Retrieves up to 500 audit log entries from the past 14 days .EXAMPLE Get-KeepitAuditLog -StartTime (Get-Date).AddDays(-7) -EndTime (Get-Date) Retrieves audit log entries from the last 7 days .EXAMPLE Get-KeepitAuditLog -Area 'Backup/Restore' -ResultSize 50 Retrieves the last 50 backup/restore audit log entries .OUTPUTS PSCustomObject[] - Array of audit log entry objects with properties: - Time: Timestamp of the action - Account: Account ID - Message: Human-readable description of the action - Area: Category of the action (e.g., 'User events', 'Backup/Restore') - Company: Company name - Acl: ACL name for the action - Method: HTTP method used - Allowed: Whether the action was allowed - Succeeded: Whether the action succeeded (based on HTTP return code) - ClientIP: IP address of the client - Device: Device/connector GUID (if applicable) - Token: UPN or name of the API token that performed the action .NOTES Requires an active connection via Connect-KeepitService. Maximum 10,000 records returned per request. #> function Get-KeepitAuditLog { [CmdletBinding()] [OutputType([PSCustomObject])] param( [Parameter(Mandatory = $false)] [DateTime]$StartTime, [Parameter(Mandatory = $false)] [DateTime]$EndTime, [Parameter(Mandatory = $false)] [ValidateRange(1, 10000)] [int]$ResultSize = 100, [Parameter(Mandatory = $false)] [ValidateSet('User events', 'Backup/Restore', 'Account events', 'Subaccount events')] [string]$Area ) try { Write-Verbose "=== Get-KeepitAuditLog ===" # Validate date parameters $hasStartTime = $PSBoundParameters.ContainsKey('StartTime') $hasEndTime = $PSBoundParameters.ContainsKey('EndTime') if ($hasStartTime -and -not $hasEndTime) { throw "StartTime specified without EndTime. Both StartTime and EndTime must be provided together, or neither." } if ($hasEndTime -and -not $hasStartTime) { throw "EndTime specified without StartTime. Both StartTime and EndTime must be provided together, or neither." } if ($hasStartTime -and $hasEndTime -and $StartTime -ge $EndTime) { throw "StartTime must be less than EndTime. StartTime: $StartTime, EndTime: $EndTime" } # Get authentication header and base URL $authHeader = Get-AuthHeader $baseUrl = Get-KeepitBaseUrl Write-Verbose "Base URL: $baseUrl" $userId = $script:KeepitUserId if (-not $userId) { throw "Unable to determine user ID. Ensure you are connected using Connect-KeepitService." } Write-Verbose "User ID: $userId" # Build request URI with pagination parameters # Note: API returns 2 fewer records than requested, so add 2 to compensate $apiLimit = [Math]::Min($ResultSize + 2, 10000) $uri = "$baseUrl/audit/filter/pretty?limit=$apiLimit&offset=0" $headers = @{ 'Authorization' = $authHeader 'Content-Type' = 'application/xml' 'Accept' = 'application/vnd.keepit.v4+xml' } # Build filter XML $escapedUserId = [System.Security.SecurityElement]::Escape($userId) $filterXml = "<filter><account>$escapedUserId</account>" if ($hasStartTime -and $hasEndTime) { $fromTimestamp = $StartTime.ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ', [System.Globalization.CultureInfo]::InvariantCulture) $toTimestamp = $EndTime.ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ', [System.Globalization.CultureInfo]::InvariantCulture) $filterXml += "<from>$fromTimestamp</from><to>$toTimestamp</to>" Write-Verbose "Date range filter: $fromTimestamp to $toTimestamp" } else { Write-Verbose "No date range specified - API will default to last 14 days" } if ($PSBoundParameters.ContainsKey('Area')) { $escapedArea = [System.Security.SecurityElement]::Escape($Area) $filterXml += "<area>$escapedArea</area>" Write-Verbose "Area filter: $Area" } $filterXml += "</filter>" Write-Verbose "=== API Request Details ===" Write-Verbose "Method: PUT" Write-Verbose "URI: $uri" Write-Verbose "Request Body: $filterXml" # Make API call $response = Invoke-RestMethod -Uri $uri -Method Put -Headers $headers -Body $filterXml -ErrorAction Stop Write-Verbose "=== API Response Received ===" Write-Verbose "Response Type: $($response.GetType().FullName)" # Parse response $records = @() if ($response.audit.record) { # Normalize to array if ($response.audit.record -is [System.Array]) { $records = $response.audit.record Write-Verbose "Found $($records.Count) audit log records" } else { $records = @($response.audit.record) Write-Verbose "Found 1 audit log record" } } else { Write-Verbose "No audit log records found in response" return } # Process and output each record foreach ($record in $records) { [PSCustomObject]@{ Time = if ($record.time) { $record.time } else { $null } Account = if ($record.account) { $record.account } else { $null } Message = if ($record.message) { $record.message } else { '' } Area = if ($record.area) { $record.area } else { $null } Company = if ($record.company) { $record.company } else { $null } Acl = if ($record.acl) { $record.acl } else { $null } Method = if ($record.method) { $record.method } else { $null } Allowed = if ($record.allowed -eq 'true' -or $record.allowed -eq $true) { $true } else { $false } Succeeded = if ($record.succeeded -eq 'true' -or $record.succeeded -eq $true) { $true } else { $false } ClientIP = if ($record.'client-ip') { $record.'client-ip' } else { $null } Device = if ($record.device) { $record.device } else { $null } Token = if ($record.token) { $record.token } else { $null } } } Write-Verbose "=== End Get-KeepitAuditLog ===" } catch { $PSCmdlet.ThrowTerminatingError( [System.Management.Automation.ErrorRecord]::new( [System.Exception]::new("Failed to retrieve audit logs: $($_.Exception.Message)", $_.Exception), 'KeepitApiError', [System.Management.Automation.ErrorCategory]::ConnectionError, $null ) ) } } |