PowerShell: List everything on a OU in a one line


To list all users in a OU, we can get it using Get-ADUser cmdlet. See the example below. (replace OU path in LDAP format to your own stuff and “Import-Module ActiveDirectory” before you run it).

Get-ADUser -Filter * -SearchBase “cn=Users,dc=company,,dc=com” -properties title, department| Select-Object name,title,department

Now what if you want everything (Users, Groups, Contacts, etc.,) from an OU. To get everything from a OU, use Get-ADObject cmdlet. See example below.

Get-ADObject -Filter * -SearchBase “cn=Users,dc=company,dc=com” -properties description | Select-Object name, objectclass, description

Enjoy!!!

PowerShell: Search User Accounts in Active Directory


Active Directory Module has many cmdlets to process many AD related tasks. BUT we don’t have simple search cmdlet.

I had a requirement to check a list of users in AD to see if they exist or not. Get-ADUser doesn’t cut it for my requirement. If a user doesn’t exist, Get-ADUser errors out. So I wrote my own function. It can be used in a script or pipe the user names (SAM Account Name). This function search active directory and returns the AD User object if exists. Otherwise it returns an null value.

Download the script here: http://1drv.ms/1fSd9PH

Feel free use it for you purpose.

# Function: Search-User
# Parameter: user’s SAM Account Name
#
# Description: Search Active Directory with given
# SAM Account Name. Return the AD User object if
# user exists, or return null value
#
# Written by: Anand Venkatachalapathy
#
Function Search-User
{


param([Parameter(ValueFromPipeline)] $User)

BEGIN {import-module activedirectory}

PROCESS
{

   $filter = “(&(ObjectClass=User)(sAMAccountName=$User))”
   $userobject = Get-ADObject -LDAPFilter $filter

   if ($userobject -eq $null)
   {
        return $null
   }

   return (Get-ADUser $userobject)

}

}

To use this function, call the function with a user’s SAM Account Name. E.g.,

$user = “JDoe”
$userobject = Search-User($user)
If ($userobject –eq $null)
{ “$user doesn’t exists in Active Directory” }
else
{ $userobject  }

Active Directory: Bulk User Password Reset by PowerShell


If you need to reset password for bulk number of user accounts, the following PowerShell scripts is for you.

This first script requires an file with usernames listed one per line. Check the UserList.txt file location in this file. Change your favorite password in ConvertTo-SecureString cmdlet in this script. Then you are good go.

#
# Script: ResetPwd.ps1
# Description: Reset the password for bulk number of users, and
# set the property to change passwrod required at next logon
#
# Written by: Anand Venkatachalapathy
#

Import-Module ActiveDirectory

# Set the default password
$password = ConvertTo-SecureString -AsPlainText “AwesomeP@ssw0rd” -Force
 
# Get the list of accounts from the file on file
# List the user names one per line
$users = Get-Content -Path c:\MyScripts\UserList.txt
 
ForEach ($user in $users)
{
    # Set the default password for the current account
    Get-ADUser $user | Set-ADAccountPassword -NewPassword $password -Reset
   
    #If you need to set the property “Change password at next logon”,
    #leave the next alone. If not, comment the next line
    Get-ADUser $user | Set-AdUser -ChangePasswordAtLogon $true
   
    Write-Host “Password has been reset for the user: $user”
}

# ————- End ———–

This second script does bulk password changes for similar named user accounts. e.g., TestUser001 to Testuser100. Change your own password and user account name in the filter.

#
# Script: ResetPwd.ps1
# Description: Reset the password for bulk number of users, and 
# set the property to change password required at next logon
#
# Written by: Anand Venkatachalapathy
#

Import-Module ActiveDirectory

# Set the default password
$password = ConvertTo-SecureString -AsPlainText "AwesomeP@ssw0rd" -Force    # Set the default password for all users named TestUserXX 
# e.g.,TestUser001 to TestUser100
Get-ADUser -Filter { SAMAccountName -like "*TestUser*"} `
| Set-ADAccountPassword -NewPassword $password -Reset
    
#If you need to set the property "Change password at next logon", 
#leave the next alone. If not, comment the next line
Get-ADUser -Filter { SAMAccountName -like "*TestUser*"} `
| Set-AdUser -ChangePasswordAtLogon $true
    

# ------------- End -----------

PowerShell 4.0: “Get-ADUser : One or more properties are invalid”


This applies to Get-ADComputer cmdlet too. When I try to get all properties of an AD account like Get-ADUser JohnDoe –Properties * it gives following error.

Get-ADUser : One or more properties are invalid.
Parameter name: msDS-AssignedAuthNPolicy

It used to work in older PowerShell versions (Windows 8 or Windows 7). Now my scripts are all stopped working.

Well I believe it is a bug in ActiveDirectory PowerShell module. But also on other hand we should NOT be using –Properties * in a script. That would be a bad scripting practice, it takes more time to process obviously. Right way is use it like –Properties <propertyname1>,<propertyname2>.

What if I don’t know the properties I want. What if I have to figure the correct property name. Do NOT worry, there is a workaround. Pipe the Get-ADUser or Get-ADComputer to a Get-ADObject cmdlet like below.

Get-ADuser JohnDoe | Get-ADObject –Properties *

Hopefully it will be fixed on next updates or MS don’t want us to use * in properties parameter. Enjoy. Open-mouthed smile

PowerShell: List Active Computers from Active Directory


I had a requirement to get list of active computers from Active Directory with some stored properties in computer account like OS, OS version and OU name where the computer account exists. I have defined the active computer as if LastLogonDate is less than 60 days. Here is the script.

P.S. Your computer should be installed with Powershell ActiveDirectory module.

# 
# Name : ListActiveComputers.ps1
# Purpose: Get active computer accounts from active directory by 
# checking the last logon date. Get the properties of computer
# account (name,OS,OSverion,lastlogondate and CanonicalName)
# and save it to ActiveComputers.csv file.
#
# Written by Anand Venkatachalapathy
# Date written: 03/28/2012
#

Import-Module ActiveDirectory

# get today's date
$today = Get-Date

#Get today - 60 days (2 month old)
$cutoffdate = $today.AddDays(-60)

#Get the computer accounts filtered by lastlogondate.
# Select only required properties of the computer account
# and export it to a file
Get-ADComputer  -Properties * -Filter {LastLogonDate -gt $cutoffdate} `
| Select Name,OperatingSystem,OperatingSystemVersion, `
LastLogonDate,CanonicalName | Export-Csv ./ActiveComputers.csv

Download the script here: ListActiveComputers.ps1

(Updated) Active Directory: Account Lockout issues


Update: See the bottom of this blog on how to search SCOM event on account lockout.

When yours or user’s account locked out frequently how do you find out which computer is sending bad passwords? I got few unconventional methods apart from Microsoft’s recommendations.

First method is throw up your hands & say “I don’t know”. Just kidding Smile . Microsoft suggests to use lockoutstatus.exe tool to see which domain controller is logging bad passwords and search the Security event log on the specific domain controller. The problem is lockoutstatus tool is NOT accurate most of the times. It doesn’t work correctly on Windows 2008 R2 domains.

You can search Event ID 4740 yourself on closest domain controller by yourself. This event ID should have the computer name which originates the bad passwords. The sample event ID 4740 looks like this:

Log Name:      Security
Source:        Microsoft-Windows-Security-Auditing
Date:          10/24/2011 7:05:54 PM
Event ID:      4740
Task Category: User Account Management
Level:         Information
Keywords:      Audit Success
User:          N/A
Computer:      DomainController1.company.com
Description:
A user account was locked out.

Subject:
    Security ID:        SYSTEM
    Account Name:        DC2$
    Account Domain:        COMPANY
    Logon ID:        0x3e7

Account That Was Locked Out:
    Security ID:        COMPANY\JohnDoe
    Account Name:        Johndoe

Additional Information:
    Caller Computer Name:   
\\johndoe-pc

Once you figure out the computer name, you have to check the computer for possible programs or software that locks out the computer. Check the following usual suspects,

  1. Manually mapped network drives
  2. Cached passwords (Credentials Manager in Windows 7, Manage passwords in Windows XP)
  3. Any disconnected Remote Desktop sessions on possible servers

There is a handy-dandy powershell command I use to get the event id 4740 from the domain controllers from my laptop. Run the following commands on a Active Directory Module for Powershell (meaning Remote Server Administration Tools needs to be installed on the local computer).

Get-EventLog –ComputerName DomainControllerName -LogName Security | Where-Object {$_.EventID -eq 4740} | fl

The problem with security log on domain controllers are it rolls out very quickly. You could run the above command and collect the results on a text file, so you can have at least week worth of collected logs for troubleshooting. Or if you have SCOM servers, you can collect the event logs to SCOM database as it logged on the domain controllers.

I like my SCOM server is collecting Event Id 4740s from all domain controllers in the enterprise and save it for 3 months.  The results is searchable, alert-able and very easy to use.

If you like the SCOM idea, read further.

First you have to create a event log collecting rule. Follow the steps to author the performance collecting rule.

  1. Open Operations Manager Console.
  2. Click on Authoring section.
  3. Click to select Rules under Management Pack Objects.
  4. Click on Create a Rule on Action pane (or right click on Rule and select Create a Rule).
  5. On Select a Rule Type section, expand Collection Rules –> Event Based –> NT Event Log.image
  6. Optional: Select your custom management pack.
  7. Click Next.
  8. On General section, type the rule name something descriptive. Select Event Collection as Rule Category. Select Rule Target as Active Directory DC and Global Catalog Server Role for appropriate server version.image
  9. Click Next.
  10. On Event Log section, click on … button and select computer as one of your domain controller and select Security event log from the list.imageimage
  11. Click Next.
  12. On Build Event Expression section, type Event ID Equals 4740. Select Event Source and click Delete.image
  13. Click Create.

That’s all. Give it enough time for all domain controllers get the new rule. When any account gets locked out, you can see an Alert in Monitoring section with all details in the event log including the computer that sends bad passwords.

image

 

How to search SCOM alerts for specific account?

It’s really sad that Microsoft SCOM console doesn’t provide a way to search in description field. Search terms are pretty basic like rule name or server name. But Operations Manager Shell comes to the rescue. Here is how you can search a specific account in SCOM alerts.

Type the following command in Operations Manager Shell (poweshell).

get-alert | where {$_.Context -like “*username*”} | fl Parameters

e.g., get-alert | where {$_.Context -like “*JohnDoe*”} | fl Parameters

When your service account is being locked out constantly….


This might be a bad idea. But this script helps at times when an service account is being locked out constantly, you need time to figure out how it is happening.

I wrote this script and schedule to run every 5 minutes to scan my service account lockouts, unlock the account and send me an email. I saved my application was going down due to the service account lockouts. I figured out how the account was locked out.

If you are interested in this script, follow the steps below.

1. Copy and paste the following script to a notepad. Save it as WatchServiceAccount.vbs

2. On 44th line, provide your NetBIOS active directory domain name to the variable strDomainName

3. on 88th line, provide your local SMTP mail server name

4. Write a batch file and call this script by Cscript WatchServiceAccount.vbs MyServiceAccountName

5. Create a scheduled task to run your batch file.

 

‘  #####                                             #                                            
‘ #     # ###### #####  #    # #  ####  ######      # #    ####   ####   ####  #    # #    # #####
‘ #       #      #    # #    # # #    # #          #   #  #    # #    # #    # #    # ##   #   #  
‘  #####  #####  #    # #    # # #      #####     #     # #      #      #    # #    # # #  #   #  
‘       # #      #####  #    # # #      #         ####### #      #      #    # #    # #  # #   #  
‘ #     # #      #   #   #  #  # #    # #         #     # #    # #    # #    # #    # #   ##   #  
‘  #####  ###### #    #   ##   #  ####  ######    #     #  ####   ####   ####   ####  #    #   #  
‘                                                                                                  ‘

‘                      #     #                                         
‘                      #  #  #   ##   #####  ####  #    # ###### ##### 
‘                      #  #  #  #  #    #   #    # #    # #      #    #
‘                      #  #  # #    #   #   #      ###### #####  #    #
‘                      #  #  # ######   #   #      #    # #      ##### 
‘                      #  #  # #    #   #   #    # #    # #      #   # 
‘                       ## ##  #    #   #    ####  #    # ###### #    #
‘ Name: WatchServiceAccount.vbs
‘ Arguments: Service Account name

‘ E.g., CScript WatchServiceAccount.vbs serviceaccount

‘ Description: When run this script it will check speific service account is locked out or not.
‘ If the account locked out it will unlock the account and send emails to admins.

‘ Written by: Anand Venkatachalapathy
‘ Created on August 13th 2011

‘Get the passed argument and assign it to a variable
ServiceAccount = WScript.Arguments(0)

‘ Call the sub routine to check the account
CheckAccount ServiceAccount


‘ Name: CheckAccount
‘ Parameters: User Account Name
‘ Description: The sub routine checks IsAccountLocked attribute. If it is
‘ True, then Account is locked out. This sub routine will unlock the account
‘ send emails to administrators.

Sub CheckAccount(strAccount)
    ‘Provide your NetBIOS domain name here
    strDomainName = “MyADDomain”
   
    ‘Get the user account object
    Set objuser = GetObject(“WinNT://” & strDomainName & “/” & strAccount)
   
    ‘check if it is locked out..
    If objuser.IsAccountLocked Then
        ‘Yes, it is LOCKED OUT.
        Wscript.Echo strAccount & ” is locked out.”
       
        ‘Unlocked the account
        objuser.IsAccountLocked = 0
        objUser.setinfo
       
        ‘Send emails to Administrators
        Alert_Admins “Windows-Admins@Company.com”, strAccount & ” is locked out”, strAccount & ” has been unlocked by script. Please check the cause of account lock out.” & vbCrLf & vbCrLf & “–Your scripting friend”
    Else     
        ‘YAY! it not. No Worries here.
        Wscript.Echo strAccount & ” is NOT locked out.”
    End If
    Set obj = Nothing
End Sub

‘===============================================================
‘ Name:      Alert_Admins
‘ Purpose:   Send email using mail.corp.idt.com server.
‘ Input:     strTo – Who to send to, strSub – Subject of the message
‘             strBody – Body of the message
‘ Output:    Sends the emails to the strTO recipients
‘===============================================================
Sub Alert_Admins( strTo,strSub,strBody)

    ‘WScript.Echo strBody

    ‘* iMsg – holds CDO.Message object
    ‘* Flds – Enumeration for CDO SMTP object properties
    ‘* iConf – holds CDO.Configuration
    Dim iMsg, Flds, iConf

    ‘* sSMTPServerName – SMTP Server Name
    Dim sSMTpServerName

    ‘* Assign corpml servers as SMTP server
    sSMTPServerName = “smtp.company.com”

    ‘* Assign cdoSendUsingPort is set to 2, i.e., send using SMTP (25) port
    Const cdoSendUsingPort = 2

    ‘* Create CDO Objects and assign to variables
    Set iMsg = CreateObject(“CDO.Message”)
    Set iConf = CreateObject(“CDO.Configuration”)
    Set Flds = iConf.Fields

    ‘* Assign values to Flds class properties

    With Flds
        .Item(“
http://schemas.microsoft.com/cdo/configuration/sendusing”) = cdoSendUsingPort
        .Item(“
http://schemas.microsoft.com/cdo/configuration/smtpserver”) = sSMTPServerName
        .Item(“
http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout”) = 25 
        .Update
    End With

    ‘* Assign message properties and Send the mail
    With iMsg
        Set .Configuration = iConf
        .Fields(“urn:schemas:httpmail:importance”).Value = 2    ‘Setting Mail importance to High (2)
        .Fields.Update
        .To = strTo
        .From = “AccountsWatcher@company.com”               ‘Fake, but make-sense email FROM address
        .Sender = “admin@company.com”                    ‘Return Email address
        .Subject = strSub
        .TextBody = strBody
    .Send
    End With

End Sub