Running Process As A Different User On Windows

As part of a build pipeline I’m working on the octopus deploy process needs to talk to the database using roundhouse as a different user from the one running the deployment. This is done because the database uses integrated AD authentication, which I quite like. If this build were running on Linux then it would be as simple as editing the sudoers file and calling the command using sudo. Unfortunatly this is Windows and the command line has long been a secondary concern.

I started by asking on the western devs slack channel to see if anybody else had done this and how. Dave Paquette suggested using psexec. This is a tool designed for running commands on a remote computer but if you leave the computer name off it will run on the local machine. This sounded perfect.

However I had a great deal of trouble getting psexec to work in the way I wanted. The command I wanted to run seemed to fail all the time giving an confusing error code -1073741502. The fix provided didn’t seem to work for me so after an afternoon of bashing my head against psexec I went looking for another solution. Running remote processes gave me an idea: what about powershell remoting?

Some investigation suggested that the command I wanted to run would look like

Invoke-command localhost -scriptblock { rh.exe --some-parameters }

This would remote to localhost and run the roundhouse command as the current user. To get it to work using a different user then the command needed credentials passed into it. I had the credentials stored as sensitive variables in Octopus which set them up as variables in powershell. To turn these into credentials you need to do

$pwd = ConvertTo-SecureString $deployPassword -asplaintext -force
$cred =new-object -TypeName System.Management.Automation.PSCredential -argumentlist $deployUser,$pwd

Now these can be passed into invoke command as

Invoke-command localhost -authentication credssp -Credential $cred -scriptblock { rh.exe --some-parameters }

You might notice that authentication flag, this tells powershell the sort of authentication and cor credssp you also need to enable Credential Security Service Provider. To do this we run

Enable-WSManCredSSP -Role server
Enable-WSManCredSSP -Role client -DelegateComputer "*"

From an admin powershell session on the machine. Normall you would run these on different machines but we’re remoting to local host so it is both the client and the server.

Finally I needed to pass some parameters to roundhouse proper.

Invoke-command localhost -authentication credssp -Credential $cred -scriptblock { param($roundHouseExe,$databaseServer,$targetDb,$databaseEnvironment,$fName) & "$roundHouseExe" --s=$databaseServer --d="${targetDb}"  --f=$fName /ni --drop } -argumentlist $roundHouseExe,$databaseServer,$targetDb,$databaseEnvironment,$fName