diff --git a/Get M365 Inactive User Report/GetM365InactiveUserReport.ps1 b/Get M365 Inactive User Report/GetM365InactiveUserReport.ps1 new file mode 100644 index 0000000..72b1b40 --- /dev/null +++ b/Get M365 Inactive User Report/GetM365InactiveUserReport.ps1 @@ -0,0 +1,230 @@ +<# +============================================================================================= +Name: Export Microsoft 365 Inactive Users Report using MS Graph PowerShell +Version: 1.0 +website: o365reports.com + +Script Highlights: +~~~~~~~~~~~~~~~~~ +1.The single script allows you to generate 10+ different inactive user reports. +2.The script can be executed with an MFA-enabled account too. +3.The script supports Certificate-based authentication (CBA). +4.Provides details about non-interactive sign-ins too. +5.You can generate reports based on inactive days. +6.Helps to filter never logged-in users alone. +7.Generates report for sign-in enabled users alone. +8.Supports filteringlicensed users alone. +9.Gets inactive external users report. +10.Export results to CSV file. +11.The assigned licenses column will show you the user-friendly-name like ‘Office 365 Enterprise E3’ rather than ‘ENTERPRISEPACK’. +12.Automatically installs the MS Graph PowerShell module (if not installed already) upon your confirmation. +13.The script is scheduler friendly. + +For detailed Script execution: https://o365reports.com/2023/06/21/microsoft-365-inactive-user-report-ms-graph-powershell +============================================================================================ +#> + +Param +( + [int]$InactiveDays, + [int]$InactiveDays_NonInteractive, + [switch]$ReturnNeverLoggedInUser, + [switch]$EnabledUsersOnly, + [switch]$DisabledUsersOnly, + [switch]$LicensedUsersOnly, + [switch]$ExternalUsersOnly, + [switch]$CreateSession, + [string]$TenantId, + [string]$ClientId, + [string]$CertificateThumbprint +) + +Function Connect_MgGraph +{ + #Check for module installation + $Module=Get-Module -Name microsoft.graph -ListAvailable + if($Module.count -eq 0) + { + Write-Host Microsoft Graph PowerShell SDK is not available -ForegroundColor yellow + $Confirm= Read-Host Are you sure you want to install module? [Y] Yes [N] No + if($Confirm -match "[yY]") + { + Write-host "Installing Microsoft Graph PowerShell module..." + Install-Module Microsoft.Graph -Repository PSGallery -Scope CurrentUser -AllowClobber -Force + } + else + { + Write-Host "Microsoft Graph PowerShell module is required to run this script. Please install module using Install-Module Microsoft.Graph cmdlet." + Exit + } + } + #Disconnect Existing MgGraph session + if($CreateSession.IsPresent) + { + Disconnect-MgGraph + } + + #Connecting to MgGraph beta + Select-MgProfile -Name beta + Write-Host Connecting to Microsoft Graph... + if(($TenantId -ne "") -and ($ClientId -ne "") -and ($CertificateThumbprint -ne "")) + { + Connect-MgGraph -TenantId $TenantId -AppId $ClientId -CertificateThumbprint $CertificateThumbprint + } + else + { + Connect-MgGraph -Scopes "User.Read.All","AuditLog.read.All" + } +} +Connect_MgGraph + +$ExportCSV = ".\InactiveM365UserReport_$((Get-Date -format yyyy-MMM-dd-ddd` hh-mm-ss` tt).ToString()).csv" +$ExportResult="" +$ExportResults=@() + +#Get friendly name of license plan from external file +$FriendlyNameHash=Get-Content -Raw -Path .\LicenseFriendlyName.txt -ErrorAction Stop | ConvertFrom-StringData + +$Count=0 +$PrintedUser=0 +#retrieve users +$RequiredProperties=@('UserPrincipalName','EmployeeId','CreatedDateTime','AccountEnabled','Department','JobTitle','RefreshTokensValidFromDateTime','SigninActivity') +Get-MgUser -All -Property $RequiredProperties | select $RequiredProperties | ForEach-Object { + $Count++ + $UPN=$_.UserPrincipalName + Write-Progress -Activity "`n Processing user: $Count - $UPN" + $EmployeeId=$_.EmployeeId + $LastInteractiveSignIn=$_.SignInActivity.LastSignInDateTime + $LastNon_InteractiveSignIn=$_.SignInActivity.LastNonInteractiveSignInDateTime + $CreatedDate=$_.CreatedDateTime + $AccountEnabled=$_.AccountEnabled + $Department=$_.Department + $JobTitle=$_.JobTitle + $RefreshTokenValidFrom=$_.RefreshTokensValidFromDateTime + #Calculate Inactive days + if($LastInteractiveSignIn -eq $null) + { + $LastInteractiveSignIn = "Never Logged In" + $InactiveDays_InteractiveSignIn = "-" + } + else + { + $InactiveDays_InteractiveSignIn = (New-TimeSpan -Start $LastInteractiveSignIn).Days + } + if($LastNon_InteractiveSignIn -eq $null) + { + $LastNon_InteractiveSignIn = "Never Logged In" + $InactiveDays_NonInteractiveSignIn = "-" + } + else + { + $InactiveDays_NonInteractiveSignIn = (New-TimeSpan -Start $LastNon_InteractiveSignIn).Days + } + if($AccountEnabled -eq $true) + { + $AccountStatus='Enabled' + } + else + { + $AccountStatus='Disabled' + } + + #Get licenses assigned to mailboxes + $Licenses = (Get-MgUserLicenseDetail -UserId $UPN).SkuPartNumber + $AssignedLicense = @() + + #Convert license plan to friendly name + if($Licenses.count -eq 0) + { + $LicenseDetails = "No License Assigned" + } + else + { + foreach($License in $Licenses) + { + $EasyName = $FriendlyNameHash[$License] + if(!($EasyName)) + {$NamePrint = $License} + else + {$NamePrint = $EasyName} + $AssignedLicense += $NamePrint + } + $LicenseDetails = $AssignedLicense -join ", " + } + $Print=1 + + + #Inactive days based on interactive signins filter + if($InactiveDays_InteractiveSignIn -ne "-") + { + if(($InactiveDays -ne "") -and ($InactiveDays -gt $InactiveDays_InteractiveSignIn)) + { + $Print=0 + } + } + + #Inactive days based on non-interactive signins filter + if($InactiveDays_NonInteractiveSignIn -ne "-") + { + if(($InactiveDays_NonInteractive -ne "") -and ($InactiveDays_NonInteractive -gt $InactiveDays_NonInteractiveSignIn)) + { + $Print=0 + } + } + + #Never Logged In user + if(($ReturnNeverLoggedInUser.IsPresent) -and ($LastInteractiveSignIn -ne "Never Logged In")) + { + $Print=0 + } + + #Filter for external users + if(($ExternalUsersOnly.IsPresent) -and ($UPN -notmatch '#EXT#')) + { + $Print=0 + } + + #Signin Allowed Users + if($EnabledUsersOnly.IsPresent -and $AccountStatus -eq 'Disabled') + { + $Print=0 + } + + #Signin disabled users + if($DisabledUsersOnly.IsPresent -and $AccountStatus -eq 'Enabled') + { + $Print=0 + } + + #Licensed Users ony + if($LicensedUsersOnly -and $Licenses.Count -eq 0) + { + $Print=0 + } + + #Export users to output file + if($Print -eq 1) + { + $PrintedUser++ + $ExportResult=[PSCustomObject]@{'UPN'=$UPN;'Creation Date'=$CreatedDate;'Last Interactive SignIn Date'=$LastInteractiveSignIn;'Last Non Interactive SignIn Date'=$LastNon_InteractiveSignIn;'Inactive Days(Interactive SignIn)'=$InactiveDays_InteractiveSignIn;'Inactive Days(Non-Interactive Signin)'=$InactiveDays_NonInteractiveSignin;'Refresh Token Valid From'=$RefreshTokenValidFrom;'Emp id'=$EmployeeId;'License Details'=$LicenseDetails;'Account Status'=$AccountStatus;'Department'=$Department;'Job Title'=$JobTitle} + $ExportResult | Export-Csv -Path $ExportCSV -Notype -Append + } +} + +#Open output file after execution +Write-Host `nScript executed successfully +if((Test-Path -Path $ExportCSV) -eq "True") +{ + Write-Host "Exported report has $PrintedUser user(s)" + $Prompt = New-Object -ComObject wscript.shell + $UserInput = $Prompt.popup("Do you want to open output file?",` 0,"Open Output File",4) + if ($UserInput -eq 6) + { + Invoke-Item "$ExportCSV" + } + Write-Host "Detailed report available in: $ExportCSV" +} +else +{ + Write-Host "No user found" -ForegroundColor Red +} \ No newline at end of file diff --git a/Get M365 Inactive User Report/LicenseFriendlyName.txt b/Get M365 Inactive User Report/LicenseFriendlyName.txt new file mode 100644 index 0000000..edddefa --- /dev/null +++ b/Get M365 Inactive User Report/LicenseFriendlyName.txt @@ -0,0 +1,239 @@ +AAD_BASIC= Azure Active Directory Basic + AAD_PREMIUM= Azure Active Directory Premium + AAD_PREMIUM_P1= Azure Active Directory Premium P1 + AAD_PREMIUM_P2= Azure Active Directory Premium P2 + ADALLOM_O365= Office 365 Advanced Security Management + ADALLOM_STANDALONE= Microsoft Cloud App Security + ADALLOM_S_O365= POWER BI STANDALONE + ADALLOM_S_STANDALONE= Microsoft Cloud App Security + ATA= Azure Advanced Threat Protection for Users + ATP_ENTERPRISE= Exchange Online Advanced Threat Protection + ATP_ENTERPRISE_FACULTY= Exchange Online Advanced Threat Protection + BI_AZURE_P0= Power BI (free) + BI_AZURE_P1= Power BI Reporting and Analytics + BI_AZURE_P2= Power BI Pro + CCIBOTS_PRIVPREV_VIRAL= Dynamics 365 AI for Customer Service Virtual Agents Viral SKU + CRMINSTANCE= Microsoft Dynamics CRM Online Additional Production Instance (Government Pricing) + CRMIUR= CRM for Partners + CRMPLAN1= Microsoft Dynamics CRM Online Essential (Government Pricing) + CRMPLAN2= Dynamics CRM Online Plan 2 + CRMSTANDARD= CRM Online + CRMSTORAGE= Microsoft Dynamics CRM Online Additional Storage + CRMTESTINSTANCE= CRM Test Instance + DESKLESS= Microsoft StaffHub + DESKLESSPACK= Office 365 (Plan K1) + DESKLESSPACK_GOV= Microsoft Office 365 (Plan K1) for Government + DESKLESSPACK_YAMMER= Office 365 Enterprise K1 with Yammer + DESKLESSWOFFPACK= Office 365 (Plan K2) + DESKLESSWOFFPACK_GOV= Microsoft Office 365 (Plan K2) for Government + DEVELOPERPACK= Office 365 Enterprise E3 Developer + DEVELOPERPACK_E5= Microsoft 365 E5 Developer(without Windows and Audio Conferencing) + DMENTERPRISE= Microsoft Dynamics Marketing Online Enterprise + DYN365_ENTERPRISE_CUSTOMER_SERVICE= Dynamics 365 for Customer Service Enterprise Edition + DYN365_ENTERPRISE_P1_IW= Dynamics 365 P1 Trial for Information Workers + DYN365_ENTERPRISE_PLAN1= Dynamics 365 Plan 1 Enterprise Edition + DYN365_ENTERPRISE_SALES= Dynamics 365 for Sales Enterprise Edition + DYN365_ENTERPRISE_SALES_CUSTOMERSERVICE= Dynamics 365 for Sales and Customer Service Enterprise Edition + DYN365_ENTERPRISE_TEAM_MEMBERS= Dynamics 365 for Team Members Enterprise Edition + DYN365_FINANCIALS_BUSINESS_SKU= Dynamics 365 for Financials Business Edition + DYN365_MARKETING_USER= Dynamics 365 for Marketing USL + DYN365_MARKETING_APP= Dynamics 365 Marketing + DYN365_SALES_INSIGHTS= Dynamics 365 AI for Sales + D365_SALES_PRO= Dynamics 365 for Sales Professional + Dynamics_365_for_Operations= Dynamics 365 Unf Ops Plan Ent Edition + ECAL_SERVICES= ECAL + EMS= Enterprise Mobility + Security E3 + EMSPREMIUM= Enterprise Mobility + Security E5 + ENTERPRISEPACK= Office 365 Enterprise E3 + ENTERPRISEPACKLRG= Office 365 Enterprise E3 LRG + ENTERPRISEPACKWITHOUTPROPLUS= Office 365 Enterprise E3 without ProPlus Add-on + ENTERPRISEPACK_B_PILOT= Office 365 (Enterprise Preview) + ENTERPRISEPACK_FACULTY= Office 365 (Plan A3) for Faculty + ENTERPRISEPACK_GOV= Microsoft Office 365 (Plan G3) for Government + ENTERPRISEPACK_STUDENT= Office 365 (Plan A3) for Students + ENTERPRISEPREMIUM= Enterprise E5 (with Audio Conferencing) + ENTERPRISEPREMIUM_NOPSTNCONF= Enterprise E5 (without Audio Conferencing) + ENTERPRISEWITHSCAL= Office 365 Enterprise E4 + ENTERPRISEWITHSCAL_FACULTY= Office 365 (Plan A4) for Faculty + ENTERPRISEWITHSCAL_GOV= Microsoft Office 365 (Plan G4) for Government + ENTERPRISEWITHSCAL_STUDENT= Office 365 (Plan A4) for Students + EOP_ENTERPRISE= Exchange Online Protection + EOP_ENTERPRISE_FACULTY= Exchange Online Protection for Faculty + EQUIVIO_ANALYTICS= Office 365 Advanced Compliance + EQUIVIO_ANALYTICS_FACULTY= Office 365 Advanced Compliance for Faculty + ESKLESSWOFFPACK_GOV= Microsoft Office 365 (Plan K2) for Government + EXCHANGEARCHIVE= Exchange Online Archiving + EXCHANGEARCHIVE_ADDON= Exchange Online Archiving for Exchange Online + EXCHANGEDESKLESS= Exchange Online Kiosk + EXCHANGEENTERPRISE= Exchange Online Plan 2 + EXCHANGEENTERPRISE_FACULTY= Exch Online Plan 2 for Faculty + EXCHANGEENTERPRISE_GOV= Microsoft Office 365 Exchange Online (Plan 2) only for Government + EXCHANGEESSENTIALS= Exchange Online Essentials + EXCHANGESTANDARD= Office 365 Exchange Online Only + EXCHANGESTANDARD_GOV= Microsoft Office 365 Exchange Online (Plan 1) only for Government + EXCHANGESTANDARD_STUDENT= Exchange Online (Plan 1) for Students + EXCHANGETELCO= Exchange Online POP + EXCHANGE_ANALYTICS= Microsoft MyAnalytics + EXCHANGE_L_STANDARD= Exchange Online (Plan 1) + EXCHANGE_S_ARCHIVE_ADDON_GOV= Exchange Online Archiving + EXCHANGE_S_DESKLESS= Exchange Online Kiosk + EXCHANGE_S_DESKLESS_GOV= Exchange Kiosk + EXCHANGE_S_ENTERPRISE= Exchange Online (Plan 2) Ent + EXCHANGE_S_ENTERPRISE_GOV= Exchange Plan 2G + EXCHANGE_S_ESSENTIALS= Exchange Online Essentials + EXCHANGE_S_FOUNDATION= Exchange Foundation for certain SKUs + EXCHANGE_S_STANDARD= Exchange Online (Plan 2) + EXCHANGE_S_STANDARD_MIDMARKET= Exchange Online (Plan 1) + FLOW_FREE= Microsoft Flow (Free) + FLOW_O365_P2= Flow for Office 365 + FLOW_O365_P3= Flow for Office 365 + FLOW_P1= Microsoft Flow Plan 1 + FLOW_P2= Microsoft Flow Plan 2 + FORMS_PLAN_E3= Microsoft Forms (Plan E3) + FORMS_PLAN_E5= Microsoft Forms (Plan E5) + INFOPROTECTION_P2= Azure Information Protection Premium P2 + INTUNE_A= Windows Intune Plan A + INTUNE_A_VL= Intune (Volume License) + INTUNE_O365= Mobile Device Management for Office 365 + INTUNE_STORAGE= Intune Extra Storage + IT_ACADEMY_AD= Microsoft Imagine Academy + LITEPACK= Office 365 (Plan P1) + LITEPACK_P2= Office 365 Small Business Premium + LOCKBOX= Customer Lockbox + LOCKBOX_ENTERPRISE= Customer Lockbox + MCOCAP= Command Area Phone + MCOEV= Skype for Business Cloud PBX + MCOIMP= Skype for Business Online (Plan 1) + MCOLITE= Lync Online (Plan 1) + MCOMEETADV= PSTN conferencing + MCOPLUSCAL= Skype for Business Plus CAL + MCOPSTN1= Skype for Business Pstn Domestic Calling + MCOPSTN2= Skype for Business Pstn Domestic and International Calling + MCOSTANDARD= Skype for Business Online Standalone Plan 2 + MCOSTANDARD_GOV= Lync Plan 2G + MCOSTANDARD_MIDMARKET= Lync Online (Plan 1) + MCVOICECONF= Lync Online (Plan 3) + MDM_SALES_COLLABORATION= Microsoft Dynamics Marketing Sales Collaboration + MEE_FACULTY= Minecraft Education Edition Faculty + MEE_STUDENT= Minecraft Education Edition Student + MEETING_ROOM= Meeting Room + MFA_PREMIUM= Azure Multi-Factor Authentication + MICROSOFT_BUSINESS_CENTER= Microsoft Business Center + MICROSOFT_REMOTE_ASSIST= Dynamics 365 Remote Assist + MIDSIZEPACK= Office 365 Midsize Business + MINECRAFT_EDUCATION_EDITION= Minecraft Education Edition Faculty + MS-AZR-0145P= Azure + MS_TEAMS_IW= Microsoft Teams + NBPOSTS= Microsoft Social Engagement Additional 10k Posts (minimum 100 licenses) (Government Pricing) + NBPROFESSIONALFORCRM= Microsoft Social Listening Professional + O365_BUSINESS= Microsoft 365 Apps for business + O365_BUSINESS_ESSENTIALS= Microsoft 365 Business Basic + O365_BUSINESS_PREMIUM= Microsoft 365 Business Standard + OFFICE365_MULTIGEO= Multi-Geo Capabilities in Office 365 + OFFICESUBSCRIPTION= Microsoft 365 Apps for enterprise + OFFICESUBSCRIPTION_FACULTY= Office 365 ProPlus for Faculty + OFFICESUBSCRIPTION_GOV= Office ProPlus + OFFICESUBSCRIPTION_STUDENT= Office ProPlus Student Benefit + OFFICE_FORMS_PLAN_2= Microsoft Forms (Plan 2) + OFFICE_PRO_PLUS_SUBSCRIPTION_SMBIZ= Office ProPlus + ONEDRIVESTANDARD= OneDrive + PAM_ENTERPRISE = Exchange Primary Active Manager + PLANNERSTANDALONE= Planner Standalone + POWERAPPS_INDIVIDUAL_USER= Microsoft PowerApps and Logic flows + POWERAPPS_O365_P2= PowerApps + POWERAPPS_O365_P3= PowerApps for Office 365 + POWERAPPS_VIRAL= PowerApps (Free) + POWERFLOW_P1= Microsoft PowerApps Plan 1 + POWERFLOW_P2= Microsoft PowerApps Plan 2 + POWER_BI_ADDON= Office 365 Power BI Addon + POWER_BI_INDIVIDUAL_USE= Power BI Individual User + POWER_BI_INDIVIDUAL_USER= Power BI for Office 365 Individual + POWER_BI_PRO= Power BI Pro + POWER_BI_STANDALONE= Power BI Standalone + POWER_BI_STANDARD= Power-BI Standard + PREMIUM_ADMINDROID= AdminDroid Office 365 Reporter + PROJECTCLIENT= Project Professional + PROJECTESSENTIALS= Project Lite + PROJECTONLINE_PLAN_1= Project Online (Plan 1) + PROJECTONLINE_PLAN_1_FACULTY= Project Online for Faculty Plan 1 + PROJECTONLINE_PLAN_1_STUDENT= Project Online for Students Plan 1 + PROJECTONLINE_PLAN_2= Project Online and PRO + PROJECTONLINE_PLAN_2_FACULTY= Project Online for Faculty Plan 2 + PROJECTONLINE_PLAN_2_STUDENT= Project Online for Students Plan 2 + PROJECTPREMIUM= Project Online Premium + PROJECTPROFESSIONAL= Project Online Pro + PROJECTWORKMANAGEMENT= Office 365 Planner Preview + PROJECT_CLIENT_SUBSCRIPTION= Project Pro for Office 365 + PROJECT_ESSENTIALS= Project Lite + PROJECT_MADEIRA_PREVIEW_IW_SKU= Dynamics 365 for Financials for IWs + PROJECT_ONLINE_PRO= Project Online Plan 3 + RIGHTSMANAGEMENT= Azure Rights Management Premium + RIGHTSMANAGEMENT_ADHOC= Windows Azure Rights Management + RIGHTSMANAGEMENT_STANDARD_FACULTY= Azure Rights Management for faculty + RIGHTSMANAGEMENT_STANDARD_STUDENT= Information Rights Management for Students + RMS_S_ENTERPRISE= Azure Active Directory Rights Management + RMS_S_ENTERPRISE_GOV= Windows Azure Active Directory Rights Management + RMS_S_PREMIUM= Azure Information Protection Plan 1 + RMS_S_PREMIUM2= Azure Information Protection Premium P2 + SCHOOL_DATA_SYNC_P1= School Data Sync (Plan 1) + SHAREPOINTDESKLESS= SharePoint Online Kiosk + SHAREPOINTDESKLESS_GOV= SharePoint Online Kiosk + SHAREPOINTENTERPRISE= SharePoint Online (Plan 2) + SHAREPOINTENTERPRISE_EDU= SharePoint Plan 2 for EDU + SHAREPOINTENTERPRISE_GOV= SharePoint Plan 2G + SHAREPOINTENTERPRISE_MIDMARKET= SharePoint Online (Plan 1) + SHAREPOINTLITE= SharePoint Online (Plan 1) + SHAREPOINTPARTNER= SharePoint Online Partner Access + SHAREPOINTSTANDARD= SharePoint Online Plan 1 + SHAREPOINTSTANDARD_EDU= SharePoint Plan 1 for EDU + SHAREPOINTSTORAGE= SharePoint Online Storage + SHAREPOINTWAC= Office Online + SHAREPOINTWAC_EDU= Office Online for Education + SHAREPOINTWAC_GOV= Office Online for Government + SHAREPOINT_PROJECT= SharePoint Online (Plan 2) Project + SHAREPOINT_PROJECT_EDU= Project Online Service for Education + SMB_APPS= Business Apps (free) + SMB_BUSINESS= Office 365 Business + SMB_BUSINESS_ESSENTIALS= Office 365 Business Essentials + SMB_BUSINESS_PREMIUM= Office 365 Business Premium + SPZA IW= Microsoft PowerApps Plan 2 Trial + SPB= Microsoft 365 Business + SPE_E3= Secure Productive Enterprise E3 + SQL_IS_SSIM= Power BI Information Services + STANDARDPACK= Office 365 (Plan E1) + STANDARDPACK_FACULTY= Office 365 (Plan A1) for Faculty + STANDARDPACK_GOV= Microsoft Office 365 (Plan G1) for Government + STANDARDPACK_STUDENT= Office 365 (Plan A1) for Students + STANDARDWOFFPACK= Office 365 (Plan E2) + STANDARDWOFFPACKPACK_FACULTY= Office 365 (Plan A2) for Faculty + STANDARDWOFFPACKPACK_STUDENT= Office 365 (Plan A2) for Students + STANDARDWOFFPACK_FACULTY= Office 365 Education E1 for Faculty + STANDARDWOFFPACK_GOV= Microsoft Office 365 (Plan G2) for Government + STANDARDWOFFPACK_IW_FACULTY= Office 365 Education for Faculty + STANDARDWOFFPACK_IW_STUDENT= Office 365 Education for Students + STANDARDWOFFPACK_STUDENT= Microsoft Office 365 (Plan A2) for Students + STANDARD_B_PILOT= Office 365 (Small Business Preview) + STREAM= Microsoft Stream + STREAM_O365_E3= Microsoft Stream for O365 E3 SKU + STREAM_O365_E5= Microsoft Stream for O365 E5 SKU + SWAY= Sway + TEAMS1= Microsoft Teams + TEAMS_COMMERCIAL_TRIAL= Microsoft Teams Commercial Cloud Trial + THREAT_INTELLIGENCE= Office 365 Threat Intelligence + VIDEO_INTEROP = Skype Meeting Video Interop for Skype for Business + VISIOCLIENT= Visio Online Plan 2 + VISIOONLINE_PLAN1= Visio Online Plan 1 + VISIO_CLIENT_SUBSCRIPTION= Visio Pro for Office 365 + WACONEDRIVEENTERPRISE= OneDrive for Business (Plan 2) + WACONEDRIVESTANDARD= OneDrive for Business with Office Online + WACSHAREPOINTSTD= Office Online STD + WHITEBOARD_PLAN3= White Board (Plan 3) + WIN_DEF_ATP= Windows Defender Advanced Threat Protection + WIN10_PRO_ENT_SUB= Windows 10 Enterprise E3 + WIN10_VDA_E3= Windows E3 + WIN10_VDA_E5= Windows E5 + WINDOWS_STORE= Windows Store + YAMMER_EDU= Yammer for Academic + YAMMER_ENTERPRISE= Yammer for the Starship Enterprise + YAMMER_ENTERPRISE_STANDALONE= Yammer Enterprise + YAMMER_MIDSIZE= Yammer \ No newline at end of file diff --git a/Office 365 Mailbox Permissions Report/GetMailboxPermission.ps1 b/Office 365 Mailbox Permissions Report/GetMailboxPermission.ps1 index 56d2d31..245fd87 100644 --- a/Office 365 Mailbox Permissions Report/GetMailboxPermission.ps1 +++ b/Office 365 Mailbox Permissions Report/GetMailboxPermission.ps1 @@ -6,7 +6,9 @@ Version: 3.0 For detailed Script execution: https://o365reports.com/2019/03/07/export-mailbox-permission-csv/ ============================================================================================ #> -#Accept input paramenters + +#If you connect via Certificate based authentication, then your application required "Directory.Read.All" application permission, assign exchange administrator role and Exchange.ManageAsApp permission to your application. + param( [switch]$FullAccess, [switch]$SendAs, @@ -14,256 +16,254 @@ param( [switch]$UserMailboxOnly, [switch]$AdminsOnly, [string]$MBNamesFile, -[string]$UserName, -[string]$Password, -[switch]$NoMFA +[string]$TenantId, +[string]$ClientId, +[string]$CertificateThumbprint ) - -function Print_Output +Function ConnectModules { - #Get admin roles assigned to user - if($RolesAssigned -eq "") - { - $Roles=(Get-MsolUserRole -UserPrincipalName $upn).Name - if($Roles.count -eq 0) - { - $RolesAssigned="No roles" - } - else - { - foreach($Role in $Roles) + $MsGraphModule = Get-Module Microsoft.Graph -ListAvailable + if($MsGraphModule -eq $null) { - $RolesAssigned=$RolesAssigned+$Role - if($Roles.indexof($role) -lt (($Roles.count)-1)) - { - $RolesAssigned=$RolesAssigned+"," - } - } - } - } - #Mailbox type based filter - if(($UserMailboxOnly.IsPresent) -and ($MBType -ne "UserMailbox")) - { - $Print=0 - } - - #Admin Role based filter - if(($AdminsOnly.IsPresent) -and ($RolesAssigned -eq "No roles")) - { - $Print=0 - } - - #Print Output - if($Print -eq 1) - { - $Result = @{'DisplayName'=$_.Displayname;'UserPrinciPalName'=$upn;'MailboxType'=$MBType;'AccessType'=$AccessType;'UserWithAccess'=$userwithAccess;'Roles'=$RolesAssigned} - $Results = New-Object PSObject -Property $Result - $Results |select-object DisplayName,UserPrinciPalName,MailboxType,AccessType,UserWithAccess,Roles | Export-Csv -Path $ExportCSV -Notype -Append - } + Write-host "Important: Microsoft Graph Powershell module is unavailable. It is mandatory to have this module installed in the system to run the script successfully." -ForegroundColor Yellow + $confirm = Read-Host Are you sure you want to install Microsoft Graph Powershell module? [Y] Yes [N] No + if($confirm -match "[yY]") + { + Write-host "Installing Microsoft Graph Powershell module..." + Install-Module -Name Microsoft.Graph -Scope CurrentUser + Write-host "Microsoft Graph Powershell module is installed in the machine successfully" -ForegroundColor Magenta + } + else + { + Write-host "Exiting. `nNote: Microsoft Graph Powershell module must be available in your system to run the script" -ForegroundColor Red + Exit + } + } + else + { + [Version]$InstalledVersion = (Get-InstalledModule Microsoft.Graph).Version + $Result = $InstalledVersion.CompareTo([Version]"1.10.0") + if($Result -eq -1) + { + $Confirm = Read-Host "The installed version of the Microsoft Graph Powershell module is not supported. Do you want to update the module? [Y] Yes [N] No" + if($confirm -match "[yY]") + { + Update-Module -Name Microsoft.Graph + } + else + { + Exit + } + } + } + $ExchangeOnlineModule = Get-Module ExchangeOnlineManagement -ListAvailable + if($ExchangeOnlineModule -eq $null) + { + Write-host "Important: Exchange Online module is unavailable. It is mandatory to have this module installed in the system to run the script successfully." + $confirm = Read-Host Are you sure you want to install Exchange Online module? [Y] Yes [N] No + if($confirm -match "[yY]") + { + Write-host "Installing Exchange Online module..." + Install-Module -Name ExchangeOnlineManagement -Scope CurrentUser + Write-host "Exchange Online Module is installed in the machine successfully" -ForegroundColor Magenta + } + else + { + Write-host "Exiting. `nNote: Exchange Online module must be available in your system to run the script" + Exit + } + } + Disconnect-MgGraph -ErrorAction SilentlyContinue | Out-Null + Disconnect-ExchangeOnline -Confirm:$false + Write-Progress -Activity "Connecting modules(Microsoft Graph and Exchange Online module)..." + try{ + if($TenantId -ne "" -and $ClientId -ne "" -and $CertificateThumbprint -ne "") + { + Connect-MgGraph -TenantId $TenantId -ClientId $ClientId -CertificateThumbprint $CertificateThumbprint -ErrorAction SilentlyContinue -ErrorVariable ConnectionError|Out-Null + if($ConnectionError -ne $null) + { + Write-Host $ConnectionError -Foregroundcolor Red + Exit + } + $Scopes = (Get-MgContext).Scopes + if($Scopes -notcontains "Directory.Read.All" -and $Scopes -notcontains "Directory.ReadWrite.All") + { + Write-Host "Note: Your application required the following graph application permissions: Directory.Read.All" -ForegroundColor Yellow + Exit + } + Connect-ExchangeOnline -AppId $ClientId -CertificateThumbprint $CertificateThumbprint -Organization (Get-MgDomain | Where-Object {$_.isInitial}).Id -ShowBanner:$false + } + else + { + Connect-MgGraph -Scopes "Directory.Read.All" -ErrorAction SilentlyContinue -Errorvariable ConnectionError |Out-Null + if($ConnectionError -ne $null) + { + Write-Host $ConnectionError -Foregroundcolor Red + Exit + } + Connect-ExchangeOnline -UserPrincipalName (Get-MgContext).Account -ShowBanner:$false + } + } + catch + { + Write-Host $_.Exception.message -ForegroundColor Red + Exit + } + Write-Host "Microsoft Graph Powershell module is connected successfully" -ForegroundColor Cyan + Write-Host "Exchange Online module is connected successfully" -ForegroundColor Cyan +} +Function Print_Output +{ + $Result = [PSCustomObject]@{'DisplayName'=$Displayname;'UserPrincipalName'=$UPN;'MailboxType'=$MBType;'AccessType'=$AccessType;'UserWithAccess'=$UserWithAccess;'Roles'=$Roles} + $Result | Export-csv -Path $ExportCSV -Append -NoTypeInformation +} +Function Get_MBPermission +{ + #Getting delegated Fullaccess permission for mailbox + if(($FilterPresent -eq 'False') -or ($FullAccess.IsPresent)) + { + $FullAccessPermissions = (Get-EXOMailboxPermission -Identity $UPN -ErrorAction SilentlyContinue | Where { ($_.AccessRights -contains "FullAccess") -and ($_.IsInherited -eq $false) -and -not ($_.User -match "NT AUTHORITY" -or $_.User -match "S-1-5-21") }).User + if([string]$FullAccessPermissions -ne "") + { + $AccessType = "FullAccess" + $UserWithAccess = @($FullAccessPermissions) -join ',' + Print_Output + } + } + #Getting delegated SendAs permission for mailbox + if(($FilterPresent -eq 'False') -or ($SendAs.IsPresent)) + { + $SendAsPermissions = (Get-EXORecipientPermission -Identity $UPN -ErrorAction SilentlyContinue | Where{ -not (($_.Trustee -match "NT AUTHORITY") -or ($_.Trustee -match "S-1-5-21"))}).Trustee + if([string]$SendAsPermissions -ne "") + { + $AccessType = "SendAs" + $UserWithAccess = @($SendAsPermissions) -join ',' + Print_Output + } + } + #Getting delegated SendOnBehalf permission for mailbox + if(($FilterPresent -eq 'False') -or ($SendOnBehalf.IsPresent)) + { + if([string]$SendOnBehalfPermissions -ne "") + { + $AccessType = "SendOnBehalf" + $UserWithAccess = @() + Foreach($SendOnBehalfPermissionDN in $SendOnBehalfPermissions) + { + $SendOnBehalfPermission = (Get-EXOMailBox -Identity $SendOnBehalfPermissionDN -ErrorAction SilentlyContinue).UserPrincipalName + if($SendOnBehalfPermission -eq $null) + { + $SendOnBehalfPermission = ($Users|?{$_.MailNickname -eq $SendOnBehalfPermissionDN}).UserPrincipalName + } + $UserWithAccess += $SendOnBehalfPermission + } + $UserWithAccess = @($UserWithAccess) -join ',' + Print_Output + } + } +} +#Getting Mailbox permission +Function Get_MailBoxData +{ + Write-Progress -Activity "`n Processing mailbox: $MBUserCount `n Currently Processing: $DisplayName" + $Script:MBUserCount++ + if($UserMailboxOnly.IsPresent -and $MBType -ne 'UserMailBox') + { + return + } + #Get admin roles assigned to user + $RoleList=Get-MgUserTransitiveMemberOf -UserId $UserId|Select-Object -ExpandProperty AdditionalProperties + $RoleList = $RoleList|?{$_.'@odata.type' -eq '#microsoft.graph.directoryRole'} + $Roles = @($RoleList.displayName) -join ',' + if($RoleList.count -eq 0) + { + $Roles = "No roles" + } + + #Admin Role based filter + if($AdminsOnly.IsPresent -and $Roles -eq "No roles") + { + return + } + Get_MBPermission +} +Function CloseConnection +{ + Disconnect-MgGraph | Out-Null + Disconnect-ExchangeOnline -Confirm:$false +} +ConnectModules +Write-Progress -Activity Completed -Completed +Select-MgProfile -Name beta +#Set output file +$Location = (Get-Location) +$ExportCSV = "$($Location)\MBPermission_$((Get-Date -format yyyy-MMM-dd-ddd` hh-mm-ss` tt).ToString()).csv" +$Result = "" ; $Mailboxes = @(); $MBUserCount = 1; +$Users = Get-MgUser -All +#Check for AccessType filter +if(($FullAccess.IsPresent) -or ($SendAs.IsPresent) -or ($SendOnBehalf.IsPresent)) +{ + $FilterPresent = 'True' +} +else +{ + $FilterPresent = 'False' } -#Getting Mailbox permission -function Get_MBPermission - { - $upn=$_.UserPrincipalName - $DisplayName=$_.Displayname - $MBType=$_.RecipientTypeDetails - $Print=0 - Write-Progress -Activity "`n Processed mailbox count: $MBUserCount "`n" Currently Processing: $DisplayName" - - #Getting delegated Fullaccess permission for mailbox - if(($FilterPresent -eq 'False') -or ($FullAccess.IsPresent)) - { - $FullAccessPermissions=(Get-MailboxPermission -Identity $upn | where { ($_.AccessRights -contains "FullAccess") -and ($_.IsInherited -eq $false) -and -not ($_.User -match "NT AUTHORITY" -or $_.User -match "S-1-5-21") }).User - if([string]$FullAccessPermissions -ne "") - { - $Print=1 - $UserWithAccess="" - $AccessType="FullAccess" - foreach($FullAccessPermission in $FullAccessPermissions) - { - $UserWithAccess=$UserWithAccess+$FullAccessPermission - if($FullAccessPermissions.indexof($FullAccessPermission) -lt (($FullAccessPermissions.count)-1)) - { - $UserWithAccess=$UserWithAccess+"," - } +#Check for input file +if ($MBNamesFile -ne "") +{ + #We have an input file, read it into memory + try{ + $MailBoxes = Import-Csv -Header "MailBoxUPN" -Path $MBNamesFile } - Print_Output - } - } - - #Getting delegated SendAs permission for mailbox - if(($FilterPresent -eq 'False') -or ($SendAs.IsPresent)) - { - $SendAsPermissions=(Get-RecipientPermission -Identity $upn | where{ -not (($_.Trustee -match "NT AUTHORITY") -or ($_.Trustee -match "S-1-5-21"))}).Trustee - if([string]$SendAsPermissions -ne "") - { - $Print=1 - $UserWithAccess="" - $AccessType="SendAs" - foreach($SendAsPermission in $SendAsPermissions) - { - $UserWithAccess=$UserWithAccess+$SendAsPermission - if($SendAsPermissions.indexof($SendAsPermission) -lt (($SendAsPermissions.count)-1)) - { - $UserWithAccess=$UserWithAccess+"," - } + catch{ + Write-Host $_.Exception.Message -ForegroundColor Red + CloseConnection + Exit } - Print_Output - } - } - - #Getting delegated SendOnBehalf permission for mailbox - if(($FilterPresent -eq 'False') -or ($SendOnBehalf.IsPresent)) - { - $SendOnBehalfPermissions=$_.GrantSendOnBehalfTo - if([string]$SendOnBehalfPermissions -ne "") + Foreach($Mail in $MailBoxes) { - $Print=1 - $UserWithAccess="" - $AccessType="SendOnBehalf" - foreach($SendOnBehalfPermissionDN in $SendOnBehalfPermissions) - { - $SendOnBehalfPermission=(Get-Mailbox -Identity $SendOnBehalfPermissionDN).UserPrincipalName - $UserWithAccess=$UserWithAccess+$SendOnBehalfPermission - if($SendOnBehalfPermissions.indexof($SendOnBehalfPermission) -lt (($SendOnBehalfPermissions.count)-1)) - { - $UserWithAccess=$UserWithAccess+"," - } - } - Print_Output + $Mailbox = Get-EXOMailbox -Identity $Mail.MailBoxUPN -PropertySets All -ErrorAction SilentlyContinue + if($Mailbox -eq $null) + { + Write-Host `n $Mail.MailBoxUPN is not found -ForegroundColor Red + Continue + } + $DisplayName = $MailBox.DisplayName + $UPN = $MailBox.UserPrincipalName + $UserId = $MailBox.ExternalDirectoryObjectId + $MBType = $MailBox.RecipientTypeDetails + $SendOnBehalfPermissions = $MailBox.GrantSendOnBehalfTo + Get_MailBoxData } - } - } - - - -function main{ - #Connect AzureAD and Exchange Online from PowerShell - Get-PSSession | Remove-PSSession - - #Check for EXO v2 module inatallation - $Module = Get-Module ExchangeOnlineManagement -ListAvailable - if($Module.count -eq 0) - { - Write-Host Exchange Online PowerShell V2 module is not available -ForegroundColor yellow - $Confirm= Read-Host Are you sure you want to install module? [Y] Yes [N] No - if($Confirm -match "[yY]") - { - Write-host "Installing Exchange Online PowerShell module" - Install-Module ExchangeOnlineManagement -Repository PSGallery -AllowClobber -Force - Import-Module ExchangeOnlineManagement - } - else - { - Write-Host EXO V2 module is required to connect Exchange Online.Please install module using Install-Module ExchangeOnlineManagement cmdlet. - Exit - } - } - #Check for Azure AD module - $Module = Get-Module MsOnline -ListAvailable - if($Module.count -eq 0) - { - Write-Host MSOnline module is not available -ForegroundColor yellow - $Confirm= Read-Host Are you sure you want to install the module? [Y] Yes [N] No - if($Confirm -match "[yY]") - { - Write-host "Installing MSOnline PowerShell module" - Install-Module MSOnline -Repository PSGallery -AllowClobber -Force - Import-Module MSOnline - } - else - { - Write-Host MSOnline module is required to generate the report.Please install module using Install-Module MSOnline cmdlet. - Exit - } - } - - #Authentication using non-MFA - if($NoMFA.IsPresent) - { - #Storing credential in script for scheduling purpose/ Passing credential as parameter - if(($UserName -ne "") -and ($Password -ne "")) - { - $SecuredPassword = ConvertTo-SecureString -AsPlainText $Password -Force - $Credential = New-Object System.Management.Automation.PSCredential $UserName,$SecuredPassword - } - else - { - $Credential=Get-Credential -Credential $null - } - Write-Host "Connecting Azure AD..." - Connect-MsolService -Credential $Credential | Out-Null - Write-Host "Connecting Exchange Online PowerShell..." - Connect-ExchangeOnline -Credential $Credential - } - #Connect to Exchange Online and AzureAD module using MFA - else - { - Write-Host "Connecting Exchange Online PowerShell..." - Connect-ExchangeOnline - Write-Host "Connecting Azure AD..." - Connect-MsolService | Out-Null - } - - #Set output file - $ExportCSV=".\MBPermission_$((Get-Date -format yyyy-MMM-dd-ddd` hh-mm` tt).ToString()).csv" - $Result="" - $Results=@() - $MBUserCount=0 - $RolesAssigned="" - - #Check for AccessType filter - if(($FullAccess.IsPresent) -or ($SendAs.IsPresent) -or ($SendOnBehalf.IsPresent)) - {} - else - { - $FilterPresent='False' - } - - #Check for input file - if ($MBNamesFile -ne "") - { - #We have an input file, read it into memory - $MBs=@() - $MBs=Import-Csv -Header "DisplayName" $MBNamesFile - foreach($item in $MBs) - { - Get-Mailbox -Identity $item.displayname | Foreach{ - $MBUserCount++ - Get_MBPermission - } - } - } - #Getting all User mailbox - else - { - Get-mailbox -ResultSize Unlimited | Where{$_.DisplayName -notlike "Discovery Search Mailbox"} | foreach{ - $MBUserCount++ - Get_MBPermission} - } - - - #Open output file after execution +} +else +{ + Get-EXOMailbox -ResultSize Unlimited -PropertySets All | Where{$_.DisplayName -notlike "Discovery Search Mailbox"} |ForEach-Object{ + $DisplayName = $_.DisplayName + $UPN = $_.UserPrincipalName + $UserId = $_.ExternalDirectoryObjectId + $MBType = $_.RecipientTypeDetails + $SendOnBehalfPermissions = $_.GrantSendOnBehalfTo + Get_MailBoxData + } +} +#Open output file after execution Write-Host `nScript executed successfully if((Test-Path -Path $ExportCSV) -eq "True") { - Write-Host "Detailed report available in: $ExportCSV" - $Prompt = New-Object -ComObject wscript.shell - $UserInput = $Prompt.popup("Do you want to open output file?",` - 0,"Open Output File",4) - If ($UserInput -eq 6) - { - Invoke-Item "$ExportCSV" - } + Write-Host Detailed report available in: $ExportCSV -ForegroundColor Green + $Prompt = New-Object -ComObject wscript.shell + $UserInput = $Prompt.popup("Do you want to open output file?",` 0,"Open Output File",4) + if ($UserInput -eq 6) + { + Invoke-Item "$ExportCSV" + } } -Else +else { - Write-Host No mailbox found that matches your criteria. + Write-Host No mailbox found that matches your criteria. -ForegroundColor Red } -#Clean up session -Get-PSSession | Remove-PSSession -} - . main - \ No newline at end of file +CloseConnection \ No newline at end of file