mirror of
https://github.com/admindroid-community/powershell-scripts.git
synced 2025-12-18 00:45:19 +00:00
265 lines
9.1 KiB
PowerShell
265 lines
9.1 KiB
PowerShell
<#
|
||
=============================================================================================
|
||
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 |