Solved

How to run Powershell script on all Servers in domain?

Posted on 2011-02-23
28
873 Views
Last Modified: 2012-06-27
Experts,

        I have an existing script that resets a users password. I would like to attach to all of the servers in our domain and run this script from the PDC. How would I accomplish this task? I have made a few attempts but the logic was incorrect.
I think I need to have something like $servers = Get-Content c:\servers.txt. Also the part that I do not know how\where to code the credentials to access each server. The passwords must be encrypted.  When I tested the script by adding a test $servers = Get-Content c:\servers.txt the password was changed on the PDC and not the server I wanted to be connected to.

Please advise, Missymadi
# Ask for a username

$Username = Read-Host "Enter UserName"

# Search for the user(s)

$Users = Get-QADUser -SamAccountName $Username | Select-Object Name, DN, 
  PasswordLastSet, PasswordAge,PasswordExpires, PasswordNeverExpires, 
  UserMustChangePassword, PasswordIsExpired, PasswordStatus

# Display the user(s)

$Users

If ($Users) {

  # Ask if they wish to proceed

  $Response = Read-Host "Do you want to reset the user's password?`n[1] Yes, [2] No"

  If ($Response -eq "1") {

    # Ask for password 

    $SecurePassword1 = Read-Host "Please enter a password to use" -AsSecureString
    $SecurePassword2 = Read-Host "Please re-enter the password to confirm" -AsSecureString

    $Password1 = [Runtime.InteropServices.Marshal]::PtrToStringAuto(
      [Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword1))
    $Password2 = [Runtime.InteropServices.Marshal]::PtrToStringAuto(
      [Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword2))

    If ($Password1 -ne $Password2) {

      Write-Host "Passwords do not match. Aborting script." -ForegroundColor Red

    } Else {

      # Perform work

      # For each user we found earlier, set the password. Log a few things and the name of the 
      # user running this script 

      $Users | ForEach-Object { 
        Set-QADUser $_.DN -UserPassword $Password1
        Write-Host "Password reset for $($_.Name)"
      } | Select-Object SamAccountName, PasswordLastSet, @{n='SetBy';e={ $Env:Username }} |
        Out-File c:\PwdChanged.txt -Append
    }
  }
} Else {

  Write-Host "No users found" -ForegroundColor Red

}

Open in new window

0
Comment
Question by:missymadi
  • 13
  • 13
28 Comments
 
LVL 27

Expert Comment

by:KenMcF
ID: 34964468
Are you trying to reset the local user passwords on all your Servers?
0
 

Author Comment

by:missymadi
ID: 34964553
Yes.

I will need to reset local Admin and local users on each server.

I did find a script that changed Admin's password on each server and the concept is what I'm looking for as far as connecting to each Server and changing the passwords BUT I want to use my script above that allows the users(maintainer) control over the script.
The script I found that changes only local admin password on domain servers is attached.  I found out on the net.
$servers = Get-Content c:\servers.txt
$old_credential = $host.ui.PromptForCredential("Please enter OLD credentials", "Please enter OLD user name/password e.g. local\netserv", "", " NetBiosUserName")
$new_credential = $host.ui.PromptForCredential("Please enter NEW credentials", "Please enter NEW user name/password e.g. local\netserv", "", " NetBiosUserName")
$new_password = $new_credential.GetNetworkCredential()
$npu = $new_password.username
$npp = $new_password.password

foreach($server in $servers) {
    Try {
        Get-WmiObject win32_BIOS -Computername $server -Credential $old_credential -ErrorAction stop | Out-Null
        "Recognized password for $($old_credential.username) in computer $server"
        "Changing password for $($new_credential.username) in computer $server"
        $admin=[adsi]("WinNT://$server/$npu, user")
        $admin.psbase.invoke("SetPassword", $npp)
    }
    Catch {
        "NOT changing password for $($old_credential.username) in computer $server"
    }
}

Open in new window

0
 
LVL 27

Expert Comment

by:KenMcF
ID: 34964619
ok, if you are looking to change local user name you can not use the quest cmdlets.  The script will need to use the below syntax instead of using get-qaduser and set-qaduser, these are only used for domain accounts. I will look through your script and see what all needs updated.


$admin=[adsi]("WinNT://$Server/$User, user")
$admin.psbase.invoke("SetPassword", $Password1)
0
 

Author Comment

by:missymadi
ID: 34964698
Thank you! You guys are great!
0
 
LVL 27

Expert Comment

by:KenMcF
ID: 34964702
Is it only the local administrator account you need to reset on each computer?

If it is then I do not understand why you need an input of the username. If it is not the lcoal administrator account then why do you need to use so many local user accounts on your servers and not domain accounts?
0
 

Author Comment

by:missymadi
ID: 34964819
Local administrator and local user accounts.
Our setup is as follows:
no central user database, all users are maintained on each machine.
0
 
LVL 27

Expert Comment

by:KenMcF
ID: 34964846
Are these all stand-alone server or are they in a AD domain? I would assume a domain since you said you want to run from a DC
0
 

Author Comment

by:missymadi
ID: 34964867
AD domain. The user accounts are maintained by the AD.
0
 
LVL 27

Expert Comment

by:KenMcF
ID: 34964904
ok, now I am really confused. Are these local account to each server or are they user account in AD that the password needs changed? If these are local accounts to each server then we will have to use what I posted before. If these are domain accounts we can use the Quest cmdlets and do not have to loop through a list of servers to change.
0
 

Author Comment

by:missymadi
ID: 34965037
Sorry - our setup is quite different than most. But you actually helped me ..... I will need two scripts.
One using the cmdlets and one using the one you posted above. We have two separate LAN's one that has no central db so accounts are maintained on each machine. The other LAN is maintained by AD. One the one that has AD is very time sensitive and any discrepancies between Server/client will result in a user not being able to log in.

0
 
LVL 27

Expert Comment

by:KenMcF
ID: 34965125
ok, let me look through the scripts and see what needs changed. For the servers that have local accounts, are these servers on the domain or are they stand alone?
0
 

Author Comment

by:missymadi
ID: 34965205
They are stand alone.
0
 
LVL 27

Expert Comment

by:KenMcF
ID: 34965228
resetting those may be a little difficult becuase you will need to specify a username and password to connect. So you will need to either prompt for a username and password or hard code one in the script. So you may want to have an account on each server for this so they are all the same username and password.
0
Free Gift Card with Acronis Backup Purchase!

Backup any data in any location: local and remote systems, physical and virtual servers, private and public clouds, Macs and PCs, tablets and mobile devices, & more! For limited time only, buy any Acronis backup products and get a FREE Amazon/Best Buy gift card worth up to $200!

 

Author Comment

by:missymadi
ID: 34965335
Could we prompt the user(maintainer) for the server connecion credentials? And could this be encrypted?
0
 

Author Comment

by:missymadi
ID: 34972524
The script must be ONE script that resides on the PDC and can reset passwords on a domain and stand alone machines.
Our network is as follows:
One LAN consists of all users maintained on each machine (no central db) the OS is Linux, Linux thin client and monta vista. The other LAN consists of AD and VM's all Windows, VMware(esx) There is one firewall and switches.

Is it possible to create one script and access each machine from PDC? I imagine the script calling other scripts to create a connection to open sockets.

Please advise.
Missymadi
0
 
LVL 27

Expert Comment

by:KenMcF
ID: 34972563
That makes it even more complicated. I assumed since you started out with using powershell and the quest cmdlets these were windows based computers. I am not very familiar with linux so I do not know how much help I can be. Can you give me an example of how you reset the passwords now on those computers? Do you do it remotly now for a single computer?
0
 

Author Comment

by:missymadi
ID: 34972768
I can definitely use the Powershell script for the Windows machines and it's doing exactly what the requirements call for. So I will keep this one and use for the Windows machines.  

Right now we log into each machine separately. It is a strange mix of machines and we are looking for one script to reach all the servers and reset the password by prompting the user for server credentials then running the script to change username and password.
I posted this before and now I'm understanding this a little more, it will contact the machine from a list of hosts and make a connection through appropriate protocol to a waiting open socket then run the script that resides on that machine to reset the password. Does that make sense? Can you help me get there?  Here is an example I found below. This is just an example but I think this is what I need?

Thanks! Missymadi

#! /usr/bin/ksh
# Change_Password --- change the user's password on a list of hosts
#
#  You will need to adjust HOSTLIST.  You may need to adjust DELAY
#  and all of section 2.
#


#
#  Section 0 --- Set stuff up

HOSTLIST="test1 test2"
DELAY=3
stty -echo
print -n Enter Old Password-
read OLDPASS
print 
print -n Enter New Password-
read NEWPASS
print
stty echo
USER=$(whoami)
exec 4>&1


#
#  Section 1 --- Prove that we can talk with the hosts in HOSTLIST
#     Part 1 --- telnet to each and touch a file

for HOST in $HOSTLIST ; do
	telnet $HOST >&4 2>&4 |&
	sleep $DELAY
	print -p $USER
	sleep $DELAY
	print -p $OLDPASS
	sleep $DELAY
	print -p touch changepassdatafile.$HOST
	sleep $DELAY
	print -p exit
	wait
done

#
#  Section 1 --- Prove that we can talk with the hosts in HOSTLIST
#     Part 2 --- Retrieve the files via ftp

ftp -nv >&4 2>&4 |&
for HOST in $HOSTLIST ; do
	print -p open $HOST
	print -p user $USER $OLDPASS
	print -p get changepassdatafile.${HOST}
	print -p close
done
print -p bye
wait

#
#  Section 1 --- Prove that we can talk with the hosts in HOSTLIST
#     Part 3 --- Inspect the retrieved files

errors=0
for HOST in $HOSTLIST ; do
	if [[ -f changepassdatafile.${HOST} ]] ; then
		echo $HOST was ok
		rm changepassdatafile.${HOST}
	else
		echo $HOST has a problem
		((errors=errors+1))
	fi
done
((errors)) && exit 1

#
#  Section 2 --- Change the passwords

for HOST in $HOSTLIST ; do
    telnet $HOST >&4 2>&4 |&
    sleep $DELAY
    print -p $USER
    sleep $DELAY
    print -p $OLDPASS
    sleep $DELAY
    print -p passwd
    sleep $DELAY
    print -p $OLDPASS
    sleep $DELAY
    print -p $NEWPASS
    sleep $DELAY
    print -p $NEWPASS
    sleep $DELAY
    print -p exit
    wait
done

#
#  Section 3 --- Verify that the passwords were changed
#     Part 1 --- Retrieve those files via ftp again

ftp -nv >&4 2>&4 |&
for HOST in $HOSTLIST ; do
    print -p open $HOST
    print -p user $USER $NEWPASS
    print -p get changepassdatafile.${HOST}
    print -p delete changepassdatafile.${HOST}
    print -p close
done
print -p bye
wait

#
#  Section 3 --- Verify that the passwords were changed
#     Part 2 --- Inspect the retrieved files

errors=0
for HOST in $HOSTLIST ; do
    if [[ -f changepassdatafile.${HOST} ]] ; then
        rm changepassdatafile.${HOST}
    else
        echo $HOST has a problem!
        ((errors=errors+1))
    fi
done
((errors)) && exit 1


exit 0

Open in new window

0
 

Author Comment

by:missymadi
ID: 34972792
But the hostlist script would run from windows not linux(in example)
0
 
LVL 27

Expert Comment

by:KenMcF
ID: 34972852
That is a Linux shell script, I do not know enough about Linux and do not have anyway to test. You may need something like cygwin installed on your windows computer to run this. You will probably be better off to close this question and post a new one in a Linux Zone, they would be able to help you better than I can and a lot faster.

http://www.cygwin.com/
0
 

Author Comment

by:missymadi
ID: 34972919
Could you still help me with the original question? I would need the two scripts - one for stand alone and one for AD to change the passwords. I will use these locally.

I do need the host list of servers script  , to be in Windows format because it needs to run on our Win2K3 (PDC) server. I'll post another question for this one.

Thanks for your help!
Missymadi
0
 
LVL 27

Expert Comment

by:KenMcF
ID: 34973089
Yes I can help with that. These are the servers that are all in the domain correct? If that is the case we do not need to run against a list of servers, we can just change the password on the DC.
0
 

Author Comment

by:missymadi
ID: 34973198
Yes they are in the domain. If it's not too much could  you provide the one that goes through a list of servers? Just curious to see how I would connect to a server not on a domain and run a script against it.

Thanks so much!
0
 
LVL 27

Expert Comment

by:KenMcF
ID: 34973217
Yes, I will test this out tonight and post back.
0
 
LVL 27

Expert Comment

by:KenMcF
ID: 34993747
missymadi

The script you posted will change a domain users password. Here is one that will loop through a list a servers and change a local users password.


# Ask for a username  
  
$Username = Read-Host "Enter UserName"  
$Servers = get-content C:\Servers.txt



$Servers | %{



    # Ask for password   
  
    $SecurePassword1 = Read-Host "Please enter a password to use" -AsSecureString  
    $SecurePassword2 = Read-Host "Please re-enter the password to confirm" -AsSecureString  
  
    $Password1 = [Runtime.InteropServices.Marshal]::PtrToStringAuto(  
      [Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword1))  
    $Password2 = [Runtime.InteropServices.Marshal]::PtrToStringAuto(  
      [Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword2))  
  
    If ($Password1 -ne $Password2) {  
  
      Write-Host "Passwords do not match. Aborting script." -ForegroundColor Red  
  
    } Else {  

$admin = [adsi]("WinNT://$($_)/$($UserName), user")
Try{
$admin.SetPassword($Password1)
"The password for $($Username) was changed on $($_)"}
Catch{
"Failed to change password for $($Username) on $($_)"}  
}

Open in new window

0
 

Author Comment

by:missymadi
ID: 34998335
Thanks for the response. Exactly what I needed except could we change instead of having a servers.txt, could we prompt the user for a computer?

Thanks! Missymadi
0
 
LVL 27

Accepted Solution

by:
KenMcF earned 500 total points
ID: 34998446
Yeah, this should prompt the user for the server name as well.

# Ask for a username    
    
$Username = Read-Host "Enter UserName"    
$Server = Read-Host "Enter Server Name"    

   
    # Ask for password     
    
    $SecurePassword1 = Read-Host "Please enter a password to use" -AsSecureString    
    $SecurePassword2 = Read-Host "Please re-enter the password to confirm" -AsSecureString    
    
    $Password1 = [Runtime.InteropServices.Marshal]::PtrToStringAuto(    
      [Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword1))    
    $Password2 = [Runtime.InteropServices.Marshal]::PtrToStringAuto(    
      [Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword2))    
    
    If ($Password1 -ne $Password2) {    
    
      Write-Host "Passwords do not match. Aborting script." -ForegroundColor Red    
    
    } Else {    
  
$admin = [adsi]("WinNT://$($Server)/$($UserName), user")  
Try{  
$admin.SetPassword($Password1)  
"The password for $($Username) was changed on $($Server)"}  
Catch{  
"Failed to change password for $($Username) on $($Server)"}

Open in new window

0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Active Directory replication delay is the cause to many problems.  Here is a super easy script to force Active Directory replication to all sites with by using an elevated PowerShell command prompt, and a tool to verify your changes.
Synchronize a new Active Directory domain with an existing Office 365 tenant
This tutorial will walk an individual through the process of transferring the five major, necessary Active Directory Roles, commonly referred to as the FSMO roles from a Windows Server 2008 domain controller to a Windows Server 2012 domain controlle…
This tutorial will walk an individual through the process of configuring their Windows Server 2012 domain controller to synchronize its time with a trusted, external resource. Use Google, Bing, or other preferred search engine to locate trusted NTP …

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now