PowerShell 5.1 What is wrong with my New-PSSession syntax - powershell

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.

Related

Rename-Computer is throwing "access is denied" error but I can't figure out to what

I am on a Windows 10 Enterprise machine that is hosting hyperv machines. We will call this "Win10Host".
One of the virtual machines is "Win10Base" which is a base install of Windows 10 Pro.
I am attempting to run the below from "Win10Host" to rename "Win10Base" and it is failing (errors below).
$secpasswd = ConvertTo-SecureString 'mypassword' -AsPlainText -Force
$localCreds = New-Object System.Management.Automation.PSCredential ('user', $secpasswd);
$computername = 'Win10Base';
$VMName = 'Win10BaseNew';
$VMIP = 'x.x.x.x'; //Redacted, I have used remote desktop to verify this ip is correct.
Rename-Computer -ComputerName $VMIP -LocalCredential $localCreds -NewName $VMName -Verbose;
Win10Base is a basic click through windows 10 pro install.
user is the initial user setup after install.
At first it was throwing:
Rename-Computer : Cannot establish the WMI connection to the computer 'Win10Base'
with the following error message: Access denied .
At line:9 char:1
+ Rename-Computer -ComputerName $computername -LocalCredential $localCr ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (Win10Base:String) [Rename-Computer], InvalidOperationException
+ FullyQualifiedErrorId : RenameComputerException,Microsoft.PowerShell.Commands.RenameComputerCommand
After giving permissions to Remote Desktop, configuring the firewall, giving permissions to "Windows Management Instrumentation" in dcomcnfg, and giving access through wmimgmt.msc to the CIMV2 namespace I have arrived at my current situation.
Currently the powershell throws:
Rename-Computer : Fail to rename computer 'Win10Base' to 'Win10BaseNew'
due to the following exception: Access is denied.
At line:9 char:1
+ Rename-Computer -ComputerName $computername -LocalCredential $localCr ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (Win10Base:String) [Rename-Computer], InvalidOperationException
+ FullyQualifiedErrorId : FailToRenameComputer,Microsoft.PowerShell.Commands.RenameComputerCommand
Run scenarios:
On Win10Base ISE - fails with the "access denied".
On Win10Base ISE run as admin - success.
On Win10Host ISE - fails with the "access denied"
On Win10Host ISE run as admin - fails with the "access denied"
As best I can tell user on Win10Base is an administrator. I even enabled "god mode" to see if I could change the user type to a high level and found it was in the administrators group.
Checking Windows Event logs (Application, Security, Setup, and system) I see nothing to correlate with the current access denied. Nothing is picked up in DbView as best I can tell.
So any suggestions on where to look next for WHAT access is denied would be greatly appreciated.
If the machine isn't on the domain your user domain needs to be specified in credentials - DOMAIN\user - where the domain is the local machine name.
Also enable WinRM in the remote machine using "winrm quickconfig" at command line

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

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"
}

PowerShell Stopping and Starting Services with Server names masked by DNS Alias

I have a simple PowerShell that accepts a file as a parameter that contains Server-Name, Service-Name and Timeout specified in seconds and the powershell stops/starts the services based on the command. I have 10 servers where application related services are configured and I'm using Workload automation capabilities to run this code on any server with the same parameter file and powershell present on all 10 servers.
All of this works fine with server names hardcoded in the param file. We have n+2 Infrastructure, and I created DNS Aliases for all the 10 servers to make Active-Standby switchover little easy. Now the problem comes with stop/start script. Ex: If the script gets invoked in Server 7, all the services will be shutdown except for the ones in Server 7 and I get below error:
Get-Service : Cannot find any service with service name
'Application-Server7'. At line:1 char:1
+ Get-Service -ComputerName app7test -Name Application-Server7
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Application-Server7:String) [Get-Service], ServiceCommandException
+ FullyQualifiedErrorId : NoServiceFoundForGivenName,Microsoft.PowerShell.Commands.GetServiceCommand
I just tested one-liner command using PowerShell ISE on the computer "appnewora79" and below are the results.
This works fine:
Get-Service -ComputerName appnewora79 -Name Application-Server7
Status Name DisplayName
------ ---- -----------
Stopped Application-Ser... Application-Server7
This fails:
Get-Service -ComputerName app7test -Name Application-Server7
Get-Service : Cannot find any service with service name 'Application-Server7'
At line:1 char:1
+ Get-Service -ComputerName app7test -Name Application-Server7
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Application-Server7:String) [Get-Service], ServiceCommandException
+ FullyQualifiedErrorId : NoServiceFoundForGivenName,Microsoft.PowerShell.Commands.GetServiceCommand
Any suggestions to overcome this, please?
I tried below as well:
It all works when the server name is hardcoded. If I change it to DNS Alias name then Get-Service fails on the server where it is executing while fetching service details only related to the same server.
On the Server-1, if I run below commands, they all work fine
Get-Service -ComputerName servername1
Get-Service -ComputerName servername2
Get-Service -ComputerName servername3
If I update the above command with server dns alias and execute them on Server-1, then only the first command fails, i.e.. the command with the same server name masked with DNS fails, If I run the same commands on server 2, then the second one alone fails
Get-Service -ComputerName dnsalias1
Get-Service -ComputerName dnsalias2
Get-Service -ComputerName dnsalias3
I tried, test-connection with DNS alias names and they go thru fine. Tried Get-WmiObject -Class WIN32_service with computer name masked as DNS alias and it goes thru fine. I'm lost as to what could be the issue.
Below is the error message with Get-Service alone:
Get-Service : Cannot open Service Control Manager on computer 'dnsalias1'. This operation might require other privileges.
At line:5 char:1
+ Get-Service -ComputerName dnsalias1
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-Service], InvalidOperationException
+ FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.PowerShell.Commands.GetServiceCommand
I found a kind of different way to resolve this as per suggestion received in PowerShell Google+ forum.
I used Resolve-DnsName to get hold of IP4Address of the server and then passed it for stopping and starting windows services and this works.

Why does Invoke-Command { net localgroup } fail?

I can successfully use NET USE and NET USER commands on the remote machine. Why not NET LOCALGROUP?
PS C:\src\powershell> Invoke-Command -ComputerName OTHERMACHINE -ScriptBlock { & NET LOCALGROUP }
System error 1312 has occurred.
+ CategoryInfo : NotSpecified: (System error 1312 has occurred.:String) [], Rem
oteException
+ FullyQualifiedErrorId : NativeCommandError
+ PSComputerName : OTHERMACHINE
A specified logon session does not exist. It may already have been terminated.
Passing the /USER parameter produces a different error.
PS C:\src\powershell> Invoke-Command -ComputerName OTHERMACHINE -ScriptBlock { & net localgroup /USER:THEDOM\theuser }
The option /USER:THEDOM\theuser is unknown.
+ CategoryInfo : NotSpecified: (The option /USE...son is unknown.:String) [], R
emoteException
+ FullyQualifiedErrorId : NativeCommandError
+ PSComputerName : OTHERMACHINE
The syntax of this command is:
NET LOCALGROUP
[groupname [/COMMENT:"text"]] [/DOMAIN]
groupname {/ADD [/COMMENT:"text"] | /DELETE} [/DOMAIN]
groupname name [...] {/ADD | /DELETE} [/DOMAIN]
More help is available by typing NET HELPMSG 3506.
I believe this is the double-hop problem. You get the same error if you try to execute net localgroup administrators in a session created with Enter-PSSession: "System error 1312 has occurred." and "A specified logon session does not exist. It may already have been terminated."
net.exe is trying to reauthenticate, but it can't reuse the credentials of the session. You may have success using CredSSP, which requires some setup and, IIRC, may have security implications. You'll have to enable CredSSP on the remote system and local system, and then delegate correctly. Even then I'm seeing conflicting reports about this working. There may even be security policies preventing it.
Personally, I just wouldn't use net.exe at all. That's too many hoops to jump through for something so basic. You can retrieve the members of a local group remotely via the ADSI provider, which is probably much easier and much more likely to work.

PowerShell Double Hop Issue

I’m trying to run a PowerShell script on SYSTEM1, which executes robocopy on SYSTEM2, copying files to SYSTEM3,4,5,etc.
SYSTEM1 and SYSTEM2 are on the same domain, but SYSTEM2 is not behind a firewall (hence the need to run robocopy from SYSTEM2 and not SYSTEM1).
SYSTEM3,4,5 are on different domains than SYSTEM2, as well as different domains than each other.
I set the script up like this (it uses the net use command to prompt the user for credentials for the different domains):
Foreach($server in $servers) {
$command = {
param($cred, $server);
$error.clear();
# Stored credentials in local variables
$user = $cred.GetNetworkCredential().username
$pass = $cred.GetNetworkCredential().password
#establish connection from SYSTEM2-> $server
net use \\$server\c$\Deployments /delete
net use \\$server\c$\Deployments /USER:$user $pass
# Check to see if C:\Deployments exists on server, and if not create it.
if ((Test-Path \\$server\c$\Deployments) -eq $FALSE) {
$c = {
New-Item \\$server\c$\Deployments -type directory
}
$ws = Invoke-Command -ComputerName $server -Credential $cred -ScriptBlock $c
}
# Copy over the deployment packages
$dest = "\\$server\Deployments\$DeploymentDate\$CurrentDirectoryName"
robocopy $CurrentDirectoryPath $dest /W:20 /R:15 /e /XF CopyPackage.ps1
# Delete connection from SYSTEM2 -> $server
net use \\$server\c$\Deployments /delete
However, the net use command returns an error after the credentials are entered:
The network connection could not be found.
+ CategoryInfo : NotSpecified: (The network con...d not be found.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
+ PSComputerName : SYSTEM2
More help is available by typing NET HELPMSG 2250.
System error 55 has occurred.
+ CategoryInfo : NotSpecified: (System error 55 has occurred.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
+ PSComputerName : SYSTEM2
The specified network resource or device is no longer available.
[SYSTEM3] Connecting to remote server failed with the following error message : WinRM cannot process the request. The
following error occured while using Kerberos authentication: There are currently no logon servers available to service
the logon request.
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.
+ CategoryInfo : OpenError: (:) [], PSRemotingTransportException
+ FullyQualifiedErrorId : PSSessionStateBroken
+ PSComputerName : SYSTEM2
The network connection could not be found.
+ CategoryInfo : NotSpecified: (The network con...d not be found.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
+ PSComputerName : SYSTEM2
More help is available by typing NET HELPMSG 2250.
I’ve read this could be a “double-hop” issue (as detailed here), but I’m not sure how to edit the script to use CredSSP instead of Kerberos (or if this is even the problem).
Any ideas?
Posting this solution in case someone is still having an issue with a simple resolution to DoubleHop without using CredSSP.
Try this out:
https://www.powershellgallery.com/packages/Invoke-PSSession
It Invokes a PSSession, then Registers a PSSessionConfiguration with the Credentials that you provided. Basically providing the credentials for that DoubleHop
Then use Invoke-Command with that new PSSession. It should have the required privileges to do what you need.