change ad account password without ad module

Kind of stuck, looking for fresh ideas.
We have an admin account for monitoring on a number of different client domains.
The creds are the same everywhere and we would like to change them every few months or on demand, and update the service creds related to this account.
I am ignoring encryption until I can prove that this will work, conceptually.

My script so far is below, not sure how to execute the change of this password given the following conditions:

  • The script will be executed by a 3rd-party mgmt platform using an agent service already running at each client site. …we can feed cmd args into the exe line. ie:
    > & .\myscript.ps1 -username abcadmin -newpass new123 -oldpass old789
    …the script is copied to a local temp folder on that server(s) and executed locally by the system.

  • The server running the agent service does not have the AD module available, and its policy is not configured to execute scripts or enable WinRM. …I can run another script to set-exe to remotesigned an hour before and switch it back after the timeout period.

  • Assume PS v 2.0, lowest common denom

  • Account executing the script is also the account we are changing the creds on.

  • [Option] I can also push the script file to the server prior to running
    …and call it from a BAT file (and bypass exe policy).

param([string]$Username,[string]$NewPass,[string]$OldPass)

$FQUserName = $env:USERDOMAIN + '\' + $Username
$OldCreds = New-Object System.Management.Automation.PSCredential -ArgumentList $FQUserName, $OldPass
$NewCreds = New-Object System.Management.Automation.PSCredential -ArgumentList $FQUserName, $NewPass

# change the AD account password here #

I looked into the dsquery, but got some weird error about the invoke method and 2 parameters. Even stumped our resident scripting expert. Any insights?

Can you not just use ADSI? Like we’d have done in VBScript?

We were trying this yesterday and were getting similar errors with the invoke method. However today with fresh eyes we saw a couple mistakes and got it working.

$UserName = 'testldap'
$NewPass = 'NewPass123$'

$UserDN = (dsquery user -samid $UserName).Replace('"', '')

$ADSI = [ADSI]"LDAP://$UserDN"
$ADSI.PSBase.Invoke("SetPassword", $NewPass)
$ADSI.PSBase.CommitChanges()

I think this’ll work I just have to try it… a lot on my plate today so I will get back. Thanks!

Another option would be to go old school and use NET USER

NET USER $UserName $NewPass /DOMAIN

Sorry for the delay, just haven’t had a chance to re-visit this project in a bit.

I have one requirement for this where it has to be able to run on a non-DC with no AD installed. I’m thinking about opening up a session into a DC to run the query. I can use psexec to remotely enable psremoting and scripting, then revert those settings when I’m done. So I will need to do:

  • Find the DC hostname
  • Check for psexec, download if not found.
  • open remote access
  • enter remote session or invoke command

…or is it possible some other way, to get the dsquery command. perhaps add the AD role on the fly. What would be most efficient?

You can user the ADSI directory searcher to find your user account DN rather than using DSQuery.

easy way is to use WinNT provider

$ad = [adsi]'WinNT://domain/username' $ad.SetPassword('Password')

Thank you Max!!!