**Table of Contents**  
**Overview**  
**Process**  
**Script**  
**Exceptions**  
**Notifications**  
**Logging**
   

## Overview

This document defines the process in which CBP has implemented automated processing to address the NIST Security control AC-2(3), for inactivity as it pertains to Microsoft Active Directory user accounts.  
 
**AC-2(3) Defined:**  
Access Control procedures or other documentation that document the automatic disabling of inactive accounts after organization defined time period. A CBP custom script process performs this function for accounts in AD.
 
CBP has defined that inactive STANDARD user accounts are to be:  
            Disabled after thirty (30) days of inactivity  
            Deleted after ninety (90) days of inactivity
 
September 2021, a WAIVER was signed to expand the number of inactive days by 30 days for approved individuals. Approved individuals who are contracted to Border Patrol for COVID medical services will have the thresholds expanded. These users will be added to group SG-ELECTRONIC-MEDICAL-RECORDS-CONTRACTORS:
 
Disabled after sixty (60) days of inactivity  
           Deleted after one hundred twenty (120) days of inactivity  
Attachment:

![[CRA-2021-09-536 Medical Services Contractors OU group_.pdf]]

Validated by Kellerman May 2023
   
![Exported image](Exported%20image%2020250808202145-0.png)

Example
 
[https://adex.cbp.dhs.gov/WSG-Forms/Logs/Users/UserLogSearch.cfm](https://adex.cbp.dhs.gov/WSG-Forms/Logs/Users/UserLogSearch.cfm)
 
**ADEX Location: Reports | Maintenance | User Maintenance**  
The script writes activity to a SQL database so it can be viewed through ADEX. This is where you should start any investigation of maintenance activity. The SQL database is [dbo].[CBP_Account_Maint] on ConnectionString = "Server=adex.cbp.dhs.gov\wsg1;Database=adex;Integrated Security=true"

### ADEX / SQL logging (SQL log queried through ADEX)
 
The script logs activity in a subdirectory where the script is located, specifically \Log\. A new log is created every month (history is kept for each month), i.e. \Log\Clean AD User Accounts 2021-Nov.log

### Script Activity (text log)

## Logging
   

The script will notify "VIP" users in the same manner as above (email to the user + manager). However, VIP users who are members of AD\SG-EIOD-VIPLIST will also trigger an email notification to: TSD Federal Managers \<TSDFederalmanagers@cbp.dhs.gov\> with BCC to WSG. This security group is maintained by someone outside of WSG.

### VIP Notification
   

Instructions:  
The criteria for keeping an account active requires an interactive computer logon at least every 30 days. Note that interactive does NOT include run-as administrator or run-as a different user functionality. You must log into a computer desktop directly to keep the account active. If nothing is done within 5 days the pending action will be executed.
 
Name: SHENKLE, ABBY ABBY.SHENKLE@cbp.dhs.gov  
Account: BBBJR8L  
Last Login: 02/13/2023 13:21:41  
Location: CN=SHENKLE\, ABBY,OU=DCC010A UserAccounts,OU=DCC010A,OU=DCMETRO,OU=METRO,DC=ad,DC=cbp,DC=dhs,DC=gov
 
Pending Action: Delete  
Days remaining: 5
 
This message is to inform you that an Active Directory account that belongs to you is about to be disabled or deleted due to login inactivity. Details:
 
cc: Manager on file (if exists)
 
This message is to inform you that an Active Directory account that belongs to you is about to be disabled or deleted due to login inactivity. Details:
 
The script will notify both the user and manager (known by user's 'manager' attribute) by email. The default script action is to notify 5 days in advance of the pending activity disable or delete. Users who don't have a defined manager will be the only recipient of the email. Here is a sample email:

### User Notification
 
## Notifications
       
1. AD User Query: The AD query can also be adjusted to ignore accounts by not including them in the script logic. The current criteria for accounts that will not be scrutinized as of 11/16/2020: 
$_.samaccountname -notlike "GMB-*" -and  
$_.userPrincipalName -notlike "GML*" -and  
$_.userPrincipalName -notlike "GMB*" -and  
$_.distinguishedName -notlike "CN=GMB-*" -and  
$_.distinguishedName -notlike "*GM?,OU=*" -and  
$_.userPrincipalName -notlike "GCAL-*" -and  
$_.distinguishedName -notlike "CN=GCAL-*" -and  
$_.userPrincipalName -notlike "RMB-*" -and  
$_.distinguishedName -notlike "CN=RMB-*" -and  
$_.distinguishedName -notlike "*-ROOM*" -and  
$_.distinguishedName -notlike "*OU=Exchange,OU=AccessControl*" -and  
$_.userPrincipalName -notlike "SVC-*" -and  
$_.distinguishedName -notlike "CN=SVC_*" -and  
$_.distinguishedName -notlike "CN=SVC-*"
 5. Variables in the script: Exceptions can be made by modifying script variables:
    
    1. Do not disable/delete based on distinguishedname: modify variable $DNskippers
    2. Do not disable/delete based on samaccountname: modify variable $SamNameSkippers
    3. Do not delete based on samaccountname: modify variable $doNotDelete. Accounts are eligible for disable, but not delete, UNLESS never logged in (if never logged in the standard criteria applies)
      
    
6. New Sept 2021: For medical records contractors. Extended the normal threshold 30 disable/90 delete to 60 disable/120 delete. User accounts receive this exception when the TSD adds approved individuals to the group SG-ELECTRONIC-MEDICAL-RECORDS-CONTRACTORS. Again, membership in this group is managed by the TSD only. Requested by Louis W Zook and approved by STP John Buckley. Note, adding members to this group does NOT change the 90 day delete limit for accounts never logged in. 8. New May 2022: Management requested special notice for "VIP" users in group AD\SG-EOID-VIPLIST. When this user is pending delete or disable, a notification will be sent to the designated mailing list TSD Federal Managers \<TSDFederalmanagers@cbp.dhs.gov\>. More detail in notifications section.

The script will process users according to the above criteria. However, to scope in or scope out users so the script doesn't have to do unnecessary work, there are two places to do this. The first option excludes accounts from the AD query so they are not scrutinized by the script. The second will be scrutinized by the script logic but skipped if a match is determined.

## Exceptions
      

# The DNSkippers is based on DISTINGUISHEDNAME add below as necessary using format "value", (don't forget the comma so next line is included)

- $DNskippers =

"OU=Leave Of Absence Users,OU=Accounts Special Purpose",  
"OU=Off Network Users,OU=Accounts Special Purpose",  
"OU=TASPO GRABBA",  
"CN=Builtin",  
"CN=Microsoft Exchange System Objects",  
"CN=Users," # consider removing this so people can't hide here
 
# used as an exception to skip delete based on "samaccountname" attribute (will still disable). however, if never logged in it will be deleted at $deleteThreshold like others

- $doNotDelete = "STU-" # add others separated by , (comma). Skips any delete action for samaccountnames with this string - $SamNameSkippers = "RGMSWODNIW" # used as an exception to skip based on "samaccountname" attribute. add others separated by , (comma)
 
- $extendedThresholdException = Get-ADGroup S-1-5-21-2487492328-1375672958-281685340-1008227 # changed Feb 2023 to SID so group could be moved in AD but be the only one able to be used by the script.
- $extendedDisableThreshold = 60 # Exceptions: DISABLE at this number of DAYS since last logon timestamp
- $extendedDeleteThreshold = 120 # Exceptions: DELETE at this number of DAYS since last logon timestamp
 
- $emailErrorsTo = "benjamin.kellerman@cbp.dhs.gov" # email this contact if any errors are thrown in powershell
- $disableThreshold = 30 # DISABLE at this number of DAYS since last logon timestamp
- $deleteThreshold = 90 # DELETE at this number of DAYS since last logon timestamp
- $maxChanges = 150 # When the script makes this number of changes stop processing

Configurable parameters (with current values):
 
The script has 3 functions: 2 of them deal with connecting to and writing records to SQL (for easy review), and the last is responsible for making changes to active directory.
 
The script is written in Powershell and requires AD RSAT tools to run.

## Script
 
Scheduled Runbooks: References the above job runbook, runs daily at 1:10 AM (schedule is not significant)
 
Job Runbook  
_DETAILS_  
Computer: tnwg01a-v3824 (subject to change to cluster model vs. single server)  
Program Path: c:\windows\system32\WindowsPowerShell\v1.0\powershell.exe  
Parameters: D:\Data\Scripts\UserTasks\CleanUserObjects\ADUserCleanV2.x.ps1 RUN  
_ADVANCED_  
Run as Username (Orchestrator global settings variable): {SVC-EDME-USER-CLEAN}  
Password (Orchestrator global settings variable): {SVC-EDME-USER-CLEANPWD}
 
Orchestrator Details  
Account used by Orchestrator to make changes in AD and write to SQL: **AD\SVC-EDME-USER-CL**
 
The script checks each users's lastlogintimestamp using configurable thresholds found in the beginning of the script. When  
a user is at the delete threshold it is deleted and when at disable threshold it is disabled.
 
& '.\ADUserCleanV2.x.ps1' # without RUN (or anything other than RUN) makes no changes, logs to screen and log file  
& '.\ADUserCleanV2.x.ps1' RUN # with RUN command argument it will make changes in AD if you have AD permission to do so!
 
This script is used to automate disable/delete user objects based on the last time they logged into AD, specifically the lastlogintimestamp attribute. The script can be run in 'whatif' mode (making no changes) unless you supply RUN as a command line argument. When you run with argument RUN the script will make changes. Examples:
 
**Runbook Location:** EDMED\Runbooks\Job Runbooks\EDMED\WSG\Active Directory\User Tasks\ Clean User Objects V2  
**Script:** D:\Data\Scripts\UserTasks\CleanUserObjects\ADUserCleanV2.x.ps1  
**Command line argument:** RUN (if no argument supplied runs in 'whatif' mode)  
**Log location**: Logs to subdirectory of the main script \Log\ subdirectory
 
A scheduled task is executed by automation using Orchestrator daily, view/configure using RunBook Designer:

## Process