« Previous 1 2 3 Next »
Manage Windows AD with PowerShell
Organized
Making Changes
You can modify users of a certain OU with a one-liner so that they all have a certain attribute value, allowing other programs (e.g., AADConnect
for synchronization to the cloud) to find and process them:
Get-ADUser -Filter * -SearchBase "OU=Externals,DC=corp,DC=frickelsoft,DC=net" | Set-ADUser -Add @{extensionAttribute4 = "M365"}
An imported CSV file lets you edit multiple users:
Import-CSV 'C:\temp\csv\users.csv' | % { if($_. mail-like '*@frickelsoft.net') { Set-ADUser $_.sAMAccountName -Add @{extensionAttribute4 ="M365"}}}
This command imports a CSV file that contains user definitions and parses it line by line. Two columns in the CSV are inspected more closely: mail
and sAMAccountName
(Figure 2). If the mail address ends with @frickelsoft.net
, extensionAttribute4
of the user in AD is set to M365
. Nothing happens for the other users found in the CSV file.
To transfer the value of the region
column to an AD attribute (e.g., preferredDataLocation
for Office 365), you need to modify the command
Import-CSV '.\Downloads\users.csv' | % { Set-ADUser -Identity $_.sAMAccountName-Add @{preferredDataLocation =$_.region }}
to take the cell value from the CSV file instead of using a fixed value.
Managing Special Accounts
Of course, you will not only want to manage normal user accounts, but also accounts belonging to external partners and suppliers or service accounts. You can simply disable accounts that are no longer needed:
Get-ADUser -Identity svc_low_SQL3 | Disable-ADAccount
This method also works with accounts belonging to external identities that are grouped in an OU. To block people or service accounts that have not logged in for 120 days or more, use:
$lastLogonCutOff = (Get-Date). AddDays(-120) Get-ADUser -Filter { LastLogonDate -lt $lastLogonCutOff -and Enabled -eq $true } -SearchBase "OU=Externals,DC=corp,DC=frickelsoft,DC=net" | Disable-ADAccount
In the best case, the service accounts that you create as normal user accounts and not as group-managed service accounts (gMSA) are restricted to the extent that the logon can only take place on certain machines to avoid misuse. To define this case, use the LogonWorkstations
parameter:
Set-ADUser svc_low_SQL3 -LogonWorkstations "SQL3"
This attribute expects a comma-separated list of machine names. For example, you can create a new service account that you want to log on to all SQL servers with:
$sqlServers = Get-ADComputer -Filter "Name -like 'SQL*'" -SearchBase "OU=Servers,OU=Tier1,DC=corp,DC=frickelsoft,DC=net" | SELECT sAMAccountName |%{$_.sAMAccountName.Trim("$")} $sqlServers = $sqlServers -join "," Set-ADUser svc_high_SQL3 -LogonWorkstations $sqlServers
If you only want the service account to be valid for a time-limited project, or if the owner of the account is required to come back and renew the account within 90 days at the latest, you can set an expiration date:
Set-ADAccountExpiration -Identity svc_low_SQL3 -TimeSpan 90.00:00:00
You will certainly want to minimize the number of accounts whose passwords never expire. In fact, apart from service accounts, there should be no accounts in AD whose passwords do not expire:
Search-ADAccount -PasswordNeverExpires | Export-CSV C:\temp\csv\neverexpires.csv
Alternatively, you can move these accounts to a group for delegated administration:
Search-ADAccount -PasswordNeverExpires | %{Add-ADGroupMember -Identity "PWDNeverExpires" -Members $_.sAMAccountName }
If you specifically need to harden certain accounts against hijacking and ensure that the passwords used are appropriately complex, you can attach custom password policies to these accounts. For example, with a few lines of PowerShell, you can create a new password settings object that contains custom password policies and assign it to a group of service accounts. First, create the password policy object that enforces manual unlocking and long, complex passwords (Listing 1).
Listing 1
Enforcing Complex Passwords
New-ADFineGrainedPasswordPolicy -Name "HighSecServiceAccountsPolicy" -Precedence 500 -ComplexityEnabled $true -Description "Password Policy for High Sec Service Accts" -DisplayName "High Sec Service Accs PassPolicy" -LockoutDuration "00:00:00" -LockoutObservationWindow "00:00:00" -LockoutThreshold 7 -MinPasswordAge "01:00:00" -PasswordHistoryCount 20 -MinPasswordLength 16
After that, define a new AD group to which you then add the service accounts as members before assigning the policy (Listing 2).
Listing 2
Defining New AD Group
New-ADGroup -Name "High Sec Service Accts" -SamAccountName HighSecSer-viceAccts -GroupCategory Security -GroupScope Global -DisplayName "High Sec Service Accts" -Path "OU=Groups,OU=Service Accounts, DC=corp,DC=frickelsoft,DC=net" -Description "Members of this group are High Security Service Accounts" Add-ADFineGrainedPasswordPolicySubject -Identity HighSecServiceAccountsPolicy -Subjects 'HighSecServiceAccts'
Finally, search and find the service accounts to be protected in AD:
Get-ADUser -Filter 'DisplayName -like "SVC_HIGH_*"' -SearchBase "OU=Service Accounts,DC= corp,DC=frickelsoft,DC=net" | % { Add-ADGroupMember "High Sec Service Accounts" -Members $_ }
The next time the password is changed, the service accounts – or the admin who resets and changes the passwords – has to comply with the new password policy.
Managing Forests and AD Services
PowerShell lets you inspect the AD service itself, as well as manage the data in the directory. Cmdlets let you create new domain controllers, domains, AD objects, and partitions and inspect existing objects:
$forest = Get-ADForest -Server "corp.frickelsoft.net" foreach($domain in $forest.Domains) { Get-ADDomainController -Filter * -Server $Domain }
The following two cmdlets show you the flexible single master operation (FSMO) role holders:
Get-ADForest | SELECT DomainNamingMaster, SchemaMaster Get -ADDomain -Name corp.frickelsoft.net | SELECT InfrastructureMaster, PDCEmulator, RIDMaster
The Get-ADDomain
and Get-ADForest
cmdlets have additional properties that you can use for an inventory or check: The DomainFunctionalLevel
can be found in DomainMode
for each domain, and the ForestFunctionalLevel
is found in ForestMode
for forest objects.
If you want to provision devices that have been added to the domain to an Azure AD, you need to configure a hybrid Azure AD join. One step in the configuration is to create the service connection object manually or automatically in the configuration partition of the AD. To check whether the object has been created, use:
configPartition = (Get-ADRootDSE).configurationNamingContext Get-ADObject -Filter * -SearchBase "LDAP://CN=62a0ff2e-97b9-4513-943f-0d221bd30080,CN=Device Registration Configuration,CN=Services,$($configPartition)"
You can check the AD schema version with PowerShell with:
Get-ADObject (Get-ADRootDSE).schemaNamingContext -Property objectVersion
Output of version 88 means Windows Server 2019, 87 means Windows Server 2016, and 69 means Windows Server 2012 R2.
If you use Exchange, you can find the schema version for Exchange with:
Get-ADObject -Identity "CN=ms-Exch-Schema-Version-Pt,$((Get-ADRootDSE).schemaNamingContext)" -Properties rangeUpper | SELECT rangeUpper
Exchange Server 2019 has version numbers starting from 17000, whereas Exchange version 2016 is in the range of 15317 to 15333.
« Previous 1 2 3 Next »
Buy this article as PDF
(incl. VAT)
Buy ADMIN Magazine
Subscribe to our ADMIN Newsletters
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Most Popular
Support Our Work
ADMIN content is made possible with support from readers like you. Please consider contributing when you've found an article to be beneficial.