Advertisement
D0cEvil

O365 - Audit Microsoft Teams meetings

Sep 23rd, 2022
103
1
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PowerShell 9.50 KB | Cybersecurity | 1 0
  1. <#
  2. =============================================================================================
  3. Name:           Audit Microsoft Teams meetings using PowerShell
  4. Description:    This script exports Teams meeting report and attendance report into 2 CSV files.
  5. website:        o365reports.com
  6. Script by:      O365Reports Team
  7. For detailed Script execution:  https://o365reports.com/2021/12/08/microsoft-teams-meeting-attendance-report
  8. ============================================================================================
  9. #>
  10.  
  11. Param
  12. (
  13.     [Parameter(Mandatory = $false)]
  14.     [Nullable[DateTime]]$StartDate,
  15.     [Nullable[DateTime]]$EndDate,
  16.     [switch]$NoMFA,
  17.     [string]$UserName,
  18.     [string]$Password
  19. )
  20.  
  21. Function Connect_Modules
  22. {
  23.  #Check for EXO v2 module inatallation
  24.  $Module = Get-Module ExchangeOnlineManagement -ListAvailable
  25.  if($Module.count -eq 0)
  26.  {
  27.   Write-Host Exchange Online PowerShell V2 module is not available  -ForegroundColor yellow  
  28.   $Confirm= Read-Host Are you sure you want to install module? [Y] Yes [N] No
  29.   if($Confirm -match "[yY]")
  30.   {
  31.    Write-host "Installing Exchange Online PowerShell module"
  32.    Install-Module ExchangeOnlineManagement -Repository PSGallery -AllowClobber -Force
  33.   }
  34.   else
  35.   {
  36.    Write-Host EXO V2 module is required to connect Exchange Online.Please install module using Install-Module ExchangeOnlineManagement cmdlet.
  37.    Exit
  38.   }
  39.  }
  40.  #Check for Azure AD module
  41.  $Module = Get-Module AzureAD -ListAvailable
  42.  if($Module.count -eq 0)
  43.  {
  44.   Write-Host Azure AD module is not available  -ForegroundColor yellow  
  45.   $Confirm= Read-Host Are you sure you want to install the module? [Y] Yes [N] No
  46.   if($Confirm -match "[yY]")
  47.   {
  48.    Write-host "Installing AzureAD PowerShell module"
  49.    Install-Module AzureAD -Repository PSGallery -AllowClobber -Force
  50.   }
  51.   else
  52.   {
  53.    Write-Host AzureAD module is required to generate the report.Please install module using Install-Module AzureAD cmdlet.
  54.    Exit
  55.   }
  56.  }
  57.  
  58.  #Authentication using non-MFA
  59.  if($NoMFA.IsPresent)
  60.  {
  61.   #Storing credential in script for scheduling purpose/ Passing credential as parameter
  62.   if(($UserName -ne "") -and ($Password -ne ""))
  63.   {
  64.    $SecuredPassword = ConvertTo-SecureString -AsPlainText $Password -Force
  65.    $Credential  = New-Object System.Management.Automation.PSCredential $UserName,$SecuredPassword
  66.   }
  67.   else
  68.   {
  69.    $Credential=Get-Credential -Credential $null
  70.   }
  71.   Write-Host "Connecting Azure AD..."
  72.   Connect-AzureAD -Credential $Credential | Out-Null
  73.   Write-Host "Connecting Exchange Online PowerShell..."
  74.   Connect-ExchangeOnline -Credential $Credential
  75.  }
  76.  #Connect to Exchange Online and AzureAD module using MFA
  77.  else
  78.  {
  79.   Write-Host "Connecting Exchange Online PowerShell..."
  80.   Connect-ExchangeOnline
  81.   Write-Host "Connecting Azure AD..."
  82.   Connect-AzureAD | Out-Null
  83.  }
  84. }
  85.  
  86. Function Get_TeamMeetings
  87. {
  88.  $Result=""  
  89.  $Results=@()  
  90.  $Count=0
  91.  Search-UnifiedAuditLog -StartDate $StartDate -EndDate $EndDate -Operations "MeetingDetail" -ResultSize 5000 | ForEach-Object {
  92.   $Count++
  93.   Write-Progress -Activity "`n     Retrieving Teams meetings data from $StartDate to $EndDate.."`n" Processed Teams meetings count: $Count"
  94.   $AuditData=$_.AuditData  | ConvertFrom-Json
  95.   $MeetingID=$AuditData.ID
  96.   $CreatedBy=$AuditData.UserId
  97.   $StartTime=(Get-Date($AuditData.StartTime)).ToLocalTime()
  98.   $EndTime=(Get-Date($AuditData.EndTime)).ToLocalTime()
  99.   $MeetingURL=$AuditData.MeetingURL
  100.   $MeetingType=$AuditData.ItemName
  101.   $Result=@{'Meeting id'=$MeetingID;'Created By'=$CreatedBy;'Start Time'=$Star=$StartTime;'End Time'=$EndTime;'Meeting Type'=$MeetingType;'Meeting Link'=$MeetingURL;'More Info'=$AuditData}
  102.   $Results= New-Object PSObject -Property $Result  
  103.   $Results | Select-Object 'Meeting id','Created By','Start Time','End Time','Meeting Type','Meeting Link','More Info' | Export-Csv -Path $ExportCSV -Notype -Append
  104.  }
  105.  Write-Host $Count meetings details are exported. -ForegroundColor Green
  106. }
  107.  
  108. $MaxStartDate=((Get-Date).AddDays(-89)).Date
  109. #Getting Teams meeting attendance report for past 90 days
  110. if(($StartDate -eq $null) -and ($EndDate -eq $null))
  111. {
  112.  $EndDate=(Get-Date)#.Date
  113.  $StartDate=$MaxStartDate
  114. }
  115. #Getting start date to generate Teams meetings attendance report
  116. While($true)
  117. {
  118.  if ($StartDate -eq $null)
  119.  {
  120.   $StartDate=Read-Host Enter start time for report generation '(Eg:11/23/2021)'
  121.  }
  122.  Try
  123.  {
  124.   $Date=[DateTime]$StartDate
  125.   if($Date -ge $MaxStartDate)
  126.   {
  127.    break
  128.   }
  129.   else
  130.   {
  131.    Write-Host `nAudit can be retrieved only for past 90 days. Please select a date after $MaxStartDate -ForegroundColor Red
  132.    return
  133.   }
  134.  }
  135.  Catch
  136.  {
  137.   Write-Host `nNot a valid date -ForegroundColor Red
  138.  }
  139. }
  140.  
  141.  
  142. #Getting end date for teams attendance report
  143. While($true)
  144. {
  145.  if ($EndDate -eq $null)
  146.  {
  147.   $EndDate=Read-Host Enter End time for report generation '(Eg: 11/23/2021)'
  148.  }
  149.  Try
  150.  {
  151.   $Date=[DateTime]$EndDate
  152.   if($EndDate -lt ($StartDate))
  153.   {
  154.    Write-Host End time should be later than start time -ForegroundColor Red
  155.    return
  156.   }
  157.   break
  158.  }
  159.  Catch
  160.  {
  161.   Write-Host `nNot a valid date -ForegroundColor Red
  162.  }
  163. }
  164.  
  165. $OutputCSV=".\TeamsMeetingAttendanceReport_$((Get-Date -format yyyy-MMM-dd-ddd` hh-mm` tt).ToString()).csv"
  166. $ExportCSV=".\TeamsMeetingsReport_$((Get-Date -format yyyy-MMM-dd-ddd` hh-mm` tt).ToString()).csv"
  167. $IntervalTimeInMinutes=1440    #$IntervalTimeInMinutes=Read-Host Enter interval time period '(in minutes)'
  168. $CurrentStart=$StartDate
  169. $CurrentEnd=$CurrentStart.AddMinutes($IntervalTimeInMinutes)
  170.  
  171. #Check whether CurrentEnd exceeds EndDate
  172. if($CurrentEnd -gt $EndDate)
  173. {
  174.  $CurrentEnd=$EndDate
  175. }
  176.  
  177. if($CurrentStart -eq $CurrentEnd)
  178. {
  179.  Write-Host Start and end time are same.Please enter different time range -ForegroundColor Red
  180.  Exit
  181. }
  182.  
  183. Connect_Modules
  184. Get_TeamMeetings
  185. $CurrentResultCount=0
  186. $AggregateResultCount=0
  187. Write-Host `nGenerating Teams meeting attendance report from $StartDate to $EndDate...
  188. $ProcessedAuditCount=0
  189. $OutputEvents=0
  190. $ExportResult=""  
  191. $ExportResults=@()  
  192. $RetriveOperation="MeetingParticipantDetail"
  193. while($true)
  194. {
  195.  #Getting Teams meeting participants report for the given time range
  196.  Search-UnifiedAuditLog -StartDate $CurrentStart -EndDate $CurrentEnd -Operations $RetriveOperation -SessionId s -SessionCommand ReturnLargeSet -ResultSize 5000 | ForEach-Object {
  197.   $ResultCount++
  198.   $ProcessedAuditCount++
  199.   Write-Progress -Activity "`n     Retrieving Team meeting participant report..."`n" Processed audit record count: $ProcessedAuditCount"
  200.   $AuditData=$_.AuditData  | ConvertFrom-Json
  201.   $MeetingID=$AuditData.MeetingDetailId
  202.   $CreatedBy=$_.UserIDs
  203.   $AttendeesInfo=($AuditData.Attendees)
  204.   $Attendees=$AttendeesInfo.userObjectId
  205.   $AttendeesType=$AttendeesInfo.RecipientType
  206.   if($AttendeesType -ne "User")
  207.   {
  208.    $Attendees=$AttendeesInfo.DisplayName
  209.   }
  210.   else
  211.   {
  212.    $Attendees=(Get-AzureADUser -ObjectId $Attendees).UserPrincipalName
  213.   }
  214.   $JoinTime=(Get-Date($AuditData.JoinTime)).ToLocalTime()  #Get-Date($AuditData.JoinTime) Uncomment to view the Activity Time in UTC
  215.   $LeaveTime=(Get-Date($AuditData.LeaveTime)).ToLocalTime()
  216.  
  217.    
  218.   #Export result to csv
  219.   $OutputEvents++
  220.   $ExportResult=@{'Meeting id'=$MeetingID;'Created By'=$CreatedBy;'Attendees'=$Attendees;'Attendee Type'=$AttendeesType;'Joined Time'=$JoinTime;'Left Time'=$LeaveTime;'More Info'=$AuditData}
  221.   $ExportResults= New-Object PSObject -Property $ExportResult  
  222.   $ExportResults | Select-Object 'Meeting id','Created By','Attendees','Attendee Type','Joined Time','Left Time','More Info' | Export-Csv -Path $OutputCSV -Notype -Append
  223.  }
  224.  
  225.  $currentResultCount=$currentResultCount+$ResultCount
  226.  if($CurrentResultCount -ge 50000)
  227.  {
  228.   Write-Host Retrieved max record for current range.Proceeding further may cause data loss or rerun the script with reduced time interval. -ForegroundColor Red
  229.   $Confirm=Read-Host `nAre you sure you want to continue? [Y] Yes [N] No
  230.   if($Confirm -match "[Y]")
  231.   {
  232.    Write-Host Proceeding audit log collection with data loss
  233.    [DateTime]$CurrentStart=$CurrentEnd
  234.    [DateTime]$CurrentEnd=$CurrentStart.AddMinutes($IntervalTimeInMinutes)
  235.    $CurrentResultCount=0
  236.    if($CurrentEnd -gt $EndDate)
  237.    {
  238.     $CurrentEnd=$EndDate
  239.    }
  240.   }
  241.   else
  242.   {
  243.    Write-Host Please rerun the script with reduced time interval -ForegroundColor Red
  244.    Exit
  245.   }
  246.  }
  247.  
  248.  if($ResultCount -lt 5000)
  249.  {
  250.   if($CurrentEnd -eq $EndDate)
  251.   {
  252.    break
  253.   }
  254.   $CurrentStart=$CurrentEnd
  255.   if($CurrentStart -gt (Get-Date))
  256.   {
  257.    break
  258.   }
  259.   $CurrentEnd=$CurrentStart.AddMinutes($IntervalTimeInMinutes)
  260.   $CurrentResultCount=0
  261.   if($CurrentEnd -gt $EndDate)
  262.   {
  263.    $CurrentEnd=$EndDate
  264.   }
  265.  }                                                                                            
  266.  $ResultCount=0
  267. }
  268.  
  269. #Open output file after execution
  270. If($OutputEvents -eq 0)
  271. {
  272.  Write-Host No records found
  273. }
  274. else
  275. {
  276.  Write-Host `nThe Teams meeting attendance report contains $OutputEvents audit records -ForegroundColor Green
  277.  if((Test-Path -Path $OutputCSV) -eq "True")
  278.  {
  279.   Write-Host `nThe Teams meetings attendance report available in $OutputCSV -ForegroundColor Cyan
  280.   $Prompt = New-Object -ComObject wscript.shell  
  281.   $UserInput = $Prompt.popup("Do you want to open output file?",`  
  282.  0,"Open Output File",4)  
  283.   If ($UserInput -eq 6)  
  284.   {  
  285.    Invoke-Item "$OutputCSV"  
  286.    Invoke-Item "$ExportCSV"
  287.   }
  288.  }
  289. }
  290.  
  291. #Disconnect Exchange Online session
  292. Disconnect-ExchangeOnline -Confirm:$false -InformationAction Ignore -ErrorAction SilentlyContinue
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement