PowerShell

I guess it is confession time.  I am a recent convert to PowerShell.  After having used VBS scripts for years now, I have recently discovered that I can do so much more using PowerShell using a lot less code.  I have a long ways to go, especially to learn best practices for writing scripts and functions. 

I thought I would share with you a few scripts that I am using and how they have helped me.  I am assuming the use of PowerShell 3.0 in this case.  (Note, to load a function so you can call it from the PowerShell prompt, you want to “dot-source” it. 

Get-ServiceAccountUsage

Have you ever had service accounts that have been around for ages yet no idea what servers they are running on or what they are actually doing?  I stumbled across Get-ServiceAccountUsage and am very impressed with it. Using the following command, I can have it search our Servers OU and tell me every place (whether it is a scheduled task, running a service or even running an IIS Application Pool) this account is in use:

(Get-AdComputer –Filter * –SearchBase “OU=Servers,DC…”).name | Get-ServiceAccountUsage –UserAccount ‘domain\service.account’

Set-AdminUser

As user accounts have been moved around through the years and been in various groups, I found that some groups used to be members of protected Admin groups (such as Account Operator or Print Operator).  When this happens, a special flag is set on the account that ensures that security inheritance is turned off on that account.  Just removing a user from those protected groups doesn’t automatically remove this adminCount flag.  Using Set-AdminUser enables you to reset the flag and turn on inheritance.  Note that if the user account should still be protected, it will refresh the adminCount flag at the next security refresh (every 90 minutes or so) so that the accounts that need to be protected are still protected.

Password Not Required field

On occasion, I have found some accounts where they are set to not require a password.  It isn’t a major issue as the GUI won’t allow these users to have a blank password, but auditors definitely don’t like to see this.  Here is a one liner to reset any user accounts with the pwdNotRequired AD field set improperly:

Get-ADUser -searchscope subtree -ldapfilter "(&(objectCategory=User)(userAccountControl:1.2.840.113556.1.4.803:=32))" | Set-ADAccountControl -PasswordNotRequired $false

and a similar one to do the same for computer accounts:

Get-ADComputer -searchscope subtree -ldapfilter "(&(objectCategory=Computer)(userAccountControl:1.2.840.113556.1.4.803:=32))" | Set-ADAccountControl -PasswordNotRequired $false

Disable Computers Using CSV File Input

On occasion, you might find it necessary to disable a list of computers.  In our environment, when we disable a computer, we do a few things:

  • Disable account
  • Set the description to note when we disabled this computer
  • Mark two fields (info and a custom schema object) with the reason we disable the account and the date we disabled the account.  (The date is used as we have another scheduled task that runs and will automatically delete disabled objects after a certain period of time.)
  • Move the account to a Pending Delete OU.
  • Finally, we also record all of this info in a database for future reference, as well as some of our regular reports on what work is done in AD.
# ==============================================================================================

# 

# Microsoft PowerShell Source File -- Created with SAPIEN Technologies PrimalScript 2011

# 

# NAME: DisableADComputerfromCSV.ps1

# 

# AUTHOR: Doug Neely , TSA

# DATE  : 3/1/2013

# 

# COMMENT: 

# 

# ==============================================================================================

Import-Module ActiveDirectory 

$datetime = Get-Date -Format MM_dd_yy_HH_mm

$csv = "R:\Scripts\ADPowershell\OldServers.csv"

$TerminationDate = Get-Date -Format M/d/yyyy

$TerminationDate = [string]$TerminationDate

 

#Import CSV File

$TerminateCSV = Import-Csv $csv 

 

foreach ($Computer in $TerminateCSV) {

    $ADSAM = $Computer.name

    

    $ADAccount = Get-ADComputer -identity $ADSAM -properties *

    $ADLastLogon = $ADAccount.LastLogonTimestamp

    $ConvertedLastLogin = [DateTime]::FromFileTime( [Int64]::Parse($ADLastLogon) )

    $ADDescription = "Disabled on " + $TerminationDate + " by This.User"

    $Justification = "Inactive computer - Last logon: " + $ConvertedLastLogin

    $ADOS = $ADAccount.OperatingSystem

    $ADOSSP = $ADAccount.OperatingSystemServicePack

    $ADFullOS = $ADOS + " " + $ADOSSP

    $Requestor = "This.UserSA"

    $DBDateTime = Get-Date

    

    #Disable Account

    Get-ADComputer -identity $ADSAM -properties *| Disable-ADAccount

    #Set AD Fields

    Get-ADComputer -identity $ADSAM -properties *| 

        Set-ADComputer -Description $ADDescription

    Get-ADComputer -identity $ADSAM -properties *| 

        Set-ADObject -clear info,tsaDisabledDate

    Get-ADComputer -identity $ADSAM -properties *| 

        Set-ADObject -ADD @{info=$Justification;tsaDisabledDate=$TerminationDate} 

    #Move to Pending Delete

    Get-ADComputer -identity $ADSAM -properties *| 

        move-ADObject -TargetPath 'ou=Pending Delete,dc=yourdomain,dc=org'

 

     #SQL Database Record information

    #Datafields: ProcessType, ComputerName, OS, Reason, Requestor, DateTime

    $Server = "ServerName"

    $Database = "DBName"

    $UserID = "User"

    $UserPassword = "Love really long passwords for others to use."

    $Table = "dbo.DisableComputersReport"

    $DateTimeRequest = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss.sss")

    $Connection = New-Object System.Data.SQLClient.SQLConnection

    $Connection.ConnectionString = "server=$Server;Initial Catalog=$Database;User ID=$UserID;Password=$UserPassword;"

    $Connection.Open()

    $Command = New-Object System.Data.SQLClient.SQLCommand

    $Command.Connection = $Connection

    $Command.CommandText = "INSERT INTO $Table (ProcessType, ComputerName, OS, Reason, Requestor, DateTime) VALUES ('ADCleanup','$ADSAM','$ADFullOS','$Justification','Test.UserSA','$DBDateTime')"

    $Command.ExecuteNonQuery()

    $Connection.Close()

    

}

These are a few PowerShell scripts/codes that I have found useful recently.  Hope you find some of these useful as well.