How do I run a powershell script from another script passing credentials? - powershell

I am currently running a powershell script that displays a message asking which script do you want to run. 1-5?
Once the user selects this it imports credentials using Import-Credential on a clixml file and runs something like:
Invoke-Command -ComputerName $Server -Credential $Cred -ScriptBlock {& C:\Temp\script.ps1}
The script then launches on the server but has no permission to read / copy / move files. I assumed because I ran with the credentials specified it would be able to perform the actions needed.
Troubleshooting
If the credentials specified were wrong then it wouldn't launch the script on the server at all.
I've tried running the script on the server and it works perfectly.
I can't see a way to pass credentials on the
{& C:\Temp\script.ps1} or I would create another set of credentials on the server and use that.
Any help would be appreciated.

Related

Powershell: Remotely Unzip from file-share using invoke-command

I am trying to unzip a file remotely. The file-share the ZIP is on uses a different credential
This is the command I ran.
Invoke-Command -Computername $compname -ScriptBlock
{
Expand-Archive -Path "\\share\somefolder\myfile.zip" -DestinationPath "\\share\somefolder"
}
I get an error stating username/password incorrect for accessing the share.
The problem is, the account I use to access $compname is not the same account I use to access the share the zip is on. I don't have a common account that can access both.
Incidentally, running the expand-archive by taking RDP to $compname works because it uses the saved credentials from the credential manager. Invoke-command on the other hand seems to be trying to access the share with the credentials used to connect to the remote computer.
Things I have tried
Mapping a network drive beforehand, but that doesn't get
recognised as a valid path when accessed via invoke-command.
Mapping a network drive on the fly inside the invoke-command
option, and then using that mapped drive with expand-archive. This
showed the most promise as I could get it working via
enter-pssession, but of course this won't work in a script am trying to automate and when
I created a new session via new-pssession and passing that to
invoke-command, it again failed to work.
Does anyone have suggestions on a possible approach? I might revisit option #2 to see if I have made a mistake somewhere.

Running a PowerShell script remotely

So I have a script sitting on a server that I can remote into using Enter-PSSession and run the script from my local environment just fine. What I do is...
Enter-PSSession hostname
cd c:\temp\myscript.ps1
or
$s = New-PSSession -ComputerName hostname
Invoke-Command -Session $s -ScriptBlock {C:\temp\myscript.ps1}
these run the script just fine. The problem I am having is the data is supposed to get sent to a database. If I run the .ps1 on the hostname by RDPing directly into it, it works. If I RDP into the server and go back to my local environment where I Enter-PSSession using the code above, it submits to the database just fine. But when I close out of the RDP session and just try running the script again locally, it doesn't go to the database.
Maybe it is something stupid I am missing but any help would be greatly appreciated.
The important bits are in the myscripts.ps1, so it's impossible to say from what you have provided.
I suggest you check that script file for where the credentials are stored. When you run it locally, I assume you run it from that working directory.
Try using $psexecscript as the root of the config file's path. That's whatever path the script is in, assuming the credentials are in the same or sub- directory.
Is it possible that the user lacks permission to write in your DB or the credentials to write in that DB are not provided in the script?
If after verifying the credential issue, it still doesn't work, you might want to register your script as a task. You can set it as a manual task. Then, whenever you need it, you (remotely) run that task. In that way your credentials are stored as well and you can safely use the 'run as' feature.

Script location of a remotely executed script?

How can I get a remotely executed script to know it's own location? I'm using Invoke-Command to run a script on a remote server. The script needs to create files in the directory in which it lives. Running with relative addressing doesn't work (i.e. .\output.log), the scripts generally end up in my user profile on the remote server. I tried all the methods outlined in this question but none of them seem to work when the script is remote.
Update: Provided script invocation code per request
$server='ad1hfdahp802'
$remotepath='\\ad1hfdahp802\d$\AHP\pi_exceed_presentation\pi_exceed_presentation_deploy.ps1'
$SDFEnvironment='INT'
Invoke-Command -ComputerName $server -FilePath $remotepath -ArgumentList($SDFEnvironment,$remotepath)
The remote script takes the $remotepath and turns it into a file system path.
Using -FilePath with Invoke-Command means that you read the script locally and send the content as the scriptblock to the remote computer. $PSScriptRoot only works when the script is executed directly on the target. You could try using:
Invoke-Command - ComputerName "computer1" -Scriptblock { & '\\server\path\to\script.ps1' } -Authentication Credssp
Be aware that you need CredSSP to make this work since the remote computer can't use your credentials to access network-resources without it. As an alternative, you could use psexec (or start a process remotely). Ex.
psexec \\computer1 powershell -noprofile -file \\server\path\to\script.ps1
After trying some of the changes proposed I've come to understand that the Invoke-Command isn't actually running the remote script at its original location, but rather loading it from the original location and then running it under the context of PowerShell as the user running the local script. The "script directory" is actually a directory in the user's workspace regardless of where the script originally lived.
This clarifies things for me somewhat. While there may be ways to divine where the script originally came from or to actually start a session on the remote server then run the script as a "local" script there, the need for the remote script to further access other servers, creating multiple hops in authentication, means I have to add CredSSP to the mix.
It seems my original plan, to pass the path I'm using to locate the script to the script so it can place output files in the original directory, is probably the best approach given that I also have to add CredSSP to the mix.
I'm open to refutation, but I don't think any of the proposed solutions actually improve the functionality of the remote script so I'm going to stick with what I started with for now. Thanks to everyone for their contributions.
Enter a session on the remote server, and call the script from there.
local PS> Enter-PSSession -ComputerName $server ...
remote PS> powershell d:\AHP\...\script.ps1
remote PS> exit
local PS>
Then you can use $PSScriptRoot in the script in the remote server to get the local path of the directory of the script on the remote server.
EDIT:
To locate the script on the remote server, you can use your knowledge of the network path of the script file, and parse the output of net share to map network path to local path on the remote server.
remote PS> net share | where { $_.StartsWith('D$ ') } | foreach { [regex]::Split($_, " +")[1]}

Execute remote quiet MSI installs from Powershell

I am trying to use the Invoke-Command powershell cmdlet to install a MSI installer. From within powershell on the local machine and from the proper directory, the following works:
./setup /quiet
The following does not seem to work:
$script =
{
param($path)
cd "$path"
& ./setup /quiet
return pwd
}
return Invoke-Command -ComputerName $product.IPs -ScriptBlock $script -Args $sourcePath
For test purposes I am working on the local machine passing in "." for the -ComputerName argument. The paths have been verified correct before passing in to Invoke-Command, and errors generated on different versions of this code indicate the paths are correct. I have also tried with and without the "& " on the remote call to setup. Other Invoke-Command calls are working, so I doubt it is a permissions issue. I have verified that the return from the pwd call is the expected directory.
How do I get the install to work?
What error (if any) are you receiving? Unfortunately, you must run the shell as admin on your local machine to be able to connect to your local machine with invoke-command or any WINRM based command that requires administrative privilege (this is not a requirement when connecting remotely).
When connecting to loopback, I believe it is unable (for some security reason) to enumerate groups and determine if you are in an admin enabled AD or local group, which is how it auto elevates when invoking on a remote machine. The only solution may be to have a conditional which checks for localhost and if so, don't use the -ComputerName parameter.
This GitHub Issue covers it
You might try using Start-Process in your script block:
cd $path
start-process setup.exe -arg "/quiet"
Not sure if you will want or need to wait. Look at help for Start-Process.
I have had weird issues when trying to remotely execute a script on a local machine. In other words, remote powershell to the local machine. It comes back with an error that seems to say that PowerShell remoting is not enabled on the machine, but it was. I can run the script remotely from another machine to the target, but when using remoting to the same box, the issue crops up.
Verify that the WinRM service is running.
Verify powershell remoting has been enabled as in Enable-PSRemoting -force.
Verify your powershell execution policy is loose enough as in Set-ExecutionPolicy Unrestricted, for example. If the policy was set to RemoteSigned, this might be the problem.
You might also want to verify the user you are running the script as (locally, but using remoting) has privileges to "log on as a service" or as a batch job. Just guessing there, if the above list doesn't solve anything.

Powershell, remote script access denied to network resources

I am trying to execute powershell script remotely using invoke-command. The script relies on a configuration file which is available over the local network. The script is called in a following way:
Invoke-Command -ComputerName 192.168.137.181 -FilePath c:\scripts\script.ps1 -ArgumentList \\192.168.137.1\share\config.xml
The configuration as you can see is an xml file and it's loaded using:
$xml = New-Object XML
$xml.Load(args[0])
When the script is called locally on the machine then it runs witout any problems and reads the configuration file. However when I run it from different machine using invoke command I get
"Access to the path '\\192.168.137.1\share\config.xml' is denied"
exception, which is thrown when executing Load method.
The file is accessible to everyone with read and write permissions.
Both, machine on which the scrip should be run (.181) and the machine on which it is run physically have the same credentials, thus I do not pass them in invoke-command cmdlet.
The share machine (.1) has different credential, but this was never an issue when calling the script locally from .181.
Can you please point me in the right direction? I stuck on this step and can't find solution by myself. I tried downloading the xml string using WebClient#DownloadString method and passing credentials for the share machine but it did not help.
Thanks in advance
It is probably a double hop issue. You have to use CredSSP to delegate your credentials to the remote computer.
Try the solution mentioned here: http://blogs.msdn.com/b/clustering/archive/2009/06/25/9803001.aspx