Part 7: Managing Local Administrator Passwords

This is Part 7 of a multi-part series on managing local admin passwords. In this part I will provide fnMain which controls the order of all of the other functions in the script and I will also provide the completed Local Admin Password Management script.  In case you missed it:

Here is Part 1 - Overview

Here is Part 2 - Random Password Generation

Here is Part 3 - Secure Active Directory Attribute Update

Here is Part 4 - Update Local Account's Password

Here is Part 5 - Logging The Update Process

Here is Part 6 - Extending The Active Directory Schema

If you want to skip straight to the script  or you can download the script which is attached to this post as a text file. The attached script MUST be opened in PowerShell ISE to display properly. If you open the attached script in Notepad with word wrap enabled or any text editor with word wrap enabled you may be unable to properly run the script afterwards.

The Problem

So now you have all of these functions which do plenty on their own but they need to be ran in a logical fashion which improves readability and ensures the desired results. What I like to do for all of my scripts that have more than one function is to create a function call fnMain whose sole purpose is to send input to the individual functions, receive their output, and feed their output to the input of the next function as needed. 

The Solution

The following is the fnMain function that I wrote for the Local Admin Password management solution.  The following function writes a log entry as the script initializes, generates a random password, formats the result to be more human readable, updates Active Directory, and creates log entries if any errors are detected.

#==================================================================================
# Sequentializes Script Actions
#==================================================================================
function fnMain{

    #Log Output
     fnLog -LogPath $LogDir -LogFileName $LogFileName -Data "INFO: Beginning LocalAdminPasswordChange"

    #Generate Random Password
    $Password = fnGeneratePassword -PassLength $PwdLength;if($Password -eq "ERROR"){Return}

    #Format for XAML Password viewer
    $AttribValue = "(Username:$AdminAccount)|(Password:$Password)"

    #Update Local Admin Account If AD Attribute Update Was Successful
    if(fnSecureAttributeUpdate -Attribute $Attribute -NewValue $AttribValue -eq "Success"){
        
        #Updates Local Admin Password
        $sResult = fnSetAdminPassword -AccountName $AdminAccount -Password $Password

        if($sResult -eq "ERROR"){
            #Log Output
            fnLog -LogPath $LogDir -LogFileName $LogFileName -Data "INFO: Errors updating local admin password for $AdminAccount were encountered. No changes were made"
        }
        #Log Output
        fnLog -LogPath $LogDir -LogFileName $LogFileName -Data "INFO: Local admin password for $AdminAccount was updated"
        }
    else{
        #Log Output
        fnLog -LogPath $LogDir -LogFileName $LogFileName -Data "INFO: Errors updating local admin password for $AdminAccount were encountered. No changes were made"
    }
}

Solution Deployment

The complete script is attached. The script is merely a starting point and will probably need to be customized to meet your specific needs. As always, the attached script should be well tested in a lab environment prior to any production use. The envisioned deployment process is:

  • Test / Customize attached script as needed in a lab environment
  • Extend the Active Directory Schema to create a confidential attribute and delegate permissions as described in Part 6
  • Copy the script to the \\domainname\sysvol\domainname\scripts directory
  • Create and link a Group Policy to the OU that was configured in Part 6
  • Configure the Group Policy to run the script as a PowerShell startup script for the computer objects that reside in the OU

Troubleshooting

If the script is unable to update the local admin password for any reason but the script was able to successfully write the password to Active Directory this could lead to a situation where the password in Active Directory does not match the password of the local admin account on the workstation. Since the script runs as a startup script it should always have the rights it needs to update the local admin password but some scenarios where it might fail are:

  • The local admin account is mistyped in the script - The script must have the proper local admin account's name to successfully update the admin account
  • Anti-Virus - If Anti-Virus or some other software prevents the PowerShell executable from running or blocks the password change, the password update process could fail

Still to Come

 The final part in this series will show you how to create a XAML based secure password viewer to retrieve the local admin password. The secure password viewer will display the username and password to authorized users while ensuring the network request that retrieves the username and password is Kerberos encrypted. If you do not wish to use the secure password viewer LDP, ADSI Edit, or Attribute editor can all display the current password. You should be aware however that these connections may not be properly encrypted which could result in the local admin password transiting the network in cleartext as the attributes are retrieved. To mitigate this possibility, ensure you use LDAPS connections or Kerberos encrypted RPC connections.

LocalAdminPasswordChange.txt