ML
    • Recent
    • Categories
    • Tags
    • Popular
    • Users
    • Groups
    • Register
    • Login

    Active Directory - Disable users in a group after an elapsed time of inactivity

    IT Discussion
    4
    15
    2.0k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • anthonyhA
      anthonyh
      last edited by anthonyh

      Hey y'all,

      I'm looking to throw together a script that looks at Active Directory users that are a member of a specific group and if their last logon was, say, 30 days or longer, disables the account.

      Has anyone put together such a thing? If so, a point in the right direction would be yugely appreciated!

      Thanks!

      EDIT: I originally specified OU when I meant group. Sorry!!

      1 Reply Last reply Reply Quote 0
      • gjacobseG
        gjacobse
        last edited by

        I can't directly answer your question.. but in part you will likely want to use something like this in PowerShell.

        To get all user objects who have not logged on since January 1, 2007, use the following commands:
        
        $logonDate = New-Object System.DateTime(2007, 1, 1)
        
        Get-ADUser -filter { lastLogon -le $logonDate }
        
        anthonyhA 1 Reply Last reply Reply Quote 2
        • anthonyhA
          anthonyh @gjacobse
          last edited by

          @gjacobse This is a starting point for sure. Thank you!

          1 Reply Last reply Reply Quote 0
          • anthonyhA
            anthonyh
            last edited by

            OK! I think I threw together something that will do what I want!

            import-module activedirectory
            $disableList = @(get-adgroupmember 'DisableMeNao' | select -expandproperty SamAccountName)
            
            $expiration = (get-date).adddays(-30)
            
            foreach ($acct in $disableList) {
                $lastLogon = get-aduser $acct -properties lastlogondate | select -expandproperty lastlogondate
                if ($lastLogon -lt $expiration) {
                    echo "$acct's last logon was more than 30 days ago. Account has been disabled."
                    disable-adaccount -identity $acct
                }
            }
            
            dafyreD 1 Reply Last reply Reply Quote 1
            • dafyreD
              dafyre @anthonyh
              last edited by

              @anthonyh said in Active Directory - Disable users in a group after an elapsed time of inactivity:

              OK! I think I threw together something that will do what I want!

              import-module activedirectory
              $disableList = @(get-adgroupmember 'DisableMeNao' | select -expandproperty SamAccountName)
              
              $expiration = (get-date).adddays(-30)
              
              foreach ($acct in $disableList) {
                  $lastLogon = get-aduser $acct -properties lastlogondate | select -expandproperty lastlogondate
                  if ($lastLogon -lt $expiration) {
                      echo "$acct's last logon was more than 30 days ago. Account has been disabled."
                      disable-adaccount -identity $acct
                  }
              }
              

              /me passes you a hard hat and puts one on myself.

              1 Reply Last reply Reply Quote 0
              • anthonyhA
                anthonyh
                last edited by

                Slight improvement

                $adGroup = "DisableMeNao"
                $days = "30"
                
                #####
                
                import-module activedirectory
                $disableList = @(get-adgroupmember $adGroup | select -expandproperty SamAccountName)
                
                $expiration = (get-date).adddays(-$days)
                
                foreach ($acct in $disableList) {
                    $lastLogon = get-aduser $acct -properties lastlogondate | select -expandproperty lastlogondate
                    if ($lastLogon -lt $expiration) {
                        echo "$acct's last logon was more than $days days ago. Account has been disabled."
                        disable-adaccount -identity $acct
                    }
                }
                
                1 Reply Last reply Reply Quote 0
                • anthonyhA
                  anthonyh
                  last edited by

                  I might even turn the two variables into parameters so they are specified when executing the script.

                  kill_it_with_fire.ps -Group 'DisableMeNao' -Days '30'

                  Hmmm...

                  1 Reply Last reply Reply Quote 0
                  • thwrT
                    thwr
                    last edited by thwr

                    Same here - take care. Last logon normally won't be synced between DCs. You need to loop through Get-ADDomainController results and query each DC individually.

                    anthonyhA 1 Reply Last reply Reply Quote 1
                    • anthonyhA
                      anthonyh
                      last edited by

                      Ok, another improvement. Parameter-ized the variables. You would run it like so:

                      script.ps1 -group 'AD Group' -days 8675309 -test NO

                      If days isn't specified the default is 30. If "-test NO" is not specified, it will print the eligible accounts but not disable them.

                      param (
                          [string]$group,
                          [string]$days = 30,
                          [string]$test = "y"
                      )
                      
                      if ( -not ($group)) {
                          $scriptName = $MyInvocation.MyCommand.Name
                          echo "Group parameter missing."
                          echo "Script usage: $scriptName -group `'AD Group`' -days 30 -test NO"
                          echo "If `"-days`" isn't specified the default is 30."
                          echo "If `"-test NO`" isn't specified, no changes will be made."
                          exit
                      }
                      
                      #####
                      
                      echo "Disabling accounts in group $group that have no logged in for more than $days day(s)."
                      if ( $test -ne "NO") { echo "Running in **TEST** mode.  No changes will be made!" }
                      
                      import-module activedirectory
                      $disableList = @(get-adgroupmember $group | select -expandproperty SamAccountName)
                      
                      $expiration = (get-date).adddays(-$days)
                      
                      foreach ($acct in $disableList) {
                          $lastLogon = get-aduser $acct -properties lastlogondate | select -expandproperty lastlogondate
                          if ($lastLogon -lt $expiration) {
                              echo "$acct's last logon was more than $days days ago. Account selected to be disabled."
                              if ($test -eq "NO") {
                                  disable-adaccount -identity $acct
                                  echo "$acct disabled"
                              }
                          }
                      }
                      
                      1 Reply Last reply Reply Quote 0
                      • anthonyhA
                        anthonyh @thwr
                        last edited by

                        @thwr said in Active Directory - Disable users in a group after an elapsed time of inactivity:

                        Same here - take care. Last logon normally won't be synced between DCs. You need to loop through Get-ADDomainController results and query each DC individually.

                        I will look into this. Thanks!

                        thwrT anthonyhA 2 Replies Last reply Reply Quote 0
                        • thwrT
                          thwr @anthonyh
                          last edited by

                          @anthonyh said in Active Directory - Disable users in a group after an elapsed time of inactivity:

                          @thwr said in Active Directory - Disable users in a group after an elapsed time of inactivity:

                          Same here - take care. Last logon normally won't be synced between DCs. You need to loop through Get-ADDomainController results and query each DC individually.

                          I will look into this. Thanks!

                          There's a couple of attributes that won't be synced. There isn't a complete list, AFAIK, but badLogonCount is another example.

                          1 Reply Last reply Reply Quote 0
                          • anthonyhA
                            anthonyh @anthonyh
                            last edited by

                            @anthonyh said in Active Directory - Disable users in a group after an elapsed time of inactivity:

                            @thwr said in Active Directory - Disable users in a group after an elapsed time of inactivity:

                            Same here - take care. Last logon normally won't be synced between DCs. You need to loop through Get-ADDomainController results and query each DC individually.

                            I will look into this. Thanks!

                            Looks like I need to use LastLogontimestamp as this is replicated among DCs.

                            anthonyhA 1 Reply Last reply Reply Quote 0
                            • anthonyhA
                              anthonyh @anthonyh
                              last edited by

                              @anthonyh said in Active Directory - Disable users in a group after an elapsed time of inactivity:

                              @anthonyh said in Active Directory - Disable users in a group after an elapsed time of inactivity:

                              @thwr said in Active Directory - Disable users in a group after an elapsed time of inactivity:

                              Same here - take care. Last logon normally won't be synced between DCs. You need to loop through Get-ADDomainController results and query each DC individually.

                              I will look into this. Thanks!

                              Looks like I need to use LastLogontimestamp as this is replicated among DCs.

                              https://blogs.technet.microsoft.com/askds/2009/04/15/the-lastlogontimestamp-attribute-what-it-was-designed-for-and-how-it-works/

                              1 Reply Last reply Reply Quote 0
                              • anthonyhA
                                anthonyh
                                last edited by anthonyh

                                Fixed! Now using lastLogonTimestamp.

                                param (
                                    [string]$group,
                                    [string]$days = 30,
                                    [string]$test = "y"
                                )
                                
                                if ( -not ($group)) {
                                    $scriptName = $MyInvocation.MyCommand.Name
                                    echo "Group parameter missing."
                                    echo "Script usage: $scriptName -group `'AD Group`' -days 30 -test NO"
                                    echo "If `"-days`" isn't specified the default is 30."
                                    echo "If `"-test NO`" isn't specified, no changes will be made."
                                    exit
                                }
                                
                                echo "Disabling accounts in group $group that have no logged in for more than $days day(s)."
                                if ( $test -ne "NO") { echo "Running in **TEST** mode.  No changes will be made!" }
                                
                                import-module activedirectory
                                $disableList = @(get-adgroupmember $group | select -expandproperty SamAccountName)
                                
                                $expiration = (get-date).adddays(-$days)
                                
                                foreach ($acct in $disableList) {
                                    $lastLogonTS = get-aduser $acct -properties lastlogontimestamp | select -expandproperty 
                                lastlogontimestamp
                                    $lastLogon = [datetime]::FromFileTime($lastLogonTS)
                                    if ($lastLogon -lt $expiration) {
                                        echo "$acct's last logon was on $lastLogon which was more than $days days ago and is eligible 
                                for deactivation."
                                        if ($test -eq "NO") {
                                            disable-adaccount -identity $acct
                                            echo "$acct disabled"
                                        }
                                    }
                                }
                                
                                1 Reply Last reply Reply Quote 4
                                • anthonyhA
                                  anthonyh
                                  last edited by anthonyh

                                  Another revision.

                                  Added logic for when "lastlogontimestamp" does not exist. This indicates the account has never logged in. So now if "lastlogontimestamp" doesn't exist it checks the account's creation date and disables the account if the creation date is past the expiration threshold.

                                  Also added basic email reporting.

                                  param (
                                      [string]$group,
                                      [string]$days = 30,
                                      [string]$test = "y"
                                  )
                                  
                                  # This script will search AD for eligible accounts to disable if they have either
                                  # 1) never logged in and are older than the expration, or 2) if the last login is older than the expiration.
                                  
                                  $emailAddrTo = "[email protected]"
                                  $emailAddrFrom = "[email protected]"
                                  $emailSMTP = "mail.domain.org"
                                  
                                  $logStart = get-date -format g
                                  $hostName = $env:COMPUTERNAME
                                  $scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
                                  $scriptName = $MyInvocation.MyCommand.Name
                                  $log = "$scriptPath\$scriptName.log"
                                  $delimitedList = "$scriptPath\$scriptName.delimited.txt"
                                  
                                  # If the group parameter is not specified, throw an error and short script usage example.
                                  
                                  if ( -not ($group)) {
                                      echo "Group parameter missing."
                                      echo "Script usage: $scriptName -group `'AD Group`' -days 30 -test NO"
                                      echo "If `"-days`" isn't specified the default is 30."
                                      echo "If `"-test NO`" isn't specified, no changes will be made."
                                      exit
                                  }
                                  
                                  echo "Disabling accounts in group $group that have no logged in for more than $days day(s)."
                                  if ( $test -ne "NO") { echo "Running in **TEST** mode.  No changes will be made!" }
                                  
                                  import-module activedirectory
                                  
                                  # Select AD accounts based on group parameter
                                  
                                  if ( $group -eq "All") {
                                      echo "Group All specified, grabbing all Active Directory users"
                                      $disableList = @(get-aduser -filter * | select -expandproperty SamAccountName)
                                  }
                                  else {
                                      echo "Grabbing Active Directory users that are a member of $group"
                                      $disableList = @(get-adgroupmember $group | select -expandproperty SamAccountName)
                                  }
                                  
                                  # Set expiration threshold based on days parameter
                                  
                                  $expiration = (get-date).adddays(-$days)
                                  
                                  # Define arrays to log eligible accounts
                                  
                                  $noLogons = @()
                                  $expiredLogons = @()
                                  
                                  # Loop through accounts
                                  
                                  foreach ($acct in $disableList) {
                                  
                                      # Reset $lastLogonTS to accomodate for null results.
                                  
                                      $lastLogonTS = ''
                                  
                                      echo "Processing account $acct"
                                  
                                      # Get user's distinguished name
                                  
                                      $acctDN = get-aduser $acct -properties distinguishedname | select -expandproperty distinguishedname
                                  
                                      # Check if account is disabled.  If disabled, skip account.
                                  
                                      $isEnabled = get-aduser $acct -properties enabled | select -expandproperty enabled
                                  
                                      if ( $isEnabled -eq $false) {
                                          echo "$acct is already disabled, skipping."
                                      }
                                      else {
                                  
                                          # Get the last logon timestamp for user.  If user has no timestamp, this will error (which means user has never logged in)
                                      
                                          $lastLogonTS = get-aduser $acct -properties lastlogontimestamp | select -expandproperty lastlogontimestamp -ErrorAction SilentlyContinue
                                      
                                          # If last logon timestamp does not exist, check when the account was created.  If the account is older than the threshold, disable.
                                      
                                          if (!$lastLogonTS) {
                                              $acctCreation = get-aduser $acct -properties whencreated | select -expandproperty whencreated
                                              if ( $acctCreation -lt $expiration) {
                                                  echo "$acct has no recorded login and was created more than $days ago (created $acctCreation) which makes it eligible for deactivation."
                                                  if ($test -eq "NO") {
                                                      disable-adaccount -identity $acct
                                                      echo "$acct disabled"
                                                      $noLogons += "$acct | $acctDN | Created: $acctCreation"
                                                  }
                                                  else {
                                                      $noLogons += "$acct | $acctDN | Created: $acctCreation | TEST ONLY"
                                                  }
                                              }
                                          }
                                          else {
                                      
                                              # Convert last logon timestamp from file time to date time     
                                          
                                              $lastLogon = [datetime]::FromFileTime($lastLogonTS)
                                          
                                              # If last logon timestamp is older than the threshold, disable account.
                                          
                                              if ($lastLogon -lt $expiration) {
                                                  echo "$acct's last logon was more than $days days ago ($lastLogon) and is eligible for deactivation."
                                                  if ($test -eq "NO") {
                                                      disable-adaccount -identity $acct
                                                      echo "$acct disabled"
                                                      $expiredLogons += "$acct | $acctDN | Last Logon: $lastLogon"
                                                  }
                                                  else {
                                                      $expiredLogons += "$acct | $acctDN | Last Logon: $lastLogon | TEST ONLY"
                                                  }
                                           
                                              }
                                          }
                                      }
                                  }
                                  
                                  # Compile report
                                  
                                      # Start log file
                                      $logEnd = get-date -format g
                                      write-output "Log for $scriptName`r`nExecuted on $hostName`r`nScript started $logStart`r`nScript ended $logEnd`r`n" | out-file $log
                                  
                                      # Generate list of users removed from group, if any.
                                      if (!$noLogons) {
                                          write-output "Accounts older than $days days with no logon were not found (this is good!).`r`n" | out-file -append $log
                                          }
                                      else
                                          {
                                          write-output "The following accounts have been disabled because they are older than $days days and have never been used:" | out-file -append $log
                                          write-output $noLogons | out-file -append $log
                                          write-output "" | out-file -append $log
                                          }
                                  
                                      # Generate list of users added to the group, if any.
                                      if (!$expiredLogons) {
                                          write-output "Accounts with the last logon older than $days days were not found (yay!)." | out-file -append $log
                                          }
                                      else
                                          {
                                          write-output "The following accounts have been disabled because their last logon was more than $days days ago:" | out-file -append $log
                                          write-output $expiredLogons | out-file -append $log
                                          }
                                  
                                      # Dump account information to text file to be attached to the email.
                                  
                                      write-output $noLogons | out-file $delimitedList
                                      write-output $expiredLogons | out-file -append $delimitedList
                                  
                                  
                                      # Send log to $emailAddr if variable is set.
                                      if (!$emailAddrTo) {
                                          write-output "`r`nNo email address specified, no report sent." | out-file -append $log
                                          }
                                      else {
                                          $emailBody = get-content -path $log | out-string
                                          send-mailmessage -from "$hostName <$emailAddrFrom>" -to $emailAddrTo -subject "$scriptName Report" -body $emailBody -smtpserver $emailSMTP -attachments $delimitedList
                                          }
                                  
                                  1 Reply Last reply Reply Quote 2
                                  • 1 / 1
                                  • First post
                                    Last post