Reports.ps1

using namespace Microsoft.Graph.PowerShell.Models

function Get-GraphReport       {
    <#
        .Synopsis
            Gets reports from MS Graph
        .Example
            >Get-GraphReport -Report MailboxUsageDetail | ft "Display Name", "Storage Used (Byte)"
            Displays mailbox storage used by users - note that
            fields have 'friendly' names which need to be wrapped in quotes
    #>

    [cmdletbinding(DefaultParameterSetName="None")]
    param   (
        #The report to Fetch
        [ValidateSet(
                'EmailActivityCounts', 'EmailActivityUserCounts', 'EmailActivityUserDetail',
                'EmailAppUsageAppsUserCounts', 'EmailAppUsageUserCounts', 'EmailAppUsageUserDetail', 'EmailAppUsageVersionsUserCounts',
                'MailboxUsageDetail', 'MailboxUsageMailboxCounts', 'MailboxUsageQuotaStatusMailboxCounts', 'MailboxUsageStorage',
                'Office365ActivationCounts', 'Office365ActivationsUserCounts', 'Office365ActivationsUserDetail',
                'Office365ActiveUserCounts', 'Office365ActiveUserDetail',  'Office365GroupsActivityCounts', 'Office365GroupsActivityDetail',
                'Office365GroupsActivityFileCounts', 'Office365GroupsActivityGroupCounts', 'Office365GroupsActivityStorage',
                'Office365ServicesUserCounts',
                'OneDriveActivityFileCounts', 'OneDriveActivityUserCounts', 'OneDriveActivityUserDetail', 'OneDriveUsageAccountCounts',
                'OneDriveUsageAccountDetail', 'OneDriveUsageFileCounts', 'OneDriveUsageStorage',
                'SharePointActivityFileCounts', 'SharePointActivityPages', 'SharePointActivityUserCounts',
                'SharePointActivityUserDetail', 'SharePointSiteUsageDetail', 'SharePointSiteUsageFileCounts',
                'SharePointSiteUsagePages', 'SharePointSiteUsageSiteCounts', 'SharePointSiteUsageStorage',
                'SkypeForBusinessActivityCounts', 'SkypeForBusinessActivityUserCounts', 'SkypeForBusinessActivityUserDetail',
                'SkypeForBusinessDeviceUsageDistributionUserCounts','SkypeForBusinessDeviceUsageUserCounts', 'SkypeForBusinessDeviceUsageUserDetail',
                'SkypeForBusinessOrganizerActivityCounts', 'SkypeForBusinessOrganizerActivityMinuteCounts',
                'SkypeForBusinessOrganizerActivityUserCounts', 'SkypeForBusinessParticipantActivityCounts',
                'SkypeForBusinessParticipantActivityMinuteCounts', 'SkypeForBusinessParticipantActivityUserCounts',
                'SkypeForBusinessPeerToPeerActivityCounts', 'SkypeForBusinessPeerToPeerActivityMinuteCounts', 'SkypeForBusinessPeerToPeerActivityUserCounts',
                'TeamsDeviceUsageDistributionUserCounts', 'TeamsDeviceUsageUserCounts', 'TeamsDeviceUsageUserDetail',
                'TeamsUserActivityCounts', 'TeamsUserActivityUserCounts', 'TeamsUserActivityUserDetail',
                'YammerActivityCounts', 'YammerActivityUserCounts', 'YammerActivityUserDetail', 'YammerDeviceUsageDistributionUserCounts',
                'YammerDeviceUsageUserCounts', 'YammerDeviceUsageUserDetail', 'YammerGroupsActivityCounts',
                'YammerGroupsActivityDetail', 'YammerGroupsActivityGroupCounts'
        )]
        [parameter(Mandatory=$true)]
        $Report,
        #Date for the report - this should be a date in the past 30 days. If specified, -Period is ignored. Reports ending in Count, Storage or pages don't support date filtering
        [DateTime]$Date,
        #The range of time for the report in the form "Dn" where n is the number of days. The default is D7, except for Office365Activation activation reports
        [ValidateSet("D7", "D30", "D90", "D180")]
        $Period,
        #If specified the data will be written in CSV format to the path provided, otherwise it will be output to the pipeline
        $Path
    )
    if     ($Date)    {
        if ($report -match 'Counts$|Pages$|Storage$') {Write-Warning -Message 'Reports ending with Counts, Pages or Storage do not support date filtering' ; return }
        if ($report -match '^Office365Activation')    {Write-Warning -Message 'Office365Activation Reports do not support any filtering.'  ; return }
        if ($report -eq    'MailboxUsageDetail')      {Write-Warning -Message 'MailboxUsageDetail does not support date filtering.' ; return}
        $uri = "$GraphUri/reports/microsoft.graph.Get{0}(date={1:yyyy-MM-dd})" -f $Report , $Date
    }
    elseif ($Period)  {
        if ($report -match '^Office365Activation')    {Write-Warning -Message 'Office365Activation Reports do not support any filtering.'  ; return }
        $uri = "$GraphUri/reports/microsoft.graph.Get{0}(period='{1}')"        -f $Report , $Period
    }
    else              {
      if ($report -notmatch '^Office365Activation')  {
        $uri = "$GraphUri/reports/microsoft.graph.Get{0}(period='d7')"         -f $Report
      }
      else {
        $uri = "$GraphUri/reports/microsoft.graph.Get{0}"                      -f $Report
      }
    }
    if ($Path) { Invoke-GraphRequest -Method GET -uri $uri -OutputFilePath $Path}
    else       {
        $Path = [System.IO.Path]::GetTempFileName()
        Invoke-GraphRequest -Method GET -uri $uri -OutputFilePath $Path
        Import-Csv  $Path
        Remove-Item $Path
        }
}

function Get-GraphSignInLog    {
    <#
      .synopsis
        Gets the audit log -requires a priviledged account
      .Description
        This command calls https://graph.microsoft.com/beta/auditLogs/signIns
        which requires consent to use the AuditLog.Read.All Scope this can only be granted to Azure AD apps.
      .Example
        >
        >Get-GraphSignInLog |
        > select Date,UserPrincipalName,appDisplayName,ipAddress,clientAppUsed,browser,device,city,lat,long |
        > Export-Excel -Path .\signin.xlsx -AutoSize -IncludePivotTable -PivotTableName Signins -PivotRows appdisplayName -PivotColumns browser -PivotData @{date='Count'} -show

        Gets the sign-in Log and exports it Excel, creating a PivotTable
    #>

    [cmdletbinding()]
    [outputtype([Microsoft.Graph.PowerShell.Models.MicrosoftGraphSignIn])]
    param   (
            $top = 200
    )
    $i = 1
    Write-Progress -Activity 'Getting Sign-in Auditlog'

    $result  = Invoke-GraphRequest  -Method get -Uri "$GraphUri/auditLogs/signIns?`$top=$top" -SkipHttpErrorCheck -StatusCodeVariable status
    if ($result.error)              {
            Write-Progress -Activity 'Getting Sign-in Auditlog' -Completed
            Write-Warning "An error was returned: '$($result.error.message)' code: $($result.error.code) "
    }
    if ($status -notmatch "2\d\d")  {Write-Warning "Status code returned was $Status ($([System.Net.HttpStatusCode]$status)) which does not look like success."}

    $records = $result.value
    while ($result.'@odata.nextLink' -and $records.count -lt $top) {
        $i ++
        Write-Progress -Activity 'Getting Sign-in Auditlog' -CurrentOperation "Page $i"
        $result   = Invoke-GraphRequest  -Method get -Uri $result.'@odata.nextLink'
        $records += $result.value
    }

    foreach ($r in $records) {
        $r.pstypenames.add('GraphSigninLog')
        $r['RiskEventTypesV2'] = $r['RiskEventTypes_V2'] ;
        [void]$r.Remove('RiskEventTypes_V2');
        New-Object -TypeName MicrosoftGraphSignIn -Property $r
    }
    Write-Progress -Activity 'Getting Sign-in Auditlog'-Completed


}

function Get-GraphDirectoryLog {
    <#
      .synopsis
        Gets the Directory audit log -requires a priviledged account
      .Description
        This command calls https://graph.microsoft.com/beta/auditLogs/directoryAudits
        which requires consent to use the AuditLog.Read.All Scope this can only be granted to Azure AD apps.

    #>

    [cmdletbinding()]
    [outputType([Microsoft.Graph.PowerShell.Models.MicrosoftGraphDirectoryAudit])]
    param   (
    [switch]$all,
    $Top = 100
    )
    $i = 1
    Write-Progress -Activity 'Getting Directory Audits log'
    $uri = "$GraphUri/auditLogs/directoryAudits"
    if (-not $all) {$uri += "?`$Top=$Top"}
    $result  = Invoke-GraphRequest  -Method get -Uri $uri -SkipHttpErrorCheck -StatusCodeVariable status
    if ($result.error)              {Write-Warning "An error was returned: '$($result.error.message)' - code: $($result.error.code) "}

    $records = $result.value
    while ($result.'@odata.nextLink' -and  $records.Count -lt $top) {
        $i ++
        Write-Progress -Activity 'Getting Directory Audits log' -CurrentOperation "Page $i"
        $result   = Invoke-GraphRequest  -Method get -Uri $result.'@odata.nextLink'
        $records += $result.value
    }
    foreach ($r in $records) {
        New-Object -TypeName MicrosoftGraphDirectoryAudit -Property $r
    }
    Write-Progress -Activity 'Getting Directory Audits log' -Completed
}