AdminDroid 7dfd4da739 Microsoft 365 Users' Password Expiry Date report
Included users' last sign-in date and inactive days
2024-05-27 19:07:49 +05:30

265 lines
9.1 KiB
PowerShell
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<#
=============================================================================================
Name: Microsoft 365 password expiry reports
Description: Export Office 365 Users Last Password Change Date and expiry date using MS Graph
website: o365reports.com
Version: 5.1
Script Highlights: 
~~~~~~~~~~~~~~~~~
1. A single script allows you to generate 7 different password reports. 
#.Export all users and their last password change and expiry date
#.List users with password never expiry
#.Exports password expired users
#.helps to find soon-to-expire password users
#.Helps to track recent password changers, etc
2. Generates pwd reports for all or Licensed users alone 
3. Gnerates pwd reports for all or sign-in enabled users alone
4. The script uses MS Graph PowerShell and installs MS Graph PowerShell SDK (if not installed already) upon your confirmation. 
5. It can be executed with certificate-based authentication (CBA) too.
6. The script can be executed with MFA enabled accounts too 
7. Exports output to CSV 
8. The script is supports certificate-based authetication
For detailed Script execution: https://o365reports.com/2020/02/17/export-office-365-users-last-password-change-date-to-csv
============================================================================================
#>
Param
(
[Parameter(Mandatory = $false)]
[switch]$PwdNeverExpires,
[switch]$PwdExpired,
[switch]$LicensedUserOnly,
[int]$SoonToExpire,
[int]$RecentPwdChanges,
[switch]$EnabledUsersOnly,
[string]$TenantId,
[string]$ClientId,
[string]$CertificateThumbprint
)
$MsGraphBetaModule = Get-Module Microsoft.Graph.Beta -ListAvailable
if($MsGraphBetaModule -eq $null)
{
Write-host "Important: Microsoft Graph Beta 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 Microsoft Graph Beta module? [Y] Yes [N] No
if($confirm -match "[yY]")
{
Write-host "Installing Microsoft Graph Beta module..."
Install-Module Microsoft.Graph.Beta -Scope CurrentUser -AllowClobber
Write-host "Microsoft Graph Beta module is installed in the machine successfully" -ForegroundColor Magenta
}
else
{
Write-host "Exiting. `nNote: Microsoft Graph Beta module must be available in your system to run the script" -ForegroundColor Red
Exit
}
}
Write-Host "Connecting to MS Graph PowerShell..."
if(($TenantId -ne "") -and ($ClientId -ne "") -and ($CertificateThumbprint -ne ""))
{
Connect-MgGraph -TenantId $TenantId -AppId $ClientId -CertificateThumbprint $CertificateThumbprint -ErrorAction SilentlyContinue -ErrorVariable ConnectionError|Out-Null
if($ConnectionError -ne $null)
{
Write-Host $ConnectionError -Foregroundcolor Red
Exit
}
}
else
{
Connect-MgGraph -Scopes "Directory.Read.All" -ErrorAction SilentlyContinue -Errorvariable ConnectionError |Out-Null
if($ConnectionError -ne $null)
{
Write-Host "$ConnectionError" -Foregroundcolor Red
Exit
}
}
$UserCount = 0
$PrintedUser = 0
$Result = ""
$PwdPolicy=@{}
#Output file declaration
$Location=Get-Location
$ExportCSV = "$Location\PasswordExpiryReport_$((Get-Date -format yyyy-MMM-dd-ddd` hh-mm-ss` tt).ToString()).csv"
#Getting Password policy for the domain
$Domains = Get-MgBetaDomain #-Status Verified
foreach($Domain in $Domains)
{
#Check for federated domain
if($Domain.AuthenticationType -eq "Federated")
{
$PwdValidity = 0
}
else
{
$PwdValidity = $Domain.PasswordValidityPeriodInDays
if($PwdValidity -eq $null)
{
$PwdValidity = 90
}
}
$PwdPolicy.Add($Domain.Id,$PwdValidity)
}
Write-Host "Generating M365 users' password expiry report..." -ForegroundColor Magenta
#Loop through each user
Get-MgBetaUser -All -Property DisplayName,UserPrincipalName,LastPasswordChangeDateTime,PasswordPolicies,AssignedLicenses,AccountEnabled,SigninActivity | foreach{
$UPN = $_.UserPrincipalName
$DisplayName = $_.DisplayName
[boolean]$Federated = $false
$UserCount++
Write-Progress -Activity "`n Processed user count: $UserCount "`n" Currently Processing: $DisplayName"
#Remove external users
if($UPN -like "*#EXT#*")
{
return
}
$PwdLastChange = $_.LastPasswordChangeDateTime
$PwdPolicies = $_.PasswordPolicies
$LicenseStatus = $_.AssignedLicenses
$LastSignInDate=$_.SignInActivity.LastSignInDateTime
#Calculate Inactive days
if($LastSignInDate -eq $null)
{
$LastSignInDate="Never Logged-in"
$InactiveDays= "-"
}
else
{
$InactiveDays= (New-TimeSpan -Start $LastSignInDate).Days
}
$Print = 0
if($LicenseStatus -ne $null)
{
$LicenseStatus = "Licensed"
}
else
{
$LicenseStatus = "Unlicensed"
}
if($_.AccountEnabled -eq $true)
{
$AccountStatus = "Enabled"
}
else
{
$AccountStatus = "Disabled"
}
#Finding password validity period for user
$UserDomain= $UPN -Split "@" | Select-Object -Last 1
$PwdValidityPeriod=$PwdPolicy[$UserDomain]
#Check for Pwd never expires set from pwd policy
if([int]$PwdValidityPeriod -eq 2147483647)
{
$PwdNeverExpire = $true
$PwdExpireIn = "Never Expires"
$PwdExpiryDate = "-"
$PwdExpiresIn = "-"
}
elseif($PwdValidityPeriod -eq 0) #Users from federated domain
{
$Federated = $true
$PwdExpireIn = "Insufficient data in O365"
$PwdExpiryDate = "-"
$PwdExpiresIn = "-"
}
elseif($PwdPolicies -eq "none" -or $PwdPolicies -eq "DisableStrongPassword") #Check for Pwd never expires set from Set-MsolUser
{
$PwdExpiryDate = $PwdLastChange.AddDays($PwdValidityPeriod)
$PwdExpiresIn = (New-TimeSpan -Start (Get-Date) -End $PwdExpiryDate).Days
if($PwdExpiresIn -gt 0)
{
$PwdExpireIn = "Will expire in $PwdExpiresIn days"
}
elseif($PwdExpiresIn -lt 0)
{
#Write-host `n $PwdExpiresIn
$PwdExpireIn = $PwdExpiresIn * (-1)
#Write-Host ************$pwdexpiresin
$PwdExpireIn = "Expired $PwdExpireIn days ago"
}
else
{
$PwdExpireIn = "Today"
}
}
else
{
$PwdExpireIn = "Never Expires"
$PwdExpiryDate = "-"
$PwdExpiresIn = "-"
}
#Calculating Password since last set
$PwdSinceLastSet = (New-TimeSpan -Start $PwdLastChange).Days
#Filter for enabled users
if(($EnabledUsersOnly.IsPresent) -and ($_.AccountEnabled -eq $false))
{
return
}
#Filter for user with Password nerver expires
if(($PwdNeverExpires.IsPresent) -and ($PwdExpireIn -ne "Never Expires"))
{
return
}
#Filter for password expired users
if(($PwdExpired.IsPresent) -and (($PwdExpiresIn -ge 0) -or ($PwdExpiresIn -eq "-")))
{
return
}
#Filter for licensed users
if(($LicensedUserOnly.IsPresent) -and ($LicenseStatus -eq "Unlicensed"))
{
return
}
#Filter for soon to expire pwd users
if(($SoonToExpire -ne "") -and (($PwdExpiryDate -eq "-") -or ($SoonToExpire -lt $PwdExpiresIn) -or ($PwdExpiresIn -lt 0)))
{
return
}
#Filter for recently password changed users
if(($RecentPwdChanges -ne "") -and ($PwdSinceLastSet -gt $RecentPwdChanges))
{
return
}
if($Federated -eq $true)
{
$PwdExpiryDate = "Insufficient data in O365"
$PwdExpiresIn = "Insufficient data in O365"
}
$PrintedUser++
#Export result to csv
$Result = [PSCustomObject]@{'Display Name'=$_.DisplayName;'User Principal Name'=$UPN;'Pwd Last Change Date'=$PwdLastChange;'Days since Pwd Last Set'=$PwdSinceLastSet;'Pwd Expiry Date'=$PwdExpiryDate;'Friendly Expiry Time'=$PwdExpireIn ;'Days since Expiry(-) / Days to Expiry(+)'=$PwdExpiresIn;'License Status'=$LicenseStatus;'Account Status'=$AccountStatus;'Last Sign-in Date'=$LastSignInDate;'Inactive Days'=$InactiveDays}
$Result | Export-Csv -Path $ExportCSV -Notype -Append
}
if($UserCount -eq 0)
{
Write-Host No records found
}
else
{
Write-Host "`nThe output file contains " -NoNewline
Write-Host $PrintedUser users. -ForegroundColor Green
Write-Host `n~~ Script prepared by AdminDroid Community ~~`n -ForegroundColor Green
Write-Host "~~ Check out " -NoNewline -ForegroundColor Green; Write-Host "admindroid.com" -ForegroundColor Yellow -NoNewline; Write-Host " to get access to 1800+ Microsoft 365 reports. ~~" -ForegroundColor Green `n`n
if((Test-Path -Path $ExportCSV) -eq "True")
{
Write-Host `n "The Output file availble in:" -NoNewline -ForegroundColor Yellow; Write-Host "$ExportCSV" `n
$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"
}
}
}
Disconnect-MgGraph | Out-Null