Published on

Archive Inactive Users

Authors
  • Name
    Jackson Chen
#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