0 votes

As part of our PCI compliance, we need to create a report of all the user accounts that are expiring in the next 30 days and email that to a user who compiles the information.

I tried using the built-in account expiration notifier, but that sends individual emails.

I'm very new to PowerShell, so I'm not sure what I would need to do to build this - I know I can scour the web for PowerShell commands to build it in general, but I was hoping to utilize Adaxes to automate it.

Any assistance would be very much appreciated.

by (440 points)

1 Answer

0 votes
by (216k points)

Update 2018

Starting with Adaxes 2018.1 you can use the built-in Soon-to-expire user accounts report. By default, the report is located in container Report\All Reports\Users\Account Status.

Original

Hello,

You can generate the report you need using the following PowerShell script:

$numDays = 30 # TODO: modify me
$to = "%adm-InitiatorEmail%" # TODO: modify me

# Email message setings
$subject = "My Subject" # TODO: modify me
$htmlReportFirstPart = @"
<h1><b>Users whose accounts expire in the next $numDays days</b></h1><br/>
<table border="1">
    <tr>
        <th>Full name</th>
        <th>Logon name</th>
    </tr>
"@ # TODO: modify me

$htmlReportLastPart = @"
</table><br/>

<p><i>Please do not reply to this e-mail, it has been sent to you for notification purposes only.</i></p>
"@ # TODO: modify me

$accountExpiresDate = ((Get-Date).AddDays($numDays)).ToFileTime()
$currentDate = (Get-Date).ToFileTime()

# Search all users
$searcher = New-Object "Softerra.Adaxes.Adsi.Search.DirectorySearcher" $NULL, $False
$searcher.SearchParameters.PageSize = 500
$searcher.SearchParameters.SearchScope = "ADS_SCOPE_SUBTREE"
$searcher.SearchParameters.Filter = "(&(objectCategory=user)(accountExpires>=$currentDate)(accountExpires<=$accountExpiresDate))"
$searcher.VirtualRoot = $True

$result = $searcher.ExecuteSearch()
$users = $result.FetchAll()
$result.Dispose()

if ($users.Count -eq 0)
{
    return
}

foreach ($user in $users)
{
    $user = $Context.BindToObject($user.AdsPath)

    # Add user information to the report
    $htmlReportFirstPart += "<tr><td>" + $user.Get("cn") + "</td>"
    $htmlReportFirstPart += "<td>" + $user.Get("userPrincipalName") + "</td></tr>"
}

# Build message body in HTML
$htmlBody = $htmlReportFirstPart + $htmlReportLastPart

# Send mail to the initiator
$Context.SendMail($to, $subject, $NULL, $htmlBody)

In the script:

  • $numDays specifies the number of days, within which an account should expire to meet the condition,
  • $to specifies the email of the recipient of the report, In the sample script, it is set to %adm-InitiatorEmail% that will be substituted with the email of the user who invokes the script. If you want emails to be always sent to the same email, you need to specify the email explicitly.

This script can be used in a Custom Command to generate the report on demand or in a Scheduled Task to generate the report on a schedule. To create a Custom Command that launches this script:

  1. Create a new Custom Command.
  2. On the 2nd step of the Create Custom Command wizard, enable the Show all properties checkbox, and select the Domain-DNS object type.
  3. On the 3rd step, click the Add Action link and choose the Run a program or a PowerShell script action.
  4. Paste the script above in the Script field.
  5. Finish creation of the Custom Command.

When executed on a domain, the Custom Command will compose a report on all the users who meet the condition.

0

Great - that gets me most of it - however, I'd also like to include the date that the account expires on.

According to the web, I just need to update it like the below:

$numDays = 30
$to = "<email>"

# Email message setings
$subject = "INFORM: PCI Compliance Account Expiration Notice" 
$htmlReportFirstPart = @"
<h3><b>Users whose accounts expire in the next $numDays days</b></h3><br/>
<table border="1">
    <tr>
        <th>Full name</th>
        <th>Logon name</th>
    <th>Account Expiration Date</th>
    </tr>
"@ 

$htmlReportLastPart = @"
</table><br/>

<p><i>Please do not reply to this e-mail, it has been sent to you for notification purposes only.</i></p>
"@ 

$accountExpiresDate = ((Get-Date).AddDays($numDays)).ToFileTime()
$currentDate = (Get-Date).ToFileTime()

# Search all users
$searcher = New-Object "Softerra.Adaxes.Adsi.Search.DirectorySearcher" $NULL, $False
$searcher.SearchParameters.PageSize = 500
$searcher.SearchParameters.SearchScope = "ADS_SCOPE_SUBTREE"
$searcher.SearchParameters.Filter = "(&(objectCategory=user)(accountExpires>=$currentDate)(accountExpires<=$accountExpiresDate))"
$searcher.VirtualRoot = $True

$result = $searcher.ExecuteSearch()
$users = $result.FetchAll()
$result.Dispose()

if ($users.Count -eq 0)
{
    return
}

foreach ($user in $users)
{
    $user = $Context.BindToObject($user.AdsPath)

    # Add user information to the report
    $htmlReportFirstPart += "<tr><td>" + $user.Get("cn") + "</td>"
    $htmlReportFirstPart += "<td>" + $user.Get("userPrincipalName") + "</td>"
    $htmlReportFirstPart += "<td>" + [datetime]::FromFileTime($user.Get("accountExpires")) + "</td></tr>"
}

# Build message body in HTML
$htmlBody = $htmlReportFirstPart + $htmlReportLastPart

# Send mail to the initiator
$Context.SendMail($to, $subject, $NULL, $htmlBody)

Specifically:

    $htmlReportFirstPart += "<td>" + [datetime]::FromFileTime($user.Get("accountExpires")) + "</td></tr>"

However, when I run this code, it does not put in anything the the third column.

If I change it to

$htmlReportFirstPart += "<td>" + $user.Get("accountExpires") + "</td></tr>"

I get the "File Time" display - which isn't very helpful.

Is there a different set of code for changing the date back into an easily "readable" date format.

0

Hello,

The IADsUser interface that is supported by any user object has a property called AccountExpirationDate that returns the account expiration date in a human readable format. So, what you need to do is just to get the value for the property. Here's a modified version of the script that should do the job:

$numDays = 30 # TODO: modify me
$to = "<mail>" # TODO: modify me

# Email message setings
$subject = "INFORM: PCI Compliance Account Expiration Notice"
$htmlReportFirstPart = @"
<h3><b>Users whose accounts expire in the next $numDays days</b></h3><br/>
<table border="1">
    <tr>
        <th>Full name</th>
        <th>Logon name</th>
        <th>Account Expiration Date</th>
    </tr>
"@

$htmlReportLastPart = @"
</table><br/>

<p><i>Please do not reply to this e-mail, it has been sent to you for notification purposes only.</i></p>
"@

$accountExpiresDate = ((Get-Date).AddDays($numDays)).ToFileTime()
$currentDate = (Get-Date).ToFileTime()

# Search all users
$searcher = New-Object "Softerra.Adaxes.Adsi.Search.DirectorySearcher" $NULL, $False
$searcher.SearchParameters.PageSize = 500
$searcher.SearchParameters.SearchScope = "ADS_SCOPE_SUBTREE"
$searcher.SearchParameters.Filter = "(&(objectCategory=user)(accountExpires>=$currentDate)(accountExpires<=$accountExpiresDate))"
$searcher.VirtualRoot = $True

$result = $searcher.ExecuteSearch()
$users = $result.FetchAll()
$result.Dispose()

if ($users.Count -eq 0)
{
    return
}

foreach ($user in $users)
{
    $user = $Context.BindToObject($user.AdsPath)

    # Add user information to the report
    $htmlReportFirstPart += "<tr><td>" + $user.Get("cn") + "</td>"
    $htmlReportFirstPart += "<td>" + $user.Get("userPrincipalName") + "</td>"
    $htmlReportFirstPart += "<td>" + $user.AccountExpirationDate + "</td></tr>"
}

# Build message body in HTML
$htmlBody = $htmlReportFirstPart + $htmlReportLastPart

# Send mail to the initiator
$Context.SendMail($to, $subject, $NULL, $htmlBody)
0

Thank you, that did it.

I'll have to read up on the programming functions.

0

Take a look at Adaxes SDK, especially its Sample Scripts section. You'll find plenty of information there.

Related questions

0 votes
1 answer

The report criteria would be as follows, Name/Last Logon Date of any user that was disabled in the last 30 days. Furthermore, if possible, how would I publish this to the user ... run a report and/or choose which dates to run the report, on his own? TIA

asked Nov 26 by Milan.Pathak (20 points)
0 votes
1 answer

We have four OUs in Active Directory (Pending Deletion, Disabled with Mail Delegates, Disabled with HR Extensions and Disabled_Temp_Leave) that users are moved to prior to their eventual ... past 7 days have been moved to one of 4 of these OUs. Thanks!

asked Jun 3, 2021 by RayBilyk (240 points)
0 votes
1 answer

We need to run a scheduled task twice a year, so I chose every 182 days like it's suggested in here, only problem is that there is no way to change the next run ... really don't want these tasks to be triggered again if they've already been executed this year.

asked May 8 by boing (20 points)
0 votes
1 answer

I would like to delete users that have been disabled for more then X number of days. This would be a phase of our deprovisioning process. The user is first disabled and placed ... we are sure that we no longer need it, I would like to automaticially delete it.

asked Oct 13, 2022 by rmedeiros (380 points)
0 votes
0 answers

We've uninstalled the previous version via the "add/Remove Programs" feature in Windows 10, but we still get an error saying that another version of the client is still installed and won't allow us to run the .MSI installer. How can we get around this?

asked Feb 15 by MShep (80 points)
3,588 questions
3,277 answers
8,303 comments
548,088 users