wrieedx
wrieedx

Reputation: 252

Run code block locally as a different user in powershell script

This is something incredibly simple, but I just can't get anything to work. I want to run a block code in a powershell script under a specific user. The keyword is locally and I'm using powershell 2.0.

Invoke-Command seems to require a remote host? I run the following and the error message that I see seems to suggest as much:

$strScriptUser = "DOMAIN\USER"
$strPass = "PASSWERD"
$PSS = ConvertTo-SecureString $strPass -AsPlainText -Force
$cred = new-object system.management.automation.PSCredential $strScriptUser,$PSS
Invoke-Command -ComputerName "." -scriptblock {
write-output "HI!"
} -Credential $cred

Start-Job with -ScriptBlock isn't supported with powershell 2.0? I run the following and the error message that I see seems to suggest as much:

$strScriptUser = "DOMAIN\USER"
$strPass = "PASSWERD"
$PSS = ConvertTo-SecureString $strPass -AsPlainText -Force
$cred = new-object system.management.automation.PSCredential $strScriptUser,$PSS
Start-Job -ScriptBlock {
write-output "HI!"
} -Credential $cred

Am I doing something wrong, or is there an alternative way?

Added: Here is what I'm trying to do in the first place. I'm making a scheduled task that runs when a user logs into/unlocks a terminal that writes logon information to a file. The scheduled task runs as the local user in order to get at the username, profile, etc. information. The logon information is then written to a log file using a different user account, which is the only account that can modify the file. To deter access to the logon credentials in the script I convert the script to an EXE using PS2EXE.

Upvotes: 13

Views: 61472

Answers (3)

olegk
olegk

Reputation: 787

Another approach is impersonation, it is good option if you are not willing to enable remoting.

Check this and this out.

You should just put your code between

Push-ImpersonationContext $credential

and

Pop-ImpersonationContext

Upvotes: 4

Nathan Hartley
Nathan Hartley

Reputation: 4175

Here is another way.

# Get the other user's credentials
$credential = Get-Credential

# Execute a scriptblock as another user
$commands = @'
    $env:username
    # ... more commands ...
'@
Start-Process -FilePath Powershell -LoadUserProfile -Credential $credential -ArgumentList '-Command', $commands

# Execute a file as another user 
$script = '.\path\name.ps1'
Start-Process -FilePath Powershell -LoadUserProfile -Credential $credential -ArgumentList '-File', $script

With the -LoadUserProfile switch, this has the added benefit of creating the user's profile if it does not already exist.

Upvotes: 9

briantist
briantist

Reputation: 47842

It would help to see the error messages you're not showing us, but I think the answer to your question is to use PowerShell Remoting as you tried with Invoke-Command. The computer name . is fine as is localhost but you do have to have remoting enabled on your machine to do it.

To enable remoting, run Enable-PSRemoting within powershell, or run winrm quickconfig in a regular command prompt.

If you already have remoting enabled, then you might be trying to do the remoting with a non-administrative user. If that's the case, take a look at the output of Get-PSSessionConfiguration. You'll get a list of endpoints and the permissions that are applied.

The endpoint you're connecting to by default is called Microsoft.Powershell and you could change the permissions with Set-PSSessionConfiguration (be sure to use the -ShowSecurityDescriptorUI parameter unless you want to mess with SDDL).

But instead of doing that, there should already be a group given access called BUILTIN\Remote Management Users which you can add your limited user to.

If none of this helps, give more details and error messages.

Edit

After seeing the explanation of what you're ultimately trying to accomplish, I have another suggestion for you.

  1. Your existing scheduled task writes the information to a known location.
  2. A different scheduled task running under the privileged user account picks up that information and puts it into the file that the limited user cannot access.
  3. Bonus: start the second task from the first task.

This could be a quick compromise to do what you want without remoting and without exposing the credentials of the privileged user.

Issues with the current approach:

The major problem I have with your original idea is that you're going to need to embed the credentials into the script, so the limited user will have access to the credentials of the account that can modify the file anyway.

Ideally:

You would have a web service that you could invoke with your limited-user powershell script in which you can only give it the login information and not get anything back. So you'd hit a URL and do a POST or whatever with the data that you want to log, but that user can't ever retrieve any info. It might be a bit beyond what you're willing to do for this.

Upvotes: 1

Related Questions