Configuring Password Expiration with PowerShell

Key Takeaways

  • Password expiration policies are critical in enhancing IT security and promoting good cyber hygiene.
  • The provided PowerShell script efficiently adjusts the Maximum Password Age for domain or non-domain computers.
  • The script requires PowerShell version 5.1 and the RSAT feature for Active Directory.
  • Depending on provided parameters, the script modifies the Active Directory Default Domain Password Policy or the local machine’s policy.
  • PowerShell scripts offer scalability and efficiency compared to traditional GUI-based tools for IT tasks.
  • Always back up configurations, inform users of changes, and audit the effects of policy modifications.
  • Balancing the frequency of password changes is vital to avoid potential security pitfalls.
  • NinjaOne, with scripts like these, helps IT professionals manage complex digital environments seamlessly.

With the continuous rise in cyber threats, managing password policies efficiently has never been more critical in the IT world. Proper password management not only ensures a robust defense against potential breaches but also promotes good cyber hygiene among users. One such essential policy is configuring password expiration. Today, we’ll discuss a PowerShell script that enables you to change the Maximum Password Age, which dictates the expiration timeframe for domain or non-domain computers.

Background

The script provided aims to streamline the process of modifying password expiration policies. As IT environments grow and evolve, the need for centralized, efficient, and scalable methods to manage user credentials becomes paramount. IT professionals and Managed Service Providers (MSPs) often find themselves juggling various systems, policies, and user requirements. With PowerShell, a powerful task automation framework, adjusting something as vital as password expiration across several systems becomes feasible.

The Script

#Requires -Version 5.1

<#
.SYNOPSIS
    Changes the Maximum Password Age(Expiry) for the domain or a non-domain computer.
.DESCRIPTION
    Changes the Maximum Password Age(Expiry) for the domain or a non-domain computer.
.EXAMPLE
     -MaxPasswordAge 90
    Set MaximumPasswordAge on the computer this script runs on to 90 days.
.EXAMPLE
     No param needed
    Disables MaximumPasswordAge on the computer this script runs on.
.EXAMPLE
     -MaxPasswordAge 90 -Domain "test.consto.com"
    Enables MaximumPasswordAge in Active Directory for the Default Domain Password Policy to 90 days.
.EXAMPLE
    PS C:> .Set-Password-Complexity.ps1 -MaxPasswordAge 90 -Domain "test.consto.com"
    Enables MaximumPasswordAge in Active Directory for the Default Domain Password Policy to 90 days.
.OUTPUTS
    None
.NOTES
    Minimum OS Architecture Supported: Windows 10, Windows Server 2016
    The RSAT feature for Active Directory needs to be installed on the computer this runs on.
    Release Notes:
    Initial Release
By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use.
    Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. 
    Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. 
    Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. 
    Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. 
    Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. 
    Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. 
    EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).
.COMPONENT
    ManageUsers
#>

[CmdletBinding()]
param (
    [Parameter(Mandatory = $false)]
    [int]
    $MaxPasswordAge,
    [Parameter(Mandatory = $false)]
    [String]
    $Domain
)

function Test-IsElevated {
    $id = [System.Security.Principal.WindowsIdentity]::GetCurrent()
    $p = New-Object System.Security.Principal.WindowsPrincipal($id)
    if ($p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator))
    { Write-Output $true }
    else
    { Write-Output $false }
}
function Get-LocalPasswordPolicy {
    param ()
    $Result = [PSCustomObject]@{
        MinimumLength = 0
        MaximumAge    = 0
        MinimumAge    = 0
    }
    $(net.exe accounts) -split "n" | ForEach-Object {
        $Line = $_ -split ":"
        if ($_ -like "Minimum password length*") {
            $Result.MinimumLength = "$($Line[1])".Trim(' ')
        }
        if ($_ -like "Maximum password age (days)*") {
            $Result.MaximumAge = "$($Line[1])".Trim(' ')
        }
        if ($_ -like "Minimum password age (days)*") {
            $Result.MinimumAge = "$($Line[1])".Trim(' ')
        }
    }
    $Result
}

if (-not (Test-IsElevated)) {
    Write-Error -Message "Access Denied. Please run with Administrator privileges."
    exit 1
}
$NetExeError = $false

$MaxAge = ""
if ($PSBoundParameters.ContainsKey("MaxPasswordAge")) {
    $MaxAge = $MaxPasswordAge
}
else {
    # If $MaxPasswordAge isn't used or is set to 0.
    $MaxAge = 0
}
if ($Domain -and [string]::IsNullOrEmpty($Domain) -and [string]::IsNullOrWhiteSpace($Domain)) {
    # Active Directory
    # Check if the ActiveDirectory module is installed
    if ((Get-Module -Name ActiveDirectory -ListAvailable -ErrorAction SilentlyContinue)) {
        try {
            # Try to import the ActiveDirectory module
            Import-Module -Name ActiveDirectory
        }
        catch {
            Write-Error -Message "Ninja Agent could not access AD, either RSAT was not installed or that the agent does not have permissions to add and remove users from groups."
            exit 5 # Access Denied exit code
        }
        # Set MaxPasswordAge to what was passed into $MaxPasswordAge
        Set-ADDefaultDomainPasswordPolicy -Identity $Domain -MaxPasswordAge $([TimeSpan]"$MaxPasswordAge.00:00:00") -Confirm:$false
        # Sleep a little while, just in case Get-ADDefaultDomainPasswordPolicy connect to a different AD server and replication is slow
        Start-Sleep -Seconds 60
        # Check if the MaxPasswordAge policy was applied correctly
        $Results = Get-ADDefaultDomainPasswordPolicy -Identity $Domain
        # Check that the policy matches what was requested
        if ($Results -and $Results.MaxPasswordAge.Days -eq $MaxPasswordAge) {
            exit 0
        }
        else {
            # The policy was not set for some reason
            exit 1
        }
    }
    else {
        Write-Error -Message "Ninja Agent could not access AD, RSAT was not installed."
        Write-Output "RSAT install documentation: https://docs.microsoft.com/en-us/troubleshoot/windows-server/system-management-components/remote-server-administration-tools"
        Write-Output "Windows Server install command: Install-WindowsFeature RSAT"
        Write-Output "Windows 10/11 install command: Add-WindowsCapability -Name RSAT* -Online"
        exit 5 # Access Denied exit code
    }
}
else {
    # Get Current localhost password policy settings
    $CurrentSettings = Get-LocalPasswordPolicy
    Write-Host "Changing Maximum Password Age from $($CurrentSettings.MaximumAge) to $MaxAge"
    if ($MaxAge -ge 1 -and $MaxAge -is [int]) {
        net.exe accounts /maxpwage:$MaxAge
    }
    else {
        net.exe accounts /maxpwage:unlimited
    }

    # Get New localhost password policy settings and check if anything changed
    $NewSettings = Get-LocalPasswordPolicy
    
    if ($MaxAge -notlike $(if ($NewSettings.MaximumAge -like "unlimited") { 0 }else { $NewSettings.MaximumAge })) {
        $NetExeError = $true
        Write-Host "Maximum Age was not set correctly."
    }
    if ($NetExeError) {
        exit 1
    }
}

 

Access 300+ scripts in the NinjaOne Dojo

Get Access

Detailed Breakdown

Let’s dive into the nitty-gritty of how the script operates:

  • Prerequisites: The script requires PowerShell version 5.1 and the Remote Server Administration Tools (RSAT) feature for Active Directory.
  • Parameters: Two main parameters can be passed – MaxPasswordAge, defining the maximum number of days before the password expires, and Domain, specifying the domain for which the password policy needs to be adjusted.
  • Functions: The script includes helper functions like Test-IsElevated to check if the script is running with administrator rights and Get-LocalPasswordPolicy to retrieve the current password policy of the local computer.
  • Execution Flow: Depending on whether a domain is provided, the script adjusts the Active Directory Default Domain Password Policy or the local computer’s password policy.

Potential Use Cases

Case Study: Imagine an MSP overseeing IT operations for a company with a growing workforce. New cybersecurity regulations demand that all employee passwords expire and be renewed every 60 days. Using the provided script, the MSP can efficiently adjust the Maximum Password Age for all computers in the domain, ensuring compliance without manually handling each system.

Comparisons

Traditionally, adjusting password policies, especially in larger networks, required navigating through GUI-based tools like the Group Policy Management Console. While effective, these methods might not scale efficiently. With the PowerShell approach, IT professionals can apply changes rapidly across multiple systems, ensuring consistency and saving time.

FAQs

  • Can I use this script on any Windows computer? 
    The script is designed for Windows 10, Windows Server 2016, and subsequent versions.
  • What happens if I don’t provide a MaxPasswordAge value? 
    The password expiration will be set to “unlimited,” essentially disabling the expiration.

Implications

Setting the right password expiration policies is a double-edged sword. While frequent changes can enhance security by limiting the time a compromised password is valid, it might also encourage users to opt for simpler passwords or note them down, reducing overall security. This script helps IT teams find the right balance and apply it consistently across their infrastructure.

Recommendations

  • Always backup current configurations before making changes.
  • It’s advisable to inform users about impending changes to password policies.
  • Monitor and audit the effects of password policy changes to ensure there are no unintended consequences.

Final Thoughts

As cyber threats evolve, tools like NinjaOne provide invaluable solutions to IT professionals, allowing them to stay ahead of potential challenges. By integrating scripts like the one discussed, NinjaOne offers a comprehensive platform that can address various IT management needs, from password policy adjustments to more intricate system configurations. As the digital landscape continues to transform, having tools that empower IT teams will be crucial to ensuring operational efficiency and security.

Next Steps

Building an efficient and effective IT team requires a centralized solution that acts as your core service deliver tool. NinjaOne enables IT teams to monitor, manage, secure, and support all their devices, wherever they are, without the need for complex on-premises infrastructure.

Learn more about NinjaOne Remote Script Deployment, check out a live tour, or start your free trial of the NinjaOne platform.

Categories:

You might also like

Watch Demo×
×

See NinjaOne in action!

By submitting this form, I accept NinjaOne's privacy policy.

NinjaOne Terms & Conditions

By clicking the “I Accept” button below, you indicate your acceptance of the following legal terms as well as our Terms of Use:

  • Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms.
  • Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party.
  • Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library belonging to or under the control of any other software provider.
  • Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations.
  • Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks.
  • Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script.
  • EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).