The script creates and emails a CSV report on users created and disabled during a certain number of days.
To schedule such a report, create a scheduled task configured for the Domain-DNS object type that runs the script and assign it over any of your AD domains. To add the script to a scheduled task, use the Run a program or PowerShell script action.
Parameters:
- $days - Specifies the number of days to include in the report.
- $propertiesToExport - Specifies a list of properties that will be included in the report for each user.
- $csvFilePath - Specifies a UNC path to the CSV file that will be created by the script.
- $removeCSVFile - Specifies whether to remove the CSV file after it is sent.
- $to - Specifies a comma separated list of recipients of the report.
- $subject - Specifies the email message subject.
- $message - Specifies the email notification message.
- $from - Specifies the e-mail address from which the message will be sent.
- $smtpServer - Specifies the SMTP server to use when sending a notification.
PowerShell
$days = 30 # TODO: modify me
$propertiesToExport = @(
@("name", "Name"),
@("distinguishedName", "Parent OU"),
@("description", "Description"),
@("department", "Department"),
@("division", "Division"),
@("mail", "Email"),
@("givenName", "First Name"),
@("sn", "Last Name"),
@("sAMAccountName", "Logon Name"),
@("manager", "Manager"),
@("physicalDeliveryOfficeName", "Office"),
@("title", "Job Title"),
@("lastLogonTimestamp", "Last Logon"),
@("employeeID", "Employee ID"),
@("userAccountControl", "Account Options")
) # TODO: modify me
# CSV file settings
$csvFilePath = "C:\scripts\report.csv" # TODO: modify me
$removeCSVFile = $True # TODO: modify me
# E-mail settings
$to = "recipient@domain.com" # TODO: modify me
$subject = "Monthly Report for Created and Disabled Accounts" # TODO: modify me
$message = "Monthly Report for Created and Disabled Accounts" # TODO: modify me
$from = "noreply@domain.com" # TODO: modify me
$smtpServer = "mail.domain.com" # TODO: modify me
$accountOptions = @{
1 = "Logon script is executed";
2 = "Account is disabled";
8 = "Home directory is required";
16 = "Account is locked out";
32 = "No password is required";
64 = "User cannot change password";
128 = "Store password using reversible encryption";
256 = "Temporary duplicated account";
512 = "Normal account";
2048 = "Interdomain trust account";
4096 = "Workstation trust account";
8192 = "Server trust account";
65536 = "Password never expires";
131072 = "MNS logon account";
262144 = "Smart card is required for interactive logon";
524288 = "Account is trusted for delegation";
1048576 = "Account is sensitive and cannot be delegated";
2097152 = "Use Kerberos DES encryption types for this account";
4194304 = "Do not require Kerberos preauthentication";
8388608 = "Password has expired";
16777216 = "Account is trusted to authenticate for delegation"
}
function GetObjectDisplayName($objectDN)
{
$objectPath = New-Object -TypeName "Softerra.Adaxes.Adsi.AdsPath" -ArgumentList @($null, $objectDN)
return [Softerra.Adaxes.Utils.ObjectNameHelper]::GetObjectName($objectPath, "IncludeParentPath")
}
function BuildReport($searFilter, $propertiesToExport, $action)
{
# Get display names for the properties
$propertyLdapNames = @()
$propertiesFriendlyNames = @()
foreach ($propertyInfo in $propertiesToExport)
{
$propertyLdapNames += $propertyInfo[0]
$propertiesFriendlyNames += $propertyInfo[1]
}
# Find users
$searcher = $Context.BindToObject("Adaxes://rootDSE")
$searcher.SearchFilter = $searFilter
$searcher.PageSize = 500
$searcher.SearchScope = "ADS_SCOPE_SUBTREE"
$searcher.SetPropertiesToLoad($propertyLdapNames)
$searcher.VirtualRoot = $True
try
{
$searchResultIterator = $searcher.ExecuteSearch()
$searchResults = $searchResultIterator.FetchAll()
# Build report
$report = @()
foreach ($searchResult in $searchResults)
{
# Get property values for each user
$record = New-Object PSObject
$record | Add-Member -MemberType NoteProperty -Name "Action" -Value $action
for ($i = 0; $i -lt $propertyLdapNames.Length; $i++)
{
$propertyName = $propertyLdapNames[$i]
# Get property value
$value = $searchResult.Properties[$propertyName].Value
switch ($propertyName)
{
"distinguishedName"
{
# Get parent object display name
$userDN = New-Object "Softerra.Adaxes.Ldap.DN" $value
$value = GetObjectDisplayName $userDN.Parent
}
"manager"
{
# Get manager display name
if ($value -ne $NULL)
{
$value = GetObjectDisplayName $managerDN
}
}
"lastLogonTimestamp"
{
if (($value -eq 0) -or ($value -eq $NULL))
{
$value = "unspecified"
}
else
{
try
{
$value = [DateTime]::FromFiletime([Int64]::Parse($value))
}
catch
{
$Context.LogMessage("Cannot convert value '$value' to the date/time format", "Warning") # TODO: modify me
$value = "unspecified"
}
}
}
"userAccountControl"
{
$userAccountControl = @()
foreach ($key in $accountOptions.Keys)
{
if ($value -band $key)
{
$userAccountControl += $accountOptions[$key]
}
}
$value = $userAccountControl -join ";"
}
}
$record | Add-Member -MemberType NoteProperty -Name $propertiesFriendlyNames[$i] -Value $value
}
$report += $record
}
return ,$report
}
finally
{
# Release resources used by the search
$searchResultIterator.Dispose()
}
}
# Build CSV report
# Add users created during the time term to the report
$csvReport = @()
if ($days -ne 0)
{
$startDate = (Get-Date).AddDays(-$days)
$dateGenerilized = [Softerra.Adaxes.Utils.Transform]::ToGeneralizedTime($startDate.ToUniversalTime())
$filter = "(&(sAMAccountType=805306368)(whenCreated>=$dateGenerilized))"
}
else
{
$filter = "(sAMAccountType=805306368)"
}
$csvReport += BuildReport $filter $propertiesToExport "Created"
# Get GUIDs of all users that were disabled during the period from Adaxes log
# Bind to the directory object representing the General Log
$path = $Context.GetWellKnownContainerPath("ServiceLog")
$serviceLog = $Context.BindToObject($path)
$generalLog = $serviceLog.GeneralLog
if ($days -ne 0)
{
$generalLog.StartDateTime = $startDate
$generalLog.EndDateTime = Get-Date
}
# Get the log records
$log = $generalLog.Log
$records = $log.GetPage(0)
# Build filter to search for disabled users
$filterParts = New-Object "System.Text.StringBuilder"
foreach ($record in $records)
{
if (($record.TargetObjectType -ne "user") -or ($record.TargetObjectGuid -eq $NULL))
{
continue
}
$operationTypes = $record.GetOperationTypes()
if ($operationTypes -notcontains "disable account")
{
continue
}
$filterPart = [Softerra.Adaxes.Ldap.FilterBuilder]::Create("ObjectGuid", [Guid]$record.TargetObjectGuid)
[void]$filterParts.Append($filterPart)
}
if ($filterParts.Length -ne 0)
{
$filter = New-Object "System.Text.StringBuilder"
[void]$filter.Append("(&(userAccountControl:1.2.840.113556.1.4.803:=2)(|")
[void]$filter.Append($filterParts)
[void]$filter.Append("))")
# Add disabled users to the report
$csvReport += BuildReport $filter.ToString() $propertiesToExport "Disabled"
}
# Send mail
$csvReport | Sort-Object -Property Action, Name | Export-csv -NoTypeInformation -Path $csvFilePath
Send-MailMessage -To $to -from $from -SmtpServer $smtpServer -Subject $subject -Body $message -Attachments $csvFilePath
if ($removeCSVFile)
{
# Remove temporary file
Remove-Item $csvFilePath -Force
}