Introduction to Fine-Grained Password Policies

In legacy Active Directory deployments, a single password policy applied to all users within a domain through the Default Domain Policy GPO. This was limiting for organizations that needed stricter controls on privileged accounts such as domain administrators or service accounts while maintaining a more relaxed policy for regular users. Windows Server 2008 introduced Fine-Grained Password Policies (FGPP), also called Password Settings Objects (PSOs), and Windows Server 2022 continues full support for this feature through both the Active Directory Administrative Center and PowerShell.

Fine-Grained Password Policies allow you to define multiple password policies within a single domain and apply them to specific users or global security groups. A PSO can override the domain-level policy for targeted principals, enabling you to enforce high-complexity requirements on IT administrators while allowing standard users to follow simpler rules. This guide walks through creating, configuring, and verifying PSOs on Windows Server 2022 using PowerShell and Active Directory Administrative Center.

Prerequisites

Before configuring Fine-Grained Password Policies, ensure the following conditions are met. The domain functional level must be Windows Server 2008 or higher. You must be a member of the Domain Admins group or the Password Settings Container Admins delegated group. The Active Directory module for Windows PowerShell must be installed on your management workstation or domain controller.

To verify your domain functional level, run the following command:

Get-ADDomain | Select-Object Name, DomainMode

To install the Active Directory PowerShell module on Windows Server 2022 if it is not already present:

Install-WindowsFeature -Name RSAT-AD-PowerShell

Understanding PSO Structure and Precedence

A Password Settings Object is a special Active Directory object stored in the Password Settings Container under CN=Password Settings Container,CN=System,DC=yourdomain,DC=com. Each PSO contains the same configurable attributes as the traditional domain password policy, including minimum password length, complexity requirements, lockout settings, and password history count.

The most important property when working with multiple PSOs is the Precedence value (msDS-PasswordSettingsPrecedence). This is a positive integer where a lower number indicates higher priority. If a user is subject to multiple PSOs (through direct assignment and group membership), the PSO with the lowest precedence number wins. If two PSOs share the same precedence number, the one with the lowest GUID takes effect. Best practice is to assign unique precedence values to avoid ambiguity.

PSOs can be applied to:

– Global security groups (preferred for manageability)

– Individual user objects (for exceptions or break-glass accounts)

PSOs cannot be applied to organizational units (OUs) directly. If you need OU-scoped application, you must create a shadow group that mirrors OU membership and apply the PSO to that group.

Creating a Fine-Grained Password Policy with PowerShell

The New-ADFineGrainedPasswordPolicy cmdlet creates a new PSO in Active Directory. The following example creates a strict policy called PrivilegedAccountPolicy intended for domain administrators and privileged service accounts:

New-ADFineGrainedPasswordPolicy `
    -Name "PrivilegedAccountPolicy" `
    -Precedence 10 `
    -MinPasswordLength 20 `
    -PasswordHistoryCount 24 `
    -MaxPasswordAge "30.00:00:00" `
    -MinPasswordAge "1.00:00:00" `
    -ComplexityEnabled $true `
    -ReversibleEncryptionEnabled $false `
    -LockoutThreshold 3 `
    -LockoutDuration "00:30:00" `
    -LockoutObservationWindow "00:30:00" `
    -Description "High-security PSO for privileged accounts and Domain Admins"

A second, more relaxed PSO for standard employees might look like this:

New-ADFineGrainedPasswordPolicy `
    -Name "StandardUserPolicy" `
    -Precedence 50 `
    -MinPasswordLength 12 `
    -PasswordHistoryCount 12 `
    -MaxPasswordAge "90.00:00:00" `
    -MinPasswordAge "1.00:00:00" `
    -ComplexityEnabled $true `
    -ReversibleEncryptionEnabled $false `
    -LockoutThreshold 10 `
    -LockoutDuration "00:15:00" `
    -LockoutObservationWindow "00:15:00" `
    -Description "Standard PSO for all domain users"

Note that time values are specified in the format Days.Hours:Minutes:Seconds. A value of "30.00:00:00" means 30 days.

Applying PSOs to Users and Groups

Once a PSO is created, it has no effect until it is linked to a principal. Use Add-ADFineGrainedPasswordPolicySubject to assign it:

# Apply to the Domain Admins global security group
Add-ADFineGrainedPasswordPolicySubject `
    -Identity "PrivilegedAccountPolicy" `
    -Subjects "Domain Admins"

# Apply to a specific privileged service account user object
Add-ADFineGrainedPasswordPolicySubject `
    -Identity "PrivilegedAccountPolicy" `
    -Subjects "svc-sqlprod"

# Apply the standard policy to the All Staff group
Add-ADFineGrainedPasswordPolicySubject `
    -Identity "StandardUserPolicy" `
    -Subjects "All Staff"

To remove a subject from a PSO:

Remove-ADFineGrainedPasswordPolicySubject `
    -Identity "PrivilegedAccountPolicy" `
    -Subjects "svc-sqlprod" `
    -Confirm:$false

Modifying an Existing PSO

Use Set-ADFineGrainedPasswordPolicy to update properties on an existing PSO without recreating it. For example, to extend the max password age and increase the lockout threshold on the standard policy:

Set-ADFineGrainedPasswordPolicy `
    -Identity "StandardUserPolicy" `
    -MaxPasswordAge "60.00:00:00" `
    -LockoutThreshold 5 `
    -LockoutDuration "00:30:00"

To change the precedence value of a PSO (for example, to make it take priority over another policy):

Set-ADFineGrainedPasswordPolicy -Identity "PrivilegedAccountPolicy" -Precedence 5

Viewing and Verifying PSOs

Use Get-ADFineGrainedPasswordPolicy to list all PSOs in the domain or inspect a specific one:

# List all PSOs with key properties
Get-ADFineGrainedPasswordPolicy -Filter * | 
    Select-Object Name, Precedence, MinPasswordLength, MaxPasswordAge, LockoutThreshold |
    Format-Table -AutoSize

# Inspect a specific PSO in full detail
Get-ADFineGrainedPasswordPolicy -Identity "PrivilegedAccountPolicy" | Format-List *

To see which principals are linked to a given PSO:

Get-ADFineGrainedPasswordPolicySubject -Identity "PrivilegedAccountPolicy"

Determining the Resultant PSO for a User

The most important verification step is confirming which PSO actually applies to a given user — the resultant PSO. Use Get-ADUserResultantPasswordPolicy for this:

# Check the effective PSO for a specific user
Get-ADUserResultantPasswordPolicy -Identity "jsmith"

# Check all domain admins
Get-ADGroupMember "Domain Admins" | ForEach-Object {
    $user = $_
    $pso = Get-ADUserResultantPasswordPolicy -Identity $user.SamAccountName -ErrorAction SilentlyContinue
    [PSCustomObject]@{
        User = $user.SamAccountName
        AppliedPSO = if ($pso) { $pso.Name } else { "Default Domain Policy" }
        MinLength = if ($pso) { $pso.MinPasswordLength } else { "N/A" }
    }
}

If no PSO is assigned (directly or through group membership), the user falls back to the Default Domain Policy configured in the Default Domain Policy GPO. The Get-ADUserResultantPasswordPolicy cmdlet returns $null in that case.

Comparing FGPP vs Domain-Level Password Policy

The domain-level password policy is configured in the Default Domain Policy GPO under Computer Configuration > Windows Settings > Security Settings > Account Policies > Password Policy. It applies to all domain user accounts unless a PSO overrides it. PSOs take precedence over this policy for any directly or indirectly assigned principals.

To view the current Default Domain Policy password settings:

Get-ADDefaultDomainPasswordPolicy -Identity "yourdomain.com" | Format-List *

Key differences between FGPP and the domain policy are: PSOs can have different settings per group or user; the domain policy is a single flat GPO setting; PSOs are stored in AD objects (not GPOs); and PSOs require domain functional level 2008 or higher.

Enabling AD Audit Logging for Password Changes

To track password-related events, enable advanced audit policy on your domain controllers. Password changes generate Event ID 4723 (user changed own password), 4724 (admin reset a password), and 4740 (account lockout). Enable the relevant audit subcategories via Group Policy:

# View current audit policy settings on the local DC
auditpol /get /subcategory:"Account Management"

# Enable success and failure auditing for User Account Management
auditpol /set /subcategory:"User Account Management" /success:enable /failure:enable

# Enable Credential Validation auditing
auditpol /set /subcategory:"Credential Validation" /success:enable /failure:enable

You can also configure these via GPO at Computer Configuration > Windows Settings > Security Settings > Advanced Audit Policy Configuration > Account Management. Apply the GPO to the Domain Controllers OU and run gpupdate /force on each DC.

To query the Security event log for password-related events using PowerShell:

Get-WinEvent -ComputerName DC01 -FilterHashtable @{
    LogName = 'Security'
    Id = 4723, 4724, 4740
    StartTime = (Get-Date).AddDays(-7)
} | Select-Object TimeCreated, Id, Message | Format-Table -AutoSize -Wrap

Managing PSOs with Active Directory Administrative Center

In addition to PowerShell, you can manage PSOs graphically through the Active Directory Administrative Center (ADAC). Open ADAC, navigate to your domain, then browse to System > Password Settings Container. Right-click to create a new Password Settings object, fill in the form fields, and use the Members section to add users or groups. ADAC provides a clean interface for reviewing all PSOs in a single view and is useful for administrators who prefer a GUI workflow for day-to-day operations.

Best Practices for Fine-Grained Password Policies

Apply PSOs to global security groups rather than individual users whenever possible. This simplifies management because group membership changes automatically adjust which policy applies. Use a tiered precedence scheme — for example, 10 for privileged accounts, 20 for service accounts, 50 for standard users — leaving gaps between tiers so future policies can be inserted without renumbering. Document all PSOs and their assigned groups in a configuration management database (CMDB). Regularly audit PSO assignments using Get-ADFineGrainedPasswordPolicySubject to ensure no unexpected principals have been added. Test new PSOs in a staging domain before deploying to production to verify the resultant policy behaves as intended. Finally, coordinate FGPP changes with your identity governance or helpdesk team, as stricter lockout policies on privileged accounts can cause operational disruption if not communicated in advance.