DOWNLOAD THE CODE:
Download the Code Listing_01.txt

Download the Code Listing_02.txt

Download the Code Listing_03.txt

The foreach block at callout A in Listing 1 parses the command-line arguments, assigning the user-assigned arguments to corresponding scalar variables. If a username or database filename is missing, the two lines after the foreach block set the $sUsername and $sPasswordDB scalars to the script defaults.

The if block at B executes when the user specifies the f=hostname option in the command line. This option retrieves the account password from the corresponding hostname record in the password database. Inside the if block, the script calls the ReadRecord subroutine, passing it the $sPasswordDB (the filename) and $sFetchPasswordFor (the hostname) scalars.

Let's look at how the script passes these parameters to the ReadRecord subroutine, which Listing 3 shows. The first statement in the ReadRecord subroutine includes the @_ symbol, which is Perl's special subroutine argument array. Perl has no concept of named formal parameters. Instead, Perl passes values to all subroutines via the built-in @_ array. The @_ array's first element, @_[0], contains the first parameter. Its second element, @_[1], contains the second parameter, and so on. Typically, a script copies the contents of the @_ array into locally scoped variables. In the ReadRecord subroutine, the first statement copies $sPasswordDB and $sFetchPasswordFor into the locally scoped variables of $db and $server. (You'll see this type of initialization statement in most of the script's subroutines.)

The ReadRecord subroutine then opens the database for read and uses the grep command (which finds matching elements in a list) to find the record containing $server, initializing @dbrecord with the result. After closing the database, the subroutine uses the split command to extract the current password (the second field of the data record) from @dbrecord. The subroutine then returns the password to $sPassword at B in Listing 1.

The print statement at B signals the end of the if block. The script prints the username and password information on the console of the person executing the script.

The if block at C changes the $sUsername password on one or all hosts based on the use of the c=hostname and c=ALL options. The process begins when the script tests the contents of $sChangePasswordOn. If the scalar contains a value, the script checks the scalar to see whether it contains the string ALL and initializes the @hosts array with the list of hostnames the CreateHostList subroutine creates. (CreateHostList uses Perl's map function to extract the server names from the password database.) If $sChangePasswordOn doesn't contain the string ALL, the block initializes the @hosts array with $sChangePasswordOn, a single hostname.

Before any password changes take place, the script performs a backup of the password database. The script then seeds Perl's rand function, which the script uses to generate random passwords in the Password subroutine.

The foreach loop at D carries out the password changes. The loop begins by assigning the first element of the @hosts array to the $host scalar. ReadRecord retrieves the current password from the password database, and the script stores it in $sOldPassword. Next, the script uses the Password subroutine to generate a new, random, eight-character alphanumeric password and stores it in $sNewPassword. The script uses Perl's time function to obtain the current timestamp and stores it in $t. The script passes the hostname, username, old password, and new password to AdminMisc's UserChangePassword function. If UserChangePassword succeeds (indicated by a return value of 1), $bResult remains TRUE; otherwise $bResult is set to FALSE.

The main body of the script then uses the WriteRecord subroutine to update the password database. On success, WriteRecord updates all the fields (except hostname) of the appropriate server record. In the event UserChangePassword fails, WriteRecord updates only the status field. The script then proceeds to the next host in the @hosts array. After the script exhausts the @hosts list, it falls out of the foreach loop and change block.

The final block at E generates the formatted report as defined by the r option in the command line. This option uses the SortPasswordDB and CreateReport subroutines to sort the database. The CreateReport subroutine uses a format definition to produce the report.

Automate Your Chores
PWManager.pl demonstrates how you can use Perl to automate an important, but time-consuming NT systems administration task. If you perform an NT administration chore that you automate with a script, drop me an email. I'm interested in your solutions; if you can't figure out a solution, I might be able to come up with one.

End of Article

Prev. page     1 2 [3]     next page -->



You must log on before posting a comment.

If you don't have a username & password, please register now.

Reader Comments

I read Bob Wells’ interesting August Scripting Solutions column, “How to Manage Your Enterprise’s Passwords the Easy Way,” about changing the administrator’s password across Windows NT systems in one or more domains. In my situation, most of the NT systems are in a large workgroup, not a domain. Can you tell me how to modify the code to work in that environment?<br> --Rich Lichvar<br><br>

<i>If you have administrator access on the target machines the accounts reside on, the script should work without any changes. Of course, in a workgroup environment, you need to have multiple administrator accounts (one on each workstation, member server, domain) with the same name and password. If you tried the script and it failed, check to see that you have an administrator account on the target system with the same name and password as the account you’re running the script under.<br> --Bob Wells</i>

Rich Lichvar

Some customers have asked me questions about the script in “How to Manage Your Enterprise’s Passwords the Easy Way” (August), Bob Wells’ article about managing remote accounts via Perl. My customers were confused about the effects of changing the passwords of accounts that they run various services under (e.g., MTS, SQL Server, IIS). They were thinking (hoping) that if they changed the password for an account, they would not have to bounce the service. I hated to tell them they would have to bounce the service after they change the account password.<br> --Jim Carroll<br><br>

<i>Thanks for the feedback. As you point out, I didn’t design the password-manager script to manage service-related accounts. That is, the script doesn’t handle updating the Service Control Manager (SCM). Thus, if a service account password changes, the user will have to update the applicable service in Control Panel’s Services applet and restart the service. Thanks for reading, and keep your eyes peeled for a Service Account Password Manager script in the near future.<br> --Bob Wells</i>

Jim Carroll

 
 

ADS BY GOOGLE