#Requires -RunAsAdministrator
cls
# Import Active Directory module
Import-Module ActiveDirectory
# Variables
$Date = Get-Date -Format "yyyy-MM-dd"
$timestamp = Get-Date -UFormat "%d/%m/%Y %R"
$DaysInactive = 60
$DaysPwdReset = 7 # Password was reset within 7 days
$NumDays = (Get-Date).AddDays(-$DaysInactive)
$60DaysInactive_Users = @()
$Computer = $env:COMPUTERNAME
$ExchangeServer = "ExchangeSrv01.lab.local"
$MailboxUpdateResult = $false
$Description = "Automatically disabled after 60 days inactivity on $Date"
$InactiveExcludedGroupName = "Inactive-Excluded-Users"
# Log and report directories
$ReportPath = "D:\Logs\LAB User Decom Reports"
$OutputPath = "D:\Outputs\LAB Inactive User List"
$GroupMembershipLog = "D:\Logs\Decom User Group Memberships"
# Disabled User OU
$DisabledUsersOU = "OU=Disabled Accounts,DC=LAB,DC=LOCAL" # Disabled User OU for all other COIs
# All the Active Users OUs
$ALLUsersPROJECTUsers = "OU=PROJECT Users,OU=All Users,DC=LAB,DC=LOCAL"
$StandardUsers = "OU=Standard Users,OU=_PROJECTS,DC=LAB,DC=LOCAL"
$PrivilegedUsers = "OU=Admin Users,OU=_Admins,DC=LAB,DC=LOCAL"
# All required active user OUs
$AllRequiredOUs = @($ALLUsersPROJECTUsers, $StandardUsers, $PrivilegedUsers)
# Test Only
# $TestOU = "OU=TESTONLY,DC=LAB,DC=LOCAL"
# $AllRequiredOUs = @($TestOU)
# ------------------------------------------------------
# Function Name: Identification
# Usage:
# Identify who and when the task runs
#
# Input: N/A
# ------------------------------------------------------
Function Identification
{
# Identify the running user and the run time
$RunUser = [Security.Principal.WindowsIdentity]::GetCurrent().Name
$RunTime = Get-Date
# Record the user and run time
Return "The require PROJECT USERs task was carried by $RunUser from $Computer at $RunTime `n"
}
# ***************************************************
# UpdateUserMailboxSettings
#
# Usage:
# Set disabled User Mailbox Quota to zero
# Hide disabled user from GAL
#
# Input:
# $User # Disable user
# $Report # Report
#
#***************************************************
Function UpdateUserMailboxSettings {
Param (
[Parameter (Mandatory=$true)] [String] $User,
[Parameter (Mandatory=$true)] [String] $Report
)
Try {
If (Get-Mailbox -Identity $user) {
# Set mailbox quota size to zero
Set-Mailbox -Identity $user -IssueWarningQuota 0 -ProhibitSendQuota 0 -ProhibitSendReceiveQuota 0 -UseDatabaseQuotaDefaults $false
"$User - mailbox quota has been set to zero." | Out-File -Encoding Ascii -Append $Report
Write-Host "$User - mailbox quota has been set to zero."
# Hide user from GAL
Set-Mailbox -Identity $User -HiddenFromAddressListsEnabled $true
"$User has been hidden from GAL." | Out-File -Encoding Ascii -Append $Report
Write-Host "$User - has been hidden from GAL."
}
}
Catch {
"$User - mailbox quota is not able to be set to zero, and not able to hidden from GAL" | Out-File -Encoding Ascii -Append $Report
Write-Host "$User - mailbox quota is not able to be set to zero, and not able to hide user from GAL." -ForegroundColor Red
}
}
# ------------------------------------------------------
# Main
#
# ------------------------------------------------------
# Set up Exchange session
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "http://$ExchangeServer/PowerShell/" -Authentication Kerberos
Import-PSSession $Session -AllowClobber
# 60 Days Inactive Excluded user accounts
$InactiveExcludedUsers = Get-ADGroupMember -Identity $InactiveExcludedGroupName | Select-Object -ExpandProperty SamAccountName
# Find users that have not been login for more than 60 days
ForEach ($OU in $AllRequiredOUs) {
Write-Host "Process top level OU: $OU" -ForegroundColor Yellow
# Process Privileged Users OU
If ($OU -like "*Privileged Users*") {
$PrivilegeInActiveUsers = Get-ADUser -Properties * -Filter {LastLogonDate -lt $NumDays } -SearchBase $OU `
| Select-Object Name,SAMAccountName,lastLogonDate,Description,DistinguishedName,PasswordLastSet,PasswordExpired,WhenCreated
# Exclude the group Inactive-Excluded-Users
Foreach ($pUser in $PrivilegeInActiveUsers) {
$pUserName = $pUser.SamAccountName
if (!($InactiveExcludedUsers -contains $pUserName)) {
# Write-Host "$pUserName not in Inactive Excluded Group."
$60DaysInactive_Users += $pUser
}
}
}
# Process other active users OUs
Else {
# Process with all OU and sub-OUs
# By default -SearchBase will search current OU and all Sub-OUs, by using -SearchScope OneLevel, ensure it search all OU and Sub-OUs
$SubOUs = Get-ADOrganizationalUnit -Filter * -SearchBase $OU
ForEach ($ChildOU in $SubOUs) {
$InactiveUsers = Get-ADUser -Properties * -SearchScope OneLevel -Filter {LastLogonDate -lt $NumDays } -SearchBase $ChildOU `
| Select-Object Name,SAMAccountName,lastLogonDate,Description,DistinguishedName,PasswordLastSet,PasswordExpired,WhenCreated
# Update inactive user list
$60DaysInactive_Users += $InactiveUsers
}
}
}
# Troubleshooting
<#
If ($60DaysInactive_Users -ne $null) {
Write-Host "Please check inactive user list file: $OutputPath\60DaysInactivedUsers-$Date.txt"
$60DaysInactive_Users | Export-Csv "$OutputPath\60DaysInactivedUsers-$Date.txt" -NoTypeInformation
}
Else {
Write-Host "There is 60 days inactive users"
}
#>
# Process if there are users that have been inactived for more than 60 days
If ($60DaysInactive_Users -ne $null) {
# Export the 60 days inactive user list
"The following users have been inactive for more than 60 days." | Add-Content "$ReportPath\60Days-Inactive-Users-Report-$Date.txt"
"" | Add-Content "$ReportPath\60Days-Inactive-Users-Report-$Date.txt"
$60DaysInactive_Users | Export-Csv "$OutputPath\60DaysInactivedUsers-$Date.txt" -NoTypeInformation
<#
Troubleshooting / verification
#>
$count = $60DaysInactive_Users.Count
Write-Host "`nThe number of 60 days inactive users: $count`n" -ForegroundColor Green
# Disable any user that have not been login for more than 60 days, if it has not been disabled
ForEach ($User in $60DaysInactive_Users) {
$DisplayName = $User.name
$LoginName = $User.SAMAccountName
$DN = $User.DistinguishedName
$PwdLastSet = $User.PasswordLastSet
$PwdExpired = $User.PasswordExpired
$WhenCreated = $User.WhenCreated
$UserDescription = $User.Description
Try {
# Get the number of days since the password was last set, if null set to 9999
If ($PwdLastSet -ne $null) {
$DaysSincePasswordLastSet = [int](New-TimeSpan -Start ($PwdLastSet) -End (Get-Date) | select -ExpandProperty TotalDays)
}
Else {
$DaysSincePasswordLastSet = 9999
}
# Disable user password last reset is greater than $DaysPwdReset (7 days)
If ($DaysSincePasswordLastSet -gt $DaysPwdReset) {
# Set user mailbox quota to zero and hide user from GAL
$Report = "$ReportPath\60Days-Inactive-Users-Report-$Date.txt"
UpdateUserMailboxSettings $LoginName $Report
# Disable user account if it is enabled
Get-ADUser -Identity $LoginName | Where-Object {$_.Enabled -eq $true} | Disable-ADAccount
# Update Users Description with automatically disable and date information
If ($UserDescription -notlike "*Automatically disabled*") {
$DescriptionUpdate = $UserDescription + " " + $Description
Set-ADUser -Identity $LoginName -Description $DescriptionUpdate
}
# Recording user group membership, then remove user group membership
# If your has more than Domain Users group membership
Try {
$NumGroups = (Get-ADPrincipalGroupMembership -Identity $LoginName | Measure-Object count).count
If ($NumGroups -gt "1") {
# Record user group membership to log file
"$DisplayName ($LoginName) - Group Membership - $timestamp" | Out-File -Encoding Ascii -Append "$GroupMembershipLog\$LoginName-GroupMembership-$Date.txt"
"" | Add-Content "$GroupMembershipLog\$LoginName-GroupMembership-$Date.txt"
"User location: $DN" | Add-Content "$GroupMembershipLog\$LoginName-GroupMembership-$Date.txt"
Get-ADPrincipalGroupMembership -Identity $LoginName `
| ?{($_.Name -notlike "Domain Users")} `
| Select-Object Name, SamAccountName `
| Out-File -Encoding Ascii -Append "$GroupMembershipLog\$LoginName-GroupMembership-$Date.txt"
Write-Host "$LoginName group membership has been recorded to $LoginName-GroupMemberhip-$Date.txt"
"$LoginName group membership has been recorded to $LoginName-GroupMemberhip-$Date.txt" | Add-Content "$ReportPath\60Days-Inactive-Users-Report-$Date.txt"
# Remove user group membership, except "Domain Users"
Get-ADPrincipalGroupMembership -Identity $LoginName `
| ?{($_.Name -notlike "Domain Users")} `
| ForEach-Object {
# "$_.Name has been removed from $DisplayName" | Out-File -Encoding ascii -Append "$GroupMembershipLog\$DisplayName ($LoginName)-GroupMemberhip.txt" # Test Only
Remove-ADPrincipalGroupMembership -Identity $LoginName -MemberOf $_ -Confirm:$false
}
Write-Host "$LoginName group memberships have been removed."
"$LoginName group memberships have been removed." | Add-Content "$ReportPath\60Days-Inactive-Users-Report-$Date.txt"
}
# Move the disabled users to Disabled Users OU
# Get-ADUser $LoginName | Move-ADObject -TargetPath $DisabledUsersOU
"$DisplayName ($LoginName) has been moved to Disabled Users OU." | Out-File -Encoding Ascii -Append "$ReportPath\60Days-Inactive-Users-Report-$Date.txt"
Write-Host "$DisplayName - has been moved to Disabled Accounts OU."
Write-Host "$DisplayName - has been process." -ForegroundColor Green
}
Catch {
Write-Host "Not able to process the disabled user: $LoginName" -ForegroundColor Red
}
}
Else {
# Do nothing
# Do not disable the user if user password was reset within last 7 days
}
}
Catch {
Write-Host "Not able to process the user - $DisplayName." -ForegroundColor Red
}
}
# Record the admin user who carry out the PROJECT02 user decommission
Identification | Add-Content "$ReportPath\60Days-Inactive-Users-Report-$Date.txt"
Write-Output "`n.....Process 60 days inactive users completed....."
}
Else {
Write-Host "No users have been inactived more than $DaysInactive days." -ForegroundColor Yellow
}
<#
Clean up
#>
$60DaysInactive_Users = @()
# Clean up Exchange session
Remove-PSSession $Session