Connect to server that requires authentication using PowerShell 5.1? - powershell

I am new to PowerShell. I can't connect to a server that requires a username and password.
I wrote a script that moves files from 5 different servers to 5 different sources.
Out of these 5 source servers, one of them requires a username and password to connect to it.
This script is supposed to run every hour. I want the authentication to go through so when it comes to transferring files the script runs as is without errors.
The code below gives the following error:
Connecting to remote server xx.xx.xx.x failed with the following error message : The WinRM client cannot
process the request. Default authentication may be used with an IP address under the following conditions: the transport
is HTTPS or the destination is in the TrustedHosts list, and explicit credentials are provided. Use winrm.cmd to configure
TrustedHosts. Note that computers in the TrustedHosts list might not be authenticated.
The complete code block is:
$logPath = "C:\Users\Log.txt"
$trancriptPath = "C:\Users\LogTranscript.txt"
$getDate = Get-Date -Format "dddd MM/dd/yyyy HH:mm "
$counter = 0
Start-Transcript -Path $trancriptPath -Append
Add-Content -Path $logPath -Value ("LOG CREATED $getDate") -PassThru
#Credentials For Server5
$password = ConvertTo-SecureString “password” -AsPlainText -Force
$userName = "username"
[pscredential]$cred = New-Object System.Management.Automation.PSCredential -ArgumentList #($userName, $password)
Enter-PSSession -ComputerName "xx.xx.xx.x" -Credential $cred
#Sources
$srcMt01 = "\\Server2\programs\RECEIVE\*"
$srcMt01NameChg ="\\Server2\programs\RECEIVE"
$srcMC2o = "\\Server3\Predator\Revised Programs\MC2o\*"
$srcMC2oNameChg ="\\Server3\Predator\Revised Programs\MC2o"
$srcHm03 = "\\Server4\Predator\Revised Programs\H3\*"
$srcHm03NameChg ="\\Server4\Predator\Revised Programs\H3"
$srcMca = "\\Server5\Public\NcLib\FromNC\*"
$srcMcaNameChg ="\\Server5\Public\NcLib\FromNC"
$srcMt02 = "\\Server6\programs\RECEIVE\*"
$srcMt02NameChg ="\\Server6\programs\RECEIVE"
#Destination
$destMt01 = "\\Sever1\MfgLib\RevisedPrograms\MT01"
$destMC2o = "\\Server1\MfgLib\RevisedPrograms\MC2old"
$destHm03 = "\\Sever1\MfgLib\RevisedPrograms\H3"
$destMca = "\\Sever1\MfgLib\RevisedPrograms\MC-A"
$destMt02 = "\\Sever1\MfgLib\RevisedPrograms\MT02"
Function MoveFiles{
Param(
[string]$src,
[string]$dest,
[string]$srcNameChange
)
Get-ChildItem -Force -Recurse $src -ErrorAction Stop -ErrorVariable SearchError | ForEach-Object{
$counter++
$fileName = $_.Name
# Check for duplicate files
$file = Test-Path -Path $dest\$fileName
Write-Output $file
if($file)
{
"$srcNameChange\$fileName" | Rename-Item -NewName ("Copy_"+$fileName);
Add-Content -Path $logPath -Value ("$fileName exists in destination folder. Name change was successful") -PassThru
}
}
Move-Item -Path $src -Destination $dest -Force
Add-Content -Path $logPath -Value ("$counter file(s) moved to $dest") -PassThru
}
MoveFiles -src $srcMt01 -dest $destMt01 -srcNameChange $srcMt01NameChg
MoveFiles -src $srcMC2o -dest $destMC2o -srcNameChange $srcMC2oNameChg
MoveFiles -src $srcHm03 -dest $destHm03 -srcNameChange $srcHm03NameChg
MoveFiles -src $srcMca -dest $destMca -srcNameChange $srcMcaNameChg
MoveFiles -src $srcMt02 -dest $destMt02 -srcNameChange $srcMt02NameChg
Stop-Transcript
Any help is appreciated.

You might find it easier to remote into the server using Invoke-Command and then running your file copy using a script block on the remote server. You will probably need to use CredSSP authentication so the copy process can connect to the destination server.
The server running the script will need to be configured as a WinRM client and the remote servers will need WinRM configured to accept connections. This is most likely where your current WinRM error is coming from. That's a pretty involved discussion so do some research and post specific questions as you uncover them.
Ex.
$Destination = "\\Sever1\MfgLib\RevisedPrograms\MT01"
$SourceServer = "Server2"
$password = ConvertTo-SecureString “password” -AsPlainText -Force
$userName = "username"
[pscredential]$cred = New-Object System.Management.Automation.PSCredential -ArgumentList #($userName, $password)
$ScriptBlock = {
param ( [string]$dest )
Code to move the files from source to $dest
}
Invoke-Command -ComputerName $SourceServer -ScriptBlock $ScriptBlock -Authentication CredSSP -Credentials $Cred -ArgumentList $Destination

Related

PowerShell script to list files from sftp server folder

I am trying to get list of files from an SFTP folder using the following PowerShell script:
$files = Get-SftpChildItem -Host mysftpserver -Port 22 -Username myusername -Password mypassword -RemoteLocation "/MySFTPFolder/outbound/"
ForEach ($f in $files)
{
"test" | Out-File $ConfigFile -Append
}
For some reason I am not able to read the 2 files that are in the remote outbound folder. Is there something I am missing?
You may be running an old version of the Posh-SSH module, since your syntax looks very different than mine, and the fact that you don't have help files installed. You should install the latest version with:
Find-Module Posh-SSH | Install-Module
Then you can create a SFTP session, and use that session to list the child items as you desire:
$userName = 'MyUserName'
$secStringPassword = 'MyPassword' | ConvertTo-SecureString -AsPlainText -Force
$Creds = [pscredential]$credObject = New-Object System.Management.Automation.PSCredential ($userName, $secStringPassword)
$session = New-SFTPSession -computername mysftpserver -Credential $Creds
$files= Get-SFTPChildItem -SFTPSession $session -Path "/MySFTPFolder/outbound/"
ForEach ($f in $files)
{
"test" | Out-File $ConfigFile -Append
}

How to pass variable in Scriipt Block for use with Invoke-Command that will call an executable that takes the variable as switch param

I am attempting to create a generic script that will process registry files on a list of remote servers. The script will take the input of the path/filename to process and a list of servers to process it on. Copies the .reg file to the remote server and then attempts to process the .reg file on the remote server. In order to make it generic for use with any .reg file I want to pass the path\filename to process in a variable in the script block. I have seen examples of passing named variables and positional parameters but that doesn't seem to meet my requirements. I tried creating the script block contents as a Scriptblock type and calling it but it does not work. Most of the errors I have been getting are related to invalid parsing, ambiguous parameter, etc. I have seen a couple of working examples in which the .reg file path/filename is hard-coded but that defeats the purpose of what I am attempting to accomplish. I have tried the Invoke-Command with a session and with the -ComputerName variable in order to try the :using:" command with no success. Is there any way to pass a variable that is basically the command line values (switch params & filepath/name) for an executable within the scriptblock or am I going about this in the wrong manner? In code below I am crossing domains so having to open session for those servers in order to create directory if it doesn't exist.
while ($true)
{
$regFile = Read-Host -Prompt "Enter the path & name of registry file to be processed"
If(Test-Path -Path $regFile) { break }
Write-Host "You must enter valid path & filename of a registry file to process."
}
$servers = Get-Content D:\MLB\Scripts\servers.txt
$fileNm = [System.IO.Path]::GetFileName($regFile)
$pass = ConvertTo-SecureString "blahblah" -AsPlainText -Force
$Creds = new-object -typename System.Management.Automation.PSCredential( "domain\username", $pass)
foreach ($server in $servers)
{
$dirPath = ''
$newfile = '\\' + $server + '\d$\MLB\RegFiles\' + $fileNm
if($server.ToLower().Contains("web"))
{
$Session = New-PSSession -ComputerName $server -Credential $Creds
Invoke-Command -Session $Session -ScriptBlock { New-Item -ErrorAction SilentlyContinue -ItemType directory -Path D:\MLB\RegFiles }
$newfile = "d:\MLB\RegFiles\" + $fileNm
Copy-Item $regFile -Destination $newfile -ToSession $Session -Force
Remove-PSSession -Session $Session
}
else
{
$dirPath = "\\$server\d`$\MLB\RegFiles"
New-Item -ErrorAction SilentlyContinue -ItemType directory -Path $dirPath
$newfile = "\\$server\d`$\MLB\RegFiles\$fileNm"
Copy-Item $regFile -Destination $newfile -Force
}
Invoke-Command -ComputerName $server -Credential $Creds -ScriptBlock {
$args = "s/ $newfile"
Start-Process -filepath "C:\Windows\regedit.exe" -Argumentlist $args
}

MI_RESULT_FAILED on Copy-Item in PowerShell Script

I am running PowerShell on CentOS 7.x. I converted working individual commands when running within PowerShell via pwsh to a PowerShell script and then it no longer works. Can someone please shed me some light on what I did wrong?
Here's the working individual commands when running within PowerShell via pwsh.
PS /home/user1/Downloads> $userPw = ConvertTo-SecureString -String "user1password" -AsPlainText -Force
PS /home/user1/Downloads> cd
PS /home/user1> $userCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "user1win", $userPw
PS /home/user1> $s = New-PSSession -computerName 192.168.20.143 -credential $userCredential -Authentication Negotiate
PS /home/user1> Copy-Item -Path /home/user1/Downloads/gssntlmssp-0.7.0-1.el7.x86_64.rpm -Destination "C:\users\user1win\Desktop" -ToSession $s
PS /home/user1> exit
Here's the script when I converted to a PowerShell script so I can pass arguments into it. remote-copy.ps
$remoteHost = $args[0]
$username = $args[1]
$pwp = $args[2]
$source = $args[3]
$destination = $args[4]
Write-Host "Remote Host: '$remoteHost'"
Write-Host "Username: '$username'"
Write-Host "Password: '$pwp'"
Write-Host "Source: '$source'"
Write-Host "Destination: '$destination'"
$pw = ConvertTo-SecureString -String $pwp -AsPlainText -Force
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $pw
$s = New-PSSession -computerName $remoteHost -credential $cred -Authentication Negotiate
Copy-Item -Path $source -Destination $destination -ToSession $s
When I run the script, I got the following error.
[user1#rhel7-tm PowerShell]$ pwsh -File ./remote_copy.ps 192.168.20.143 user1win user1password /home/user1/Downloads/vte-0.28.2-10.el7.x86_64.rpm "C:\\users\user1win\Desktop"
Remote Host: '192.168.20.143'
Username: 'user1'
Password: 'user1password'
Source: '/home/user1/Downloads/vte-0.28.2-10.el7.x86_64.rpm'
Destination: 'C:\users\user1win\Desktop'
Copy-Item:
Line |
19 |
Copy-Item -Path "$source" -Destination "$destination" -ToSession $s |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
Starting a command on the remote server failed with the following error message : MI_RESULT_FAILED For more information, see the about_Remote_Troubleshooting Help topic.
Copy-Item: Line |
19 |
Copy-Item -Path "$source" -Destination "$destination" -ToSession $s |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
Failed to copy file /home/user1/Downloads/vte-0.28.2-10.el7.x86_64.rpm to remote target destination.
I would be greatly appreciate if someone can point me to where I did wrong. Thanks!
It's a false alarm. The script does work. The issue is by default the MaxEnvelopeSizekb in winrm/config is only 500kb. I need to set to a bigger value if I want to send a bigger file. To set MaxEnvelopSizekb to 500mb, you need to open PowerShell on Windows as Administrator and run the following command.
PS C:\WINDOWS\system32> Set-WSManInstance -ResourceUri winrm/config -ValueSet #{MaxEnvelopeSizekb = "500000"}

Use PowerShell to remotely bulk override a file and restart a certain service

I need your help.
I need to write a script that will from a windows server,
Will connect to a list of servers (provided by a csv that has IP Addresses)
on those servers will overwrite a file located either on
C:\Program Files (x86)\Folder1 or C:\Program Files\Folder1
Taking the correct version from the server Running the script from D:\
and then restart a service called sname1.
(we can assume all target servers have the WinRM Active)
Your help will be greatly appriciated.
What I have so far is this, but I'm not sure it's correct assuming I'm working with IP Addresses and not Hostnames (Hostnames aren't an option as I'm not using this in a domain environment)
$servers=Get-Content D:\List.txt
foreach ($server in $servers)
{
if (Test-Path "\\$_\c$\Program Files\Folder1")
{
Copy-Item \\127.0.0.1\D$\file1.ini "\\$_\c$\Program Files\Folder1\file1.ini"
}
if (Test-Path "\\$_\c$\Program Files (x86)\Folder1")
{
Copy-Item \\127.0.0.1\D$\file1.ini "\\$_\c$\Program Files (x86)\Folder1\file1.ini"
}
Restart-Service -InputObject $(Get-Service -Computer $server -Name sname1)
}
REF:
$servers=Import-Csv E:\Temp\serverlist.csv
$Source = "D:\file1.ini"
foreach ($server in $servers)
{
$Password = ConvertTo-SecureString -AsPlainText -Force -String "$server.Password"
$User = "$server.Domain\$server.Usernaem"
$credentials = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $user,$password
if (Test-Path "\\$server.Alias\c$\Program Files\Folder1")
{
$Destination = "\\$server.Alias\c$\Program Files\Folder1"
}
if (Test-Path "\\$server.Alias\c$\Program Files (x86)\Folder1")
{
$Destination = "\\$server.Alias\c$\Program Files (x86)\Folder1"
}
Copy-Item $Source -Destination $Destination -Credential $credentials -Force
Restart-Service -InputObject $(Get-Service -Computer $server,Alias -Name sname1)
}
Note that you CANNOT access properties or methods of variables if you enclose it in quotes. For example, if you say;
$test = 1234
Write-Output "House $test.ToString()"
You will get the output "House 1234.ToString()" because the method is not resolved, it just assumes it's a string. You need to either split it up or enclose it:
Write-Output ("House " + $test.ToString())
Write-Output "House $($test.ToString())"
Additionally you've misspelled UserName when declaring $User. Fix those up and it should work fine.
I recommend checking out Microsoft's MVAs PowerShell 3.0 JumpStart and Advanced Tools & Scripting as they explain a lot of this stuff, get you into good habits and are actually pretty fun to watch.

Using Remove-Item with Credentials

I am attempting to use the Remove-Item cmdlet as part of an automation for a system. The files are stored on a server that requires elevated rights to perform the file deletion. I have access to a domain admin account that I use for such automation scripts.
The code below will build the PSCredential object:
$password = New-Object System.Security.SecureString
"passwordhere".ToCharArray() | ForEach-Object { $password.AppendChar($_) }
$cred = New-Object System.Management.Automation.PSCredential("domain\username",$password)
$cred
I am passing this object to the following action:
Remove-Item -LiteralPath $path -Force -Credential $cred
Any ideas?
It's not clear to me if the files are local (you're running the script on the server) or remote (on another machine). If local try running the command using a background job and pass in the credentials to Start-Job:
$job = Start-Job { Remove-Item -LiteralPath $path -force } -cred $cred
Wait-Job $job
Receive-Job $job
If they're remote, try using remoting:
Invoke-Command -computername servername `
-scriptblock { Remove-Item -LiteralPath $path -force } `
-Cred $cred
Note: This requires that you execute Enable-PSRemoting on the remote machine.
In general, putting raw passwords in your script isn't a great idea. You can store the password in an encrypted manner using DPAPI and later, only that user account can decrypt the password e.g.:
# Stick password into DPAPI storage once - accessible only by current user
Add-Type -assembly System.Security
$passwordBytes = [System.Text.Encoding]::Unicode.GetBytes("Open Sesame")
$entropy = [byte[]](1,2,3,4,5)
$encrytpedData = [System.Security.Cryptography.ProtectedData]::Protect( `
$passwordBytes, $entropy, 'CurrentUser')
$encrytpedData | Set-Content -enc byte .\password.bin
# Retrieve and decrypted password
$encrytpedData = Get-Content -enc byte .\password.bin
$unencrytpedData = [System.Security.Cryptography.ProtectedData]::Unprotect( `
$encrytpedData, $entropy, 'CurrentUser')
$password = [System.Text.Encoding]::Unicode.GetString($unencrytpedData)
$password
Remove-Item can fail due to authorisation. Alternatively, either find the reference for each file and hit it with a .Delete() or move all of the files to the recycle bin.
foreach ($svr in $computers)
{
Invoke-Command -ComputerName $svr {
$folderitems = Get-ChildItem $cachefolder -Recurse
# Method 1: .Delete
foreach ($cachefolderitem in $cachefolderitems)
    {
     if ($cachefolderitem -like "*.ini")
        {
$cachefolderitem.Delete()
        }
}
# Method 2: Move all matching files to the recycle bin
Move-Item "$cachefolder\*.ini" 'C:\$Recycle.Bin' -Force
}