Part 1 stood up the DC. Part 2 built the OU structure. This part populates the OUs with policies that actually do something.

The policies below are the minimum I run on every domain. Default Domain Policy out-of-the-box is permissive — 7-character passwords, no lockout, no audit. None of those are okay in 2026.

TL;DR — the GPOs to create and where to link them:

GPO Linked at Purpose
Password Policy Domain root Length, complexity, lockout
Audit Policy Domain root Logon, account changes, privilege use
Hardening — Protocols Domain root SMBv1 off, LLMNR off, NTLMv1 refused
RDP Restrictions OU=Servers Allow group, NLA enforced, IP scope
BitLocker Enforcement OU=Workstations and OU=Servers TPM unlock, recovery to AD
Defender Hardening All workstations ASR rules, tamper protection

Each one's a small, focused GPO. Don't make one giant "Hardening" GPO — they get hard to debug and require all-or-nothing rollback.

Password policy

Old default: 7 chars, complexity off, no lockout. Bad on a desktop, suicidal on a domain.

Edit Default Domain Policy (or build a new GPO and override) — Computer Config → Policies → Windows Settings → Security Settings → Account Policies:

Password Policy:
  Enforce password history: 24
  Maximum password age: 365 days   (or 0 = never expire, see below)
  Minimum password age: 1 day
  Minimum password length: 14
  Password must meet complexity: Enabled

Account Lockout Policy:
  Account lockout threshold: 5 invalid logon attempts
  Account lockout duration: 30 minutes
  Reset account lockout counter after: 30 minutes

Why 14 chars and no expiration: NIST recommends long passwords without forced rotation. Forced rotation breeds Spring2024!Summer2024! patterns. A 14-char password is computationally infeasible to brute force; rotation buys nothing on top of that.

If your auditor still demands 90-day rotation, set 90. Both are defensible — long-no-rotation is just better.

These are forest-wide. If you need per-OU exceptions (e.g. service accounts with stricter rules), use Fine-Grained Password Policies (PSO) via New-ADFineGrainedPasswordPolicy.

Audit policy

Default is "log a few things badly." You want detailed audit on logons and account changes.

Computer Config → Policies → Windows Settings → Security Settings → Advanced Audit Policy Configuration:

Account Logon:
  Audit Credential Validation: Success and Failure
  Audit Kerberos Authentication Service: Success and Failure
  Audit Kerberos Service Ticket Operations: Success and Failure

Account Management:
  Audit User Account Management: Success and Failure
  Audit Security Group Management: Success and Failure

Logon/Logoff:
  Audit Logon: Success and Failure
  Audit Logoff: Success
  Audit Special Logon: Success

Privilege Use:
  Audit Sensitive Privilege Use: Success and Failure

System:
  Audit System Integrity: Success and Failure
  Audit Security State Change: Success

Plus on the DC, increase Security log size:

Computer Config → Policies → Windows Settings → Security Settings →
  Event Log → Security: Maximum size = 1 GB

Default is 20 MB. Fills in a day on an active DC. 1 GB lets you actually look at events from last week. Forward to a SIEM if you have one.

Same audit lines you'd hunt with Get-WinEvent post-incident.

Protocol hardening — SMBv1, LLMNR, NTLMv1

The trio from the standalone post, now via GPO so every machine in the domain inherits.

LLMNR off:

Computer Config → Policies → Administrative Templates → Network → DNS Client →
  Turn off multicast name resolution: Enabled

NTLMv1 off:

Computer Config → Policies → Windows Settings → Security Settings → Local Policies →
  Security Options →
    Network security: LAN Manager authentication level = Send NTLMv2 only. Refuse LM & NTLM
    Microsoft network server: Digitally sign communications (always) = Enabled
    Network security: Restrict NTLM: Audit Incoming NTLM Traffic = Enable auditing for all accounts

The Restrict NTLM audit setting is reconnaissance — it logs what's still using NTLM so you can identify and replace it. Don't switch directly to "Deny" without auditing first; you will break legitimate things you didn't know existed.

SMBv1: GPO has no native toggle. Push via the registry path that the OS reads:

Computer Config → Preferences → Windows Settings → Registry → New →
  Hive: HKLM
  Key: SYSTEM\CurrentControlSet\Services\mrxsmb10
  Value name: Start
  Value type: REG_DWORD
  Value data: 4 (Disabled)

Reboot required — schedule.

NBT-NS via Preferences too — adapter setting, push as PowerShell startup script if needed.

The standalone hardening but pushed via GPO:

Computer Config → Policies → Administrative Templates → Windows Components →
  Remote Desktop Services → Remote Desktop Session Host → Security:
    Require user authentication for remote connections by using NLA: Enabled
    Set client connection encryption level: High Level

Restrict who can RDP in:

Computer Config → Policies → Windows Settings → Security Settings → Local Policies →
  User Rights Assignment:
    Allow log on through Remote Desktop Services: <your IT-Admins group>

Remove Administrators from this list (counterintuitively) — instead, members of IT-Admins who happen to also be local admins can RDP. Default-deny is the goal.

Restrict from where:

Computer Config → Policies → Windows Settings → Security Settings → Windows Firewall →
  Inbound Rules → "Remote Desktop - User Mode (TCP-In)":
    Scope → Remote IP: <your trusted ranges>

Link the GPO at OU=Servers,OU=Computers,OU=Corp,DC=.... Workstations get a separate (looser, e.g. LAN-only) RDP policy.

BitLocker enforcement

Computer Config → Policies → Administrative Templates → Windows Components →
  BitLocker Drive Encryption → Operating System Drives:
    Require additional authentication at startup: Enabled
      Allow BitLocker without a compatible TPM: No
    Choose how BitLocker-protected operating system drives can be recovered:
      Save BitLocker recovery information to AD DS: Enabled
      Do not enable BitLocker until recovery information is stored: Enabled

This forces:

  1. New machines must encrypt the OS drive.
  2. They must have a TPM (modern hardware does).
  3. The recovery key auto-saves into the AD object — no more "where did we put the key" panics.

Recovery keys then visible via Get-ADObject -Filter ... -Properties msFVE-RecoveryPassword or in the BitLocker tab of the computer object in ADUC.

Pair with the BitLocker-on-server post for the manual side.

Defender ASR rules

Microsoft Defender Attack Surface Reduction — block specific tactics like "Office macros launch processes":

Computer Config → Policies → Administrative Templates → Windows Components →
  Microsoft Defender Antivirus → Microsoft Defender Exploit Guard →
    Attack Surface Reduction → Configure Attack Surface Reduction rules: Enabled

  Add rule IDs as values, set to "Block":
    BE9BA2D9-53EA-4CDC-84E5-9B1EEEE46550   ← Block Office from creating child processes
    D4F940AB-401B-4EFC-AADC-AD5F3C50688A   ← Block Office from creating executable content
    9E6C4E1F-7D60-472F-BA1A-A39EF669E4B2   ← Block credential stealing from LSASS
    D3E037E1-3EB8-44C8-A917-57927947596D   ← Block JS/VBScript launching downloaded content

There are ~15 ASR rules. Start with these four — high signal, low false positive. Add more after a month of audit-mode (Audit instead of Block first).

Linking and inheritance

$domain = "DC=lab,DC=example,DC=com"

# Domain-wide
New-GPLink -Name "Password-Policy" -Target $domain
New-GPLink -Name "Audit-Policy" -Target $domain
New-GPLink -Name "Protocol-Hardening" -Target $domain

# OU-scoped
New-GPLink -Name "RDP-Server-Policy" -Target "OU=Servers,OU=Computers,OU=Corp,$domain"
New-GPLink -Name "BitLocker-Workstations" -Target "OU=Workstations,OU=Computers,OU=Corp,$domain"
New-GPLink -Name "BitLocker-Servers" -Target "OU=Servers,OU=Computers,OU=Corp,$domain"
New-GPLink -Name "Defender-ASR" -Target "OU=Workstations,OU=Computers,OU=Corp,$domain"

GPO inheritance is top-down: domain root → OU → child OU. Settings further down win on conflict (last applied wins). Use Enforced sparingly to override child blocks; use Block Inheritance even more sparingly because it cuts everything.

Test before pushing domain-wide

Critical: test new GPOs on a single machine before linking to the domain.

  1. Create the GPO unlinked.
  2. Link to OU=Test containing one VM.
  3. gpupdate /force on the VM, reboot, verify.
  4. Test for at least a day under normal use.
  5. Move the link to broader scope.

Skip this and your "small password tweak" will lock out the CEO at 9am Monday.

What this combines with

Every other Windows-server post in the cluster:

GPO is the multiplier: do the work once at the domain level, every joined machine inherits.

Gotchas

  • GPOs cache for 90 minutes by default. Changes don't apply instantly. gpupdate /force triggers immediately on one machine. Domain-wide is "next refresh".
  • Don't edit Default Domain Policy and Default Domain Controllers Policy with abandon. They have Microsoft-blessed defaults; create new GPOs with overrides instead. Easier to roll back.
  • WMI filters slow GPO processing. Powerful but expensive — use security-group filtering when you can.
  • Loopback processing is a niche feature. Ignore until you have a specific need (terminal-server kiosk, etc.). Adding it casually breaks user-policy expectations.
  • Audit GPO links after restructures. Moving an OU doesn't move the linked GPOs — the new parent's GPOs apply, not the OU's old ones.

This is the spine. Every additional hardening (vendor-specific antivirus, DLP, EDR baselines) layers on top via more GPOs. With the OU structure from Part 2 and these baseline policies, you have a defensible domain ready for actual workloads.


Related posts