AD – Force SYSVOL and AD replication

Update 17/03/2016: Added a download link for the script.

Recently I’ve been doing a lot of work on group policies and due to the nature of our network replication between our domain controllers is slow. This was causing me issues when testing my changes as they hadn’t replicated to some domain controllers. Knowing that group policies consist of two parts files located in the SYSVOL and a version attribute in AD, I wanted a quick way of replicating my changes to all DC’s within our domain.

Below is a batch file that I written to do this.

Update 17/08/2015 : Now automatically determines all domains in a forest, and forces the KCC to recalculate.

@ECHO OFF

REM Location of the ntfrsutil tool from the File Replication Service Diagnostics Tool.
REM This can be downloaded from: http://www.microsoft.com/en-gb/download/details.aspx?id=8613
SET NTFRSUTL="C:\Program Files (x86)\Windows Resource Kits\Tools\FRSDiag\ntfrsutl.exe"

CALL :ForceKCCUpdate

REM Get the forest partition dn without specifying the parent domain.
FOR /F %%p IN ('dsquery * forestroot -scope subtree -filter "(objectClass=crossRefContainer)" -l -limit 0') DO (

	REM Get all parent/child domains from the forest configuration.
	FOR /F %%d IN ('dsquery * %%p -scope subtree -filter "(&(objectClass=crossRef)(nETBIOSName=*))" -attr dnsRoot -l -limit 0') DO (
		CALL :ReplicateDomain %%d
	)
)

GOTO END

:ReplicateDomain
	ECHO Replicating Domain: %1
	
	REM Replicate SYSVOL.
	FOR /F %%f IN ('DsQuery Server -domain %1 -limit 0 -o rdn') DO (
		FOR /F %%t IN ('DsQuery Server -domain %1 -limit 0 -o rdn') DO (
			IF /I "%%f" NEQ "%%t" (
				ECHO Replicating SYSVOL from %%f to %%t
				%NTFRSUTL% forcerepl %%t /r "Domain System Volume (SYSVOL share)" /p %%f
			)
		)
	)

	REM Replicate AD.
	ECHO Replicating AD
	repadmin /syncall %1 /APed

GOTO END

:ForceKCCUpdate
	ECHO Forcing KCC Update

	REM Force the KCC to recalculate in all sites.
	FOR /F %%s IN ('DsQuery Site -limit 0 -o rdn') DO (
		repadmin /kcc site:%%s
	)

GOTO END

:END

Download (Right click and click ‘Save Link as’)

Advertisements

AD – Reset the pwdLastSet attribute using PowerShell

Update 17/03/2016: Added a download link for the script.

I had a requirement to change some of our AD accounts so that the password expired as per our company policy. Instead of having to call every user to see if they were on-site or not, I wanted a way of making the account adhere without causing the account to expire immediately. After a little look around the internet I found that you could reset the password last set date in AD which would cause the account to expire after x days that our policy defines with all the usual prompts.

Below is a Powershell script that I created to achieve this.

# This script sets a users account so that the password is to expire as per our policy,
# and resets the last password change date so that the user doesn't need login and change
# their password straight away.

# Define input parameters the script can accept.
param
(
	[Parameter(Mandatory=$True)]
	[string]$SearchBase,

	[Parameter(Mandatory=$True)]
	[string]$DNSDomainName,

	[Parameter(Mandatory=$True)]
	[string]$sAMAccountName,

	[bool]$Change = $False,

	[string]$LogFile = $MyInvocation.MyCommand.Name + ".log"
)

$Culture = Get-Culture
If ((Test-Path $Logfile) -eq $False)
{
	# Add headers to the LogFile if it doesn't already exist.
	Add-Content $LogFile "sAMAccountName, LastChange, Today, Changed"
}

# Get the user & properties from AD
$ADUser = Get-ADUser -Filter {sAMAccountName -eq $sAMAccountName} -SearchScope Subtree -SearchBase $SearchBase -Properties Name,pwdLastSet,PasswordNeverExpires -Server $DNSDomainName

# Check that user exist before going further.
If($ADUser -eq $Null)
{
	Write-Host "User not found. Aborting."
}
Else
{
	# Get the sAMAccountName from AD (Don't rely on the users input)
	$ADsAMAccountName = $ADUser.sAMAccountName

	# Get todays date and format it correctly.
	$Today = Get-Date -Format ($Culture.DateTimeFormat.FullDateTimePattern)

	# Get the date of the last password change and format it correctly.
	$LastChange = Get-Date -Date ([DateTime]::FromFileTime($ADUser.pwdLastSet)) -Format ($Culture.DateTimeFormat.FullDateTimePattern)

	If ($Change -eq $True)
	{
		# Set the password to expired, must be done first.
		$ADUser.pwdLastSet = 0
		# Set the account so that the password expires.
		$ADUser.PasswordNeverExpires = $False
		# Save the changes
		Set-ADUser -Instance $ADUser -Server $DNSDomainName

		# Reset the date of the last password change to today.
		$ADUser.pwdLastSet = -1
		# Save the changes
		Set-ADUser -Instance $ADUser -Server $DNSDomainName

		# Inform the user of the script that the account was changed.
		Write-Host "Account Changed."
	}

	# Log the change to the LogFile.
	Add-Content $LogFile "$ADsAMAccountName, $LastChange, $Today, $Change"
}

Download (Right click and click ‘Save Link as’)

Example syntax for the script

./<script>.ps1 -SearchBase "DC=contoso,DC=lan" -DNSDomainName "contoso.lan" -Change $True -sAMAccountName <accountName>