Access to password protected network share (double/second hop limitation) - powershell

This is about the famous double-hop limitation that looks trivial and has at least 10 workarounds but I cannot find even one that works for my setup.
Here is my environment: I have ~50 virtual machines on Windows 10, every VM runs on a separate hardware - we use virtual machines because our IT guys claim it's easier to maintain and physical ones, I personally dislike VMs but it's not something that depends on me.
We are on a non-domain environment, no Active Directory, we use a workgroup and every machine is administered individually.
My goal is to optimize PC management like installing software, registering/starting services and etc - I need to do that on all machines at once not to perform each task 50 times. I managed to run PowerShell remote relatively quickly but very soon I stuck on non being able to access any network resource that requires additional authentication (all our network shares requires LDAP authentication).
What I tried so far.
Re-authenticate from the session, described here:
$mappedDrive = #{
Name = "u"
PSProvider = "FileSystem"
Root = "\\bladefs\share2"
Credential = 'svetlozar.draganov'
}
Invoke-Command -ComputerName bw33 -ScriptBlock {
New-PSDrive #using:mappedDrive
Get-Content -Path \\bladefs\share2\text.txt
Get-PSDrive
Remove-PSDrive -Name "u"
Get-PSDrive
} -Credential render
What the above command does is to run a remote command via Invoke-Command that request two authentications, the first authentication is to connect to the machine bw33 then with a New-PSDrive command another authentication is sent to an already establishes session with bw33 to mount a network share with username and password. This sometimes on very rare occasions actually works, but I cannot pinpoint when and why it works and why in most of the cases doesn't work. Even though I'm executing absolutely the same PowerShell script a dozen of times it only works for a very small percentage of them the rest of them it just says this:
A specified logon session does not exist. It may already have been
terminated
+ CategoryInfo : InvalidOperation: (u:PSDriveInfo) [New-PSDrive], Win32Exception
+ FullyQualifiedErrorId : CouldNotMapNetworkDrive,Microsoft.PowerShell.Commands.NewPSDriveCommand
+ PSComputerName : bw33
Cannot find path '\\bladefs\share2\text.txt' because it does not exist.
+ CategoryInfo : ObjectNotFound: (\\bladefs\share2\text.txt:String) [Get-Content], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand
+ PSComputerName : bw33
I actually captured a working and non-working attempt on the video bellow:
https://drive.google.com/uc?id=1HYD8p-VkLYyIExZVWO_8qgpI2kmlUDgF
As you can see with first execution everything is fine PSDrive is mapped successfully and I can reach \bladefs\share2 network path but with second execution I got some errors.
Similar as the above but instead of mapping drive via PSDrive command mapping it via NET USE command with username and password.
Invoke-Command -ComputerName bw33 -Credential render -ScriptBlock {
net use x: \\bladefs\share2 /user:svetlozar.draganov password
Test-Path \\bladefs\share2
}
This, as the first, sometimes works but again it only works once, all subsequent execution leads to this error:
System error 1312 has occurred.
+ CategoryInfo : NotSpecified: (System error 1312 has occurred.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
+ PSComputerName : bw33
A specified logon session does not exist. It may already have been terminated.
Here is a video of another attempt that again captures working and non-working execution of that command:
https://drive.google.com/uc?id=1wP20sbmXMfWu4dvjsdF8REDWgNxiKAS-
Using CredSSP described here:
$session = New-PSSession -cn bw33 -Credential render -Authentication Credssp
Invoke-Command -Session $session -ScriptBlock {Test-Path \\bladefs\share2}
Although this is the most popular and insecure way to resolve this issue I decided to give it a try cause recommended options didn't work. Unfortunately I hit a brick with this approach as well, here are the errors:
New-PSSession : [bw33] Connecting to remote server bw33 failed with
the following error message : The request is not supported. For more
information, see the about_Remote_Troubleshooting Help topic.
At line:1 char:12
+ $session = New-PSSession -cn bw33 -Credential render -Authentication ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OpenError: (System.Manageme....RemoteRunspace:RemoteRunspace) [New-PSSession], PSRemotingTransportException
+ FullyQualifiedErrorId : 50,PSSessionOpenFailed
Invoke-Command : Cannot validate argument on parameter 'Session'. The
argument is null or empty. Provide an argument that is not null or empty,
and then try the command again.
At line:2 char:25
+ Invoke-Command -Session $session -ScriptBlock {Test-Path \\bladefs\sh ...
+ ~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Invoke-Command], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.InvokeCommandCommand
And respectively the video:
https://drive.google.com/uc?id=10tbAq6vvRsvT-1SGqOzvPgIPcM-MT8CJ

I had a somewhat similar issue to yours a while back, but I have a domain joined setup. That shouldn't make to much difference as long as you have the credentials. In your example you don't seem to be using an actual PSCredential object, which might be you issue. If you can use the same credential to connect to the remote system and then back to your share then this should work:
$Password = Read-Host -Prompt 'Enter Password' -AsSecureString
$Credential = New-Object -TypeName PSCredential('username',$Password)
$mappedDrive = #{
Name = "u"
PSProvider = "FileSystem"
Root = "\\bladefs\share2"
Credential = $Credential
}
Invoke-Command -ComputerName bw33 -Credential $Credential -ScriptBlock {
New-PSDrive #Using:mappedDrive
# Do Stuff...
Remove-PSDrive -Name "u"
}

Related

Running Windows updates from poweshell script on remote servers

I know this question has been asked a million times but I am really struggling with this and I would like to be able to add in a few extra features.
I have a list of servers which I would like to input into my script and then I would like the script to go off and check for updates on those servers. After which my aim is to get to it to ask if I want to continue giving the option to input Y/N.
Then I need it to go off and install updates without rebooting. It would be great then to tell me its finished and ask if I want to reboot.
Can anyone help? I am new to powershell and so far only got this which is erroring out.
$creds = Get-Credential
$serverlist = "C:\testlist.txt"
$session=New-PSSession -ComputerName $serverlist
Invoke-Command -Session $session -ScriptBlock {
[net.servicepointmanager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12
Install-module pswindowsupdate -force -AllowClobber
Get-WUInstall -AcceptAll
}
Get-PSSession | Remove-PSSession`
This doesn't get me anywhere and gives this error.
New-PSSession : One or more computer names are not valid. If you are trying to pass a URI, use the -ConnectionUri parameter, or pass URI objects instead of strings.
At C:\Untitled5.ps1:16 char:10
+ $session=New-PSSession -ComputerName $serverlist
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (System.String[]:String[]) [New-PSSession], ArgumentException
+ FullyQualifiedErrorId : PSSessionInvalidComputerName,Microsoft.PowerShell.Commands.NewPSSessionCommand
Invoke-Command : Cannot validate argument on parameter 'Session'. The argument is null or empty.
Provide an argument that is not null or empty, and then try the
command again.
At C:\Untitled5.ps1:17 char:25
+ Invoke-Command -Session $session -ScriptBlock {
+ ~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Invoke-Command], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.InvokeCommandCommand`

PowerShell 5.1 What is wrong with my New-PSSession syntax

Environment:
PowerShell 5.1
Windows 2016 Standard
Windows 10 Pro
Just asking here if syntax is fundamentally correct...
$hostSession = New-PSSession -ComputerName $hostName -Credential $cred
$versionFolder = "c:\temp"
$sspLatestVer = Invoke-Command -Session $hostSession -ScriptBlock { param($path) (Get-ChildItem $path | Sort-Object LastWriteTime -Descending | Select-Object -First 1).Name } -ArgumentList $versionFolder
Update:
The following works on one machine but not on another:
$versionFolder = "\\COMPUTER01\c$\temp"
$sspLatestVer = (Get-ChildItem $versionFolder | Sort-Object LastWriteTime -Descending | Select-Object -First 1).Name
Error Message for machine that doesn't work
Get-ChildItem : Cannot find path '\\COMPUTER01\c$\temp' because it does not exist.
At C:\temp\candidate2.ps1:24 char:18
+ $sspLatestVer = (Get-ChildItem $versionFolder | Sort-Object LastWrite ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (\\COMPUTER01\c$\temp:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
OP Error Message:
New-PSSession : [COMPUTER01] Connecting to remote server COMPUTER01 failed with the following error message : WinRM cannot process the request. The following error with errorcode 0x80090311 occurred while using
Kerberos authentication: We can't sign you in with this credential because your domain isn't available. Make sure your device is connected to your organization's network and try again. If you previously signed in on
this device with another credential, you can sign in with that credential.
Possible causes are:
-The user name or password specified are invalid.
-Kerberos is used when no authentication method and no user name are specified.
-Kerberos accepts domain user names, but not local user names.
-The Service Principal Name (SPN) for the remote computer name and port does not exist.
-The client and remote computers are in different domains and there is no trust between the two domains.
After checking for the above issues, try the following:
-Check the Event Viewer for events related to authentication.
-Change the authentication method; add the destination computer to the WinRM TrustedHosts configuration setting or use HTTPS transport.
Note that computers in the TrustedHosts list might not be authenticated.
-For more information about WinRM configuration, run the following command: winrm help config. For more information, see the about_Remote_Troubleshooting Help topic.
At C:\Users\RSTEST\Documents\candidate2.ps1:17 char:16
+ ... hostSession = New-PSSession -ComputerName $hostName -Credential $cred
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OpenError: (System.Manageme....RemoteRunspace:RemoteRunspace) [New-PSSession], PSRemotingTransportException
+ FullyQualifiedErrorId : AuthenticationFailed,PSSessionOpenFailed
Invoke-Command : Cannot validate argument on parameter 'Session'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
At C:\Users\RSTEST\Documents\candidate2.ps1:19 char:41
+ $sspLatestVer = Invoke-Command -Session $hostSession -ScriptBlock { p ...
+ ~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Invoke-Command], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.InvokeCommandCommand
Remove-PSSession : Cannot validate argument on parameter 'Name'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
At C:\Users\RSTEST\Documents\candidate2.ps1:20 char:24
+ Remove-PSSession -Name $hostSession
+ ~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand
Two issues here:
First, see WinRM cannot process the request. Error 0x80090311
If the remote system is in the same domain, and you are already logged in with a domain account that is an administrator on that system, then there would be no need to specify a credential for New-PSSession
If the systems are in different forests that have a trust with each other, note that there is a need to use the fully qualified domain name (FQDN) of the remote host for Kerberos authentication to function correctly.
Second, regarding:
$versionFolder = "\\COMPUTER01\c$\temp"
Note that remote sessions normally do not have access to network shares, even when presumably running under the credentials of an administrative user.
This is known as the "second hop problem". There have been various posts about it:
https://learn.microsoft.com/en-us/powershell/scripting/learn/remoting/ps-remoting-second-hop?view=powershell-5.1
https://devblogs.microsoft.com/scripting/enable-powershell-second-hop-functionality-with-credssp/
This may work from COMPUTER01 itself, since it could be aliased to local drive access.

Powershell VSCode invoke-command from localhost different user for SCCM

Because VSCode is not able to run a powershell console and debug it as a different user i am trying to get arround it with invoked credentials like this:
Start-Service -Name "WinRM"
$cred = Get-Credential -Credential domain\myuser
Invoke-command -Credential $cred -Computer "localhost" -scriptblock {
Import-Module "$($ENV:SMS_ADMIN_UI_PATH)\..\ConfigurationManager.psd1"
Set-Location 'XXX:' # my sccm site code
Import-CMComputerInformation -CollectionName "All Systems" -ComputerName "TestComputer" -MacAddress "00:00:00:00:00:69"
}
If i start it in the debugger of VSCode (F5) it starts but cant connect then to the SCCM Server infrastructure. Could someone help me to solve this issue?
Error:
Cannot find drive. A drive with the name 'XXX' does not exist.
+ CategoryInfo : ObjectNotFound: (XXX:String) [Set-Location], DriveNotFoundException
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.SetLocationCommand
+ PSComputerName : localhost
This command cannot be run from the current drive. To run this command you must first connect to a Configuration Manager drive.
+ CategoryInfo : DeviceError: (Microsoft.Confi...ormationCommand:ImportComputerInformationCommand) [Import-CMComputerInformation], InvalidOperationException
+ FullyQualifiedErrorId : CommandCannotExecuteFromCurrentDrive,Microsoft.ConfigurationManagement.Cmdlets.Oob.Commands.ImportComputerInformationCommand
+ PSComputerName : localhost
If i logoff from my machine and login with my admin credentials and execute everything in the invoke-command scriptblock it works.
As i am not allowed to work like this by our company policy's is there maybe a alternative way or something i can do to use the visual studio code debugger?
Have you logged onto the SCCM site server interactively with the credentials you are using and opened the console at least once? I believe this initial first opening is required before the drive is accessible remotely...

Remote server login error

Hi I want to login into my remote server using power shell . I wrote code for this but I am getting error .
CODE
$cred = get-credential - Prompts for username and password
Enter-PSSession -ComputerName servername -Credential $cred
ERROR
Get-Credential : A positional parameter cannot be found that accepts
argument 'Prompts'.At C:\documents\Untitled8.ps1:1 char:9
+ $cred = get-credential - Prompts for username and password
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-Credential], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.GetCredentialCommand
Enter-PSSession : Connecting to remote server XXXXX failed with the
following error message : Access is denied. For more information, see
the about_Remote_Troubleshooting Help topic.At
C:\documents\Untitled8.ps1:5 char:1
+ Enter-PSSession -ComputerName servername -Credential $cred
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (servername:String) [Enter-PSSession], PSRemotingTransportException
+ FullyQualifiedErrorId : CreateRemoteRunspaceFailed
Any clue regarding this will help....
Get-Credential : A positional parameter cannot be found that accepts argument 'Prompts'
Anybody have any clue how to login into remote server in power shell using servername..any clue any link regarding this will be helpful
The problem is that there it canĀ“t find a positional parameter, where "Prompts" is accepted. If you look at the help file for Get-credential you will see that the -Credential paramenter is positional, meaning you dont need to type it.
Try with this
$cred = get-credential -Message "Prompts for username and password"
Enter-PSSession -ComputerName servername -Credential $cred
Some reading about positional parameters
https://itknowledgeexchange.techtarget.com/powershell/positional-parameters/

"Access is denied" error during "New-Item" call in PS

I am trying to create a folder on a server using powershell. The script looks like this:
$pass = ConvertTo-SecureString "myPW" -AsPlainText -Force
$cred = new-object System.Management.Automation.PSCredential("myUser", $pass)
$session = New-PSSession -ComputerName "localhost" -Credential $cred
Invoke-Command -session $session -ScriptBlock {
New-Item -Path "\\myServer\myShare\" -Name "myFolder" -ItemType directory -Force
}
I'm getting the following error:
Access is denied
+ CategoryInfo : PermissionDenied: (\\myServer\myShare:String) [New-Item], UnauthorizedAccessException
+ FullyQualifiedErrorId : ItemExistsUnauthorizedAccessError,Microsoft.PowerShell.Commands.NewItemCommand
+ PSComputerName : localhost
Access to the path 'myShare' is denied.
+ CategoryInfo : PermissionDenied: (\\myServer\myShare:String) [New-Item], UnauthorizedAccessException
+ FullyQualifiedErrorId : CreateDirectoryUnauthorizedAccessError,Microsoft.PowerShell.Commands.NewItemCommand
+ PSComputerName : localhost
Access to the path 'myFolder' is denied.
+ CategoryInfo : PermissionDenied: (\\myServer\myShare\myFolder:String) [New-Item], UnauthorizedAccessException
+ FullyQualifiedErrorId : CreateDirectoryUnauthorizedAccessError,Microsoft.PowerShell.Commands.NewItemCommand
+ PSComputerName : localhost
At first I thought the message is pretty clear an the user I used is missing rights. But here is the thing: If I go to the share in the Explorer and log in with the same user, I can create a folder without any problems. Besides that, the user is Domain Admin.
What am I doing wrong?
It's a double hop, you're connecting to a PSSession and then trying to access the folder.
As a security measure PowerShell does not allow you to remote to one computer, then remote to another computer from there (even if two of those are the same computer). The exact reasoning is complex and heavily involved in how credentials are used in sessions and I don't fully understand it myself so I won't try to explain but basically it's to prevent the credentials being stolen.
You can do some reading on it (this looks like a good resource) but it would be a LOT simpler to just try to work out another way of doing it. You're only remoting to the local computer so you could for example start another PS process.
If you are just using a PSSession for the alternative credentials to access the share, then using New-PSDrive might be an alternative way to do it:
$pass = ConvertTo-SecureString "myPW" -AsPlainText -Force
$cred = new-object System.Management.Automation.PSCredential("myUser", $pass)
New-PSDrive -Name myShare -PSProvider FileSystem -Root "\\myServer\myShare\" -Credential $cred
New-Item -Path "myShare:\" -Name "myFolder" -ItemType directory -Force