Last Update: Sep 04, 2024 | Published: Sep 16, 2019
In this article, I show you how to manage and secure Active Directory using PowerShell. I’ll look at the most useful PowerShell cmdlets and give examples of how to use them.
The New-ADUser cmdlet is for creating new AD users. You can optionally specify where to create new users with the -Path parameter. In the example below, the new user will be created in the Accounts Organizational Unit (OU). The -Server parameter is also optional. It is used to determine on which domain controller (DC) the new user will be created. Note that you cannot specify a password in plaintext in the -AccountPassword parameter. You must convert it to a secure string using the ConvertTo-SecureString cmdlet.
New-ADUser -DisplayName:"Russell Smith" -GivenName:"Russell" -Name:"Russell Smith" -Path:"OU=Accounts,DC=ad,DC=contoso,DC=com" -SamAccountName:"russellsmith" -Server:"dc1.ad.contoso.com" -Surname:"Smith" -Type:"user" -AccountPassword (ConvertTo-SecureString Pas$W0rd!!11 -AsPlainText -Force) -Enabled $true
Adding groups to AD is easy with the New-ADGroup cmdlet. -Server and -Path parameters are both optional.
New-ADGroup -GroupCategory:"Security" -GroupScope:"Global" -Name:"Netwrix" -Path:"OU=Accounts,DC=ad,DC=contoso,DC=com" -SamAccountName:"Netwrix" -Server:"dc1.ad.contoso.com"
Once you have some users and groups in your domain, you can add users to groups with the Add-ADGroupMember cmdlet.
Add-ADGroupMember -Identity Netwrix -Members russellsmith,bob.trent
Use the New-ADOrganizationalUnit cmdlet to create new Organizational Units (OU) in AD. Note that the -ProtectedFromAccidentalDeletion flag is optional. When set to $true, you can’t delete the OU without first changing the status of the flag to $false.
New-ADOrganizationalUnit -Name:"Sensitive" -Path:"OU=Accounts,DC=ad,DC=contoso,DC=com" -ProtectedFromAccidentalDeletion:$true -Server:"dc1.ad.contoso.com"
The ‘Remove’ verb is used in AD cmdlets to delete objects. Remove-ADUser and Remove-ADGroup are used respectively to delete users and groups.
Remove-ADUser -Identity russellsmith Remove-ADGroup -Identity Netwrix
Before you can delete an OU, you need to set the accidental deletion flag to false using Set-ADObject.
Set-ADObject -Identity:"OU=Sensitive,OU=Accounts,DC=ad,DC=contoso,DC=com" -ProtectedFromAccidentalDeletion:$false -Server:"dc1.ad.contoso.com" Remove-ADOrganizationalUnit -Identity "OU=Sensitive,OU=Accounts,DC=ad,DC=contoso,DC=com"
PowerShell makes it easy to automate tasks. In the script below, I use a comma-delimited (CSV) text file to create two users with the Import-Csv and New-ADUser cmdlets. The only trickery involved is splitting the first field of each entry in the text file so that I can separate the first and surnames for the -GiveName and -Surname parameters of the New-ADUser cmdlet.
Import-Csv -Path c:tempusers.csv | ForEach-Object { $givenName = $_.name.split()[0] $surname = $_.name.split()[1] New-ADUser -Name $_.name -Enabled $true –GivenName $givenName –Surname $surname -Accountpassword (ConvertTo-SecureString $_.password -AsPlainText -Force) -ChangePasswordAtLogon $true -SamAccountName $_.samaccountname –UserPrincipalName ($_.samaccountname+”@ad.contoso.com”) -City $_.city -Department $_.department }
The first line of the text file contains the field names. You can add as many users as you want.
Name,samAccountName,Password,City,Department
Russell Smith,smithrussell,PassW0rd!!11,London,IT
David Jones,jonesdavid,4SHH$$#AAAHh,New York,Accounts
The Move-ADObject cmdlet is for moving AD objects. In the example below, I move a user account from the Accounts OU to the Users container.
Move-ADObject -Identity "CN=Russell Smith,OU=Accounts,DC=ad,DC=contoso,DC=com" -TargetPath "CN=Users,DC=ad,DC=contoso,DC=com"
While PowerShell can’t be used to create Group Policy Objects (GPO), it can be used to perform other tasks related to Group Policy. The New-GPLink cmdlet is used to link existing GPOs to OUs. In the example below, I link a GPO called Firewall Settings to the Accounts OU.
New-GPLink -Name "Firewall Settings" -Target "OU=Accounts,DC=ad,DC=contoso,DC=com" -LinkEnabled Yes -Enforced Yes
The Get-ADObject cmdlet can be used to filter the directory and display information about objects. In the example below, I use a filter to find the Accounts OU and then pipe the results to the Get-GPInheritence cmdlet. Select-Object is then used to extract information about the GPOs linked to the OU.
Get-ADObject -Filter {name -like "Accounts*"} | Get-GPInheritance | Select-Object -Expand gpolinks | ForEach-Object {Get-GPO -Guid $_.gpoid}
One of the most useful cmdlets for AD admins is the Search-ADAccount cmdlet. In the example below, I search the domain for locked out user accounts and automatically unlock them using Unlock-ADAccount.
Search-ADAccount –LockedOut | Unlock-ADAccount
Get-ADObject can be used with complex filters. Here I list all objects created after the specified date ($Date).
$Date = [Datetime]"02/07/2019" Get-ADObject -Filter 'WhenCreated -GT $Date'
Filters can get quite complex. In the next command, I list all deleted objects where the change attribute is later than the specified date, and that can be restored, excluding the Deleted Objects container.
Get-ADObject -Filter 'whenChanged -gt $Date -and isDeleted -eq $True -and name -ne "Deleted Objects"' -IncludeDeletedObjects
Finally, I use Get-EventLog to search the event logs on each DC for login event ID 4624. Note the use of Get-ADDomainController to return all the DCs in the domain. Once I’ve retrieved the necessary information, I use Write-Host to write the output to the terminal window, with information separated by tabs to make it easier to read.
$DCs = Get-ADDomainController -Filter * $startDate = (get-date).AddDays(-1) foreach ($DC in $DCs){ $slogonevents = Get-Eventlog -LogName Security -ComputerName $DC.Hostname -after $startDate | Where-Object {$_.eventID -eq 4624 }} foreach ($e in $slogonevents){ if (($e.EventID -eq 4624 ) -and ($e.ReplacementStrings[8] -eq 2)){ write-host "Type: Local Logon`tDate: "$e.TimeGenerated "`tStatus: Success`tUser: "$e.ReplacementStrings[5] "`tWorkstation: "$e.ReplacementStrings[11] } if (($e.EventID -eq 4624 ) -and ($e.ReplacementStrings[8] -eq 10)){ write-host "Type: Remote Logon`tDate: "$e.TimeGenerated "`tStatus: Success`tUser: "$e.ReplacementStrings[5] "`tWorkstation: "$e.ReplacementStrings[11] "`tIP Address: "$e.ReplacementStrings[18] }}
Related Article: