Running PowerShell script locally from remote location - powershell

I am having an issue that I can't resolve. I am trying to run a script locally on a server, the script exists on a remote server. It is a script that I created that makes a series of domain credentials from a file with secure strings and a key file.
The script works fine locally if the ps1 file itself is on the system where I am running it. I am unable to run the script locally if the ps1 file is on the other machine.
Here is the script that I am trying to run... (this ps1 file is on "server1")
$creds = Import-Csv "\\server1\D$\Credentials\creds.csv"
$key = Get-Content "\\server1\D$\Resources\AES.key"
foreach ($cred in $creds) {
$user = $cred.User
$password = $cred.Hash | ConvertTo-SecureString -Key $key
#$password = "" | ConvertTo-SecureString -AsPlainText -Force
$i = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $user,$password
New-Variable -Name ($cred.Domain + "_Cred") -Value $i -Force -Verbose
}
I am trying to run it from server2 using the following command...
& '\\server1\D$\Credentials\BuildCreds.ps1'
Any thoughts? Is this a scope issue, or the fact that I am loading the files with UNC? I've tried everything that I can think of.

It seems like this issue only exists in PowerShell ISE. I ran the code in PowerShell and everything worked correctly.
I am not quite sure why it is like that.

Related

JiraPS printing linebreaks instead of results

I have a problem when using the JiraPS Module in a script.
When executing the script below I receive a line-break instead of an actual result. The weird thing is, when executing the script twice, once without the Get-JiraProject -Project 'exampleBoard' at the bottom and once with only the Get-JiraProject -Project 'exampleBoard' everything works fine and I get the correct output. When using Get-JiraProject in the script which outputs all projects with read-access I get a line-break for every project.
param ($jirauser)
$ServerURi = 'https://company.atlassian.net'
if (!(
(Get-Module BetterCredentials -ListAvailable) -and
(Get-Module JiraPS -ListAvailable)
)) {
$Force = $True
}
if ($Force) {
# Force the installation of the latest version of the modules
Install-Module -Name BetterCredentials -Scope CurrentUser -AllowClobber -Force
Install-Module -Name JiraPS -Scope CurrentUser -Force
}
# Set Jira server and create session
Import-Module JiraPS -Force
Set-JiraConfigServer $ServerURi
# Get credentials with "BetterCredentials" and store them if they are new
Import-Module BetterCredentials -Force
$cred = Get-Credential -UserName $jirauser -Store
#Session Creation
Write-Output "Creating a session"
$session = New-JiraSession -Credential $cred
if ($session) {
Write-Output $session
}
Get-JiraProject -Project 'exampleBoard'
The output looks as follows:
The value of jirauser is: example#company.com
Creating a session
Username WebSession
-------- ----------
example#company.com Microsoft.PowerShell.Commands.WebRequestSession
I tried the following already:
Running the script inside WSL and PWSH to work around Execution Policies
Using / not using BetterCredentials
Split the code in two (as described above) and ran it twice
Writing the output of Get-JiraProject into a variable and printing the variable instead
Using New-Object System.Management.Automation.PSCredential to create the credentials manually
Sleep for a few seconds after authenticating

Powershell Get-FTPItem -Path * ... is not working

I am working on a fairly small script that aims to download all files from a FTP folder. The script is a powershell script and uses the PSFTP module.
So for test purposes I created 3 randoms files in the ftp folder called "a", "b" and "c".
The script works like this
Creating PSCredentials
Creating a FTP connection
Connecting to session
Downloading all files from the root ftp folder
So, all is working except the last line. To take all files i try using the wildcard * but this creates an error : Exception calling ".ctor" with 2 argument(s)
The whole script looks like this :
Import-Module PSFTP
$pass = ConvertTo-SecureString "1234" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ('...2', $pass)
Set-FTPConnection -Credentials $cred -Server ... -Session CertFTP -IgnoreCert -UseBinary -KeepAlive
$Session1 = Get-FTPConnection -Session CertFTP
Get-FTPItem -Path * -LocalPath 'C:\Certificats' -Session $Session1
I tried the same thing but with -Path "a", and this is working.
Thus, what I don't know is : Am I doing something wrong in the syntax itself, or does Get-FTPItem doesn't support using * in -Path?
I ended up using Get-FTPChildItem in a foreach and then using Get-FTPItem on each object.

Save output to txt file on remote server with user and password [duplicate]

This question already has answers here:
Connecting to a network folder with username/password in Powershell
(3 answers)
Closed 4 years ago.
After connecting to remote computer and executing some powershell job, I need to save a text file with output to a remote server using powershell.
My file name is created depending on computer name and date.
$filename = '' + $enddate + '' + $name + ''
Output is:
$output = "\\10.0.50.8\Informatyka\Posnet_raporty"
There is a username and password to connect to folder "Posnet_raporty"
$username = "user"
$password = "pass"
I use 2 functions to create the file and have been trying to use the NET USE command to create a disc on the remote computer to save the file there, but it has failed ;/ (already mapped source from this adress, net use don't like it)
If ([int]$end1 -gt 30) {
$end1, $end2 | Out-File Q:\$filename'.txt'
}
else {
$end1, $end2 | Out-File Q:\'#'$filename'.txt'
}
The output of $end1 is a number (this does not apply to the question, but I prefer to write everything I can)
edit:
net use fail, can not work with this same source what is already mapped on computers. PSDrive is only accessible in PowerShell session.
I'm not totally clear on what you're trying to do, but if you want to map to a specific remote folder, you might want to use a PSDrive. These are like traditional mapped drives, but are by default only accessible in your PowerShell session. You can create one like this:
$userName = "domain\user"
$password = "Password"
$secPassword = ConvertTo-SecureString $password -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ($userName, $secPassword)
New-PSDrive -Name Q `
-PSProvider FileSystem `
-Credential $cred `
-Root \\ServerName\Share\Folder1\Folder2
The credentials are optional - the mapping will work ok if the current user already has permission to access the location.
You can then use it like any other drive:
Get-ChildItem Q: -File -Recurse
Disconnect afterwards, by doing this:
Remove-PSDrive -Name Q

Import saved AzureRMContext still requires password

I was using Save-AzureRmProfile for all my scripts to execute azure requests in parallel. I borrowed this idea from auto login to azure with powershell/
I had to update my systems to latest version (AzureRM > 4) and despite the fact that the AzureRmProfile are now AzureRmContext cmdlets I still cannot use it as before.
Scenario
Open a PS console and execute
Save-AzureRmContext -Profile (Add-AzureRmAccount) -Path myprofile.json
# List my VMs
Get-AzureRmVm
Open a second PS console
Import-AzureRmContext -Path myprofile.json
# List my VMs
Get-AzureRmVm
Get-AzureRmVM : Your Azure credentials have not been set up or have expired, please run Login-AzureRMAccount to set up your Azure credentials.
How can I reuse my profile to be loaded in parallel executions?
There's a bug in the cmdlets. Not much you can do (only downgrade).
Track it here: https://github.com/Azure/azure-powershell/issues/3954
Here are a couple of workarounds.
Simple, in memory workaround, would need to be added whenever you import a context:
$ctx = Import-AzureRmContext -Path <path-to-context>
$ctx.Context.TokenCache.Deserialize($ctx.Context.TokenCache.CacheData)
More complex workaround. This creates a permanent file, TokenCache.dat, which, if present, may allow you to avoid this problem on a machine altogether.
In a new POSH window:
$ctx = Import-AzureRmContext -Path <path-to-saved-context>
$session = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance
$cacheFile = [System.IO.Path]::Combine($session.ProfileDirectory, $session.TokenCacheFile)
if (Test-Path $cacheFile) {
$session.DataStore.CopyFile($cacheFile, ($cacheFile + ".bak"))
}
$session.DataStore.WriteFile( $cacheFile, [System.Security.Cryptography.ProtectedData]::Protect($ctx.Context.TokenCache.CacheData, $null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser))
$session.TokenCache = New-Object -TypeName Microsoft.Azure.Commands.Common.Authentication.ProtectedFileTokenCache -ArgumentList $cacheFile
[Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile.DefaultContext.TokenCache = $session.TokenCache
Note that this problem should be fixed in the next release
As a workaround until the issue is not fixed or I downgrade my PS installation I used
$azureAccountName ="my.email#example.com"
$Password = "12345678"
$azurePassword = ConvertTo-SecureString $Password -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($azureAccountName, $azurePassword)
Then in my parallel ScriptBlock I do a call like this to replace the broken import credentials
Login-AzureRmAccount -Credential $psCred
Not the kind of solutions I'm proud of but... it did the trick.

Trouble calling powershell script from within powershell with arguments

I have spent the last 4 hours on this issue and would greatly appreciate any input you might have.
I need to call a powershell script with different credentials and pass arguments onto that script.
Following the installation of a program wrapped in WISEScript this script kicks off to gather AD accounts for the machine and remove them from specific AD Security Groups. Unfortunately as the script runs locally I cannot use ActiveDirectory modules in powershell as not all machines in our environment have RSAT.
The initial script is run from an elevated account on the machine:
$creds = New-Object System.Management.Automation.PsCredential("DOMAIN\USER", (ConvertTo-SecureString "Password" -AsPlainText -Force))
$ProfileGUIDS = Get-ChildItem 'hklm:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileGuid'
$Groups = [ADSI]"LDAP://CN=Group4d_test,OU=GroupMigrationTesting,OU=TestOU,OU=US,DC=DOMAIN",[ADSI]"LDAP://CN=Group3d_test,OU=GroupMigrationTesting,OU=TestOU,OU=US,DC=DOMAIN"
Function Get-DistinguishedName ($strUserName)
{
$searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]'')
$searcher.Filter = "(&(objectClass=User)(samAccountName=$strUserName))"
$result = $searcher.FindOne()
if ($result)
{
Return $result.GetDirectoryEntry().DistinguishedName
}
}
forEach ($GUIDkey in $ProfileGUIDS)
{
$GUID = Out-String -InputObject $GUIDKey
$index = $GUID.IndexOf("S-1")
$GUID = $GUID.Substring($index)
$GUID = $GUID.Substring(0,128)
$index = $GUID.IndexOf(" ")
$GUID = $GUID.Substring(0,$index)
$Profile = "hklm:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$GUID"
$ProfileItems = Get-ItemProperty $Profile
$SAM = $ProfileItems.ProfileImagePath
$index = $SAM.LastIndexOf("\")
$index ++
$SAM = $SAM.substring($index)
$UserDN = Get-DistinguishedName $SAM
$User = [ADSI]"LDAP://$UserDN"
if($User -ne $null)
{
forEach($group in $groups)
{
Right here is where I need to call the 2nd script with different credentials.
This is RemoveUsers.ps1, the script I need to run with different credentials:
param
(
[string]$group = "MyDefaultSAM",
[string]$user = "MyDefaultUser"
)
$Group.remove($User.ADsPath)
I have tried:
start-process powershell.exe -Credential $creds -NoNewWindow -ArgumentList "Start-Process $PSSCriptRoot\RemoveUsers.ps1 -Verb
This will run the script however I cannot specify any arguments
powershell.exe -file "$PSScriptRoot\RemoveUsers.ps1" -user $user -group $group
This calls the script with arguments but does not allow for the -Credentials switch
I have also tried:
$job = Start-Job -ScriptBlock {
powershell.exe -file "$PSScriptRoot\RemoveUsers.ps1" -user $user -group $group
} -Credential $creds
This runs but does not appear to work properly as the users remain in the AD groups.
Any help is appreciated.
Thanks - Jeff
**** UPDATE ****
Thanks for the information. When I add the changes you suggest I receive an error
Invoke-Command : Parameter set cannot be resolved using the specified named parameters
It appears, as I have found online, the -Credential switch cannot be used without the -Computer switch. If I specify $env:COMPUTERNAME or localhost for the computer I receive the error
\RemoveUsers.ps1 is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was
included, verify that the path is correct and try again
I can avoid this issue if I remove the -Credential switch and open the AD group to everyone. At this point I don't need to elevate a new powershell script and can add the command in the same. If I cannot resolve the issue with Invoke-Command this is likely what I will do.
**** UPDATE ****
What I ultimately had to do was use -Authentication Credssp in the argument list as there is an issue with using the AD Module via Invoke-Command. In addition I had to start the Win-RM service, Enable WSMacCredSSP (-role client on each machine and add a DelegateComputer entry and -role server on the server connecting to). Only after the service was started and an entry was made for WSManCredSSP was I able to use the Invoke-Command switch and have the AD Module work correctly.
This of course makes things more complicated and I decided just installing the AD Module on each PC (after finding a way to do it without RSAT) and forgetting about running the command remotely all together. Thanks for your help with the matter.
Thanks
You don't need to run PowerShell scripts with powershell.exe when calling them from another PowerShell script. Simply use the call operator (&). Also, I'd use Invoke-Command for running something inline with different credentials.
Beware that the scriptblock doesn't automatically know about the variables in the rest of your script. You need to pass them into the scriptblock via the -ArgumentList parameter. That is most likely the reason why removal didn't work when you ran RemoveUsers.ps1 as a job.
Something like this should work:
Invoke-Command -ScriptBlock {
& "$PSScriptRoot\RemoveUsers.ps1" -user $args[0] -group $args[1]
} -ArgumentList $user, $group -Credential $creds -Computer $env:COMPUTERNAME
This requires PSRemoting, though (run Enable-PSRemoting as an administrator).