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 (3.4k points)

1 Answer

0 votes
by (217k points)

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

I am trying to see if Adaxes and send me a report of how many users have Dial In access. is there a way to do it.. If so please advise .. The object is msNPAllowDialin

asked Dec 2, 2011 by Nate (250 points)
0 votes
1 answer

I need to be able to create a csv and email it once a week of accounts that have a date in %hiredate% that starts in the next 7 days. I need to include the full ... dept, and %hiredate% feilds in the CSV. Any help you can provide would be great. Thank you,

asked Sep 9 by hgletifer (6.8k points)
0 votes
2 answers

Hi, Can you tell me how to look up a list of last logged-in users for computers from specific OU? Have OU called Laptops and need to know who as last person logged into ... username-of-last-user-who-lgged-on-to-computer-s269.htm but it' s not design for OU

asked Dec 2, 2019 by roberttryba (650 points)
0 votes
1 answer

I'm trying to combine these two scripts to effectively store a user's group memberships in customattributebinary5 and then be able to copy and paste those memberships to a ... ) $Context.LogMessage("Added the user to group '$groupName'", "Information") }

asked Jan 24 by yourpp (2.5k points)
0 votes
1 answer

If I have 2 Active Directory Security groups in my domain - Group A Group B Is it possible to create a report that shows only users who have membership in both groups? For ... Jane Doe is in Group A AND Group B she would be included in the resulting report.

asked May 11 by sirslimjim (2.1k points)
2,352 questions
2,106 answers
5,746 comments
127,235 users