SSH remoting cmdlet parameter set changes based on RFC 0010 (#2710)

* RFC 0010 SSH remoting cmdlet updates.

* Tweaks to SSH remoting cmdlets

* SSHTransport parameter is now optional instead of mandatory.  Aded fix for CoreCLR entry point when hosted in SSH as a subsystem.

* Added tests

* Code review feedback

* Code review comment changes

* Making SSHTransport switch parameter mandatory because otherwise existing Invoke-Command parameter set

* The new SSH parameter set was causing legacy positional based parameters to no longer work. This fix separates the SSH parameter sets from the existing WinRM parameter sets.

* Fixed region name spelling error.
This commit is contained in:
Paul Higinbotham
2016-12-02 14:01:08 -08:00
committed by Mike Richmond
parent 19a0d993e7
commit d2bf6294ab
11 changed files with 441 additions and 61 deletions
@@ -240,6 +240,13 @@ namespace Microsoft.PowerShell
throw hostException;
}
#if !CORECLR
// The default font face used for Powershell Console is Lucida Console.
// However certain CJK locales dont support Lucida Console font. Hence for such
// locales the console font is updated to Raster dynamically.
ConsoleControl.UpdateLocaleSpecificFont();
#endif
s_theConsoleHost.BindBreakHandler();
PSHost.IsStdOutputRedirected = Console.IsOutputRedirected;
@@ -82,17 +82,6 @@ namespace Microsoft.PowerShell
throw PSTraceSource.NewArgumentNullException("args");
}
// The default font face used for Powershell Console is Lucida Console.
// However certain CJK locales dont support Lucida Console font. Hence for such
// locales the console font is updated to Raster dynamically.
// For NanoServer:
// 1. There is no GetCurrentConsoleFontEx / SetCurrentConsoleFontEx on NanoServer;
// 2. We don't handle CJK locales on NanoServer due to lack of win32 API supports on NanoServer.
#if !CORECLR
ConsoleControl.UpdateLocaleSpecificFont();
#endif
return ConsoleHost.Start(configuration, bannerText, helpText, preStartWarning, args);
}
}
@@ -3,6 +3,7 @@ Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
@@ -387,7 +388,9 @@ namespace Microsoft.PowerShell.Commands
[Parameter(ParameterSetName = InvokeCommandCommand.FilePathVMNameParameterSet)]
[Parameter(ParameterSetName = InvokeCommandCommand.FilePathContainerIdParameterSet)]
[Parameter(ParameterSetName = InvokeCommandCommand.SSHHostParameterSet)]
[Parameter(ParameterSetName = InvokeCommandCommand.SSHHostHashParameterSet)]
[Parameter(ParameterSetName = InvokeCommandCommand.FilePathSSHHostParameterSet)]
[Parameter(ParameterSetName = InvokeCommandCommand.FilePathSSHHostHashParameterSet)]
public SwitchParameter AsJob
{
get
@@ -446,7 +449,9 @@ namespace Microsoft.PowerShell.Commands
[Parameter(ParameterSetName = InvokeCommandCommand.FilePathVMNameParameterSet)]
[Parameter(ParameterSetName = InvokeCommandCommand.FilePathContainerIdParameterSet)]
[Parameter(ParameterSetName = InvokeCommandCommand.SSHHostParameterSet)]
[Parameter(ParameterSetName = InvokeCommandCommand.SSHHostHashParameterSet)]
[Parameter(ParameterSetName = InvokeCommandCommand.FilePathSSHHostParameterSet)]
[Parameter(ParameterSetName = InvokeCommandCommand.FilePathSSHHostHashParameterSet)]
[Alias("HCN")]
public SwitchParameter HideComputerName
{
@@ -509,9 +514,10 @@ namespace Microsoft.PowerShell.Commands
[Parameter(Position = 1,
Mandatory = true,
ParameterSetName = InvokeCommandCommand.ContainerIdParameterSet)]
[Parameter(Position = 1,
Mandatory = true,
[Parameter(Mandatory = true,
ParameterSetName = InvokeCommandCommand.SSHHostParameterSet)]
[Parameter(Mandatory = true,
ParameterSetName = InvokeCommandCommand.SSHHostHashParameterSet)]
[ValidateNotNull]
[Alias("Command")]
public override ScriptBlock ScriptBlock
@@ -555,9 +561,10 @@ namespace Microsoft.PowerShell.Commands
[Parameter(Position = 1,
Mandatory = true,
ParameterSetName = FilePathContainerIdParameterSet)]
[Parameter(Position = 1,
Mandatory = true,
[Parameter(Mandatory = true,
ParameterSetName = FilePathSSHHostParameterSet)]
[Parameter(Mandatory = true,
ParameterSetName = FilePathSSHHostHashParameterSet)]
[ValidateNotNull]
[Alias("PSPath")]
public override string FilePath
@@ -662,28 +669,28 @@ namespace Microsoft.PowerShell.Commands
#region SSH Parameters
/// <summary>
/// Host Name
/// Host name for an SSH remote connection
/// </summary>
[Parameter(Mandatory = true,
ParameterSetName = InvokeCommandCommand.SSHHostParameterSet)]
[Parameter(Mandatory = true,
ParameterSetName = InvokeCommandCommand.FilePathSSHHostParameterSet)]
[ValidateNotNullOrEmpty()]
[Parameter(Position = 0, Mandatory = true, ParameterSetName = InvokeCommandCommand.SSHHostParameterSet)]
[Parameter(Position = 0, Mandatory = true, ParameterSetName = InvokeCommandCommand.FilePathSSHHostParameterSet)]
public override string HostName
public override string[] HostName
{
get { return base.HostName; }
set { base.HostName = value; }
}
/// <summary>
/// User Name
/// </summary>
[Parameter(Mandatory = true, ParameterSetName = InvokeCommandCommand.SSHHostParameterSet)]
[Parameter(Mandatory = true, ParameterSetName = InvokeCommandCommand.FilePathSSHHostParameterSet)]
[Parameter(ParameterSetName = InvokeCommandCommand.SSHHostParameterSet)]
[Parameter(ParameterSetName = InvokeCommandCommand.FilePathSSHHostParameterSet)]
[ValidateNotNullOrEmpty()]
public override string UserName
{
get { return base.UserName; }
set { base.UserName = value; }
}
@@ -693,13 +700,43 @@ namespace Microsoft.PowerShell.Commands
[Parameter(ParameterSetName = InvokeCommandCommand.SSHHostParameterSet)]
[Parameter(ParameterSetName = InvokeCommandCommand.FilePathSSHHostParameterSet)]
[ValidateNotNullOrEmpty()]
[Alias("IdentityFilePath")]
public override string KeyFilePath
{
get { return base.KeyFilePath; }
set { base.KeyFilePath = value; }
}
/// <summary>
/// This parameter specifies that SSH is used to establish the remote
/// connection and act as the remoting transport. By default WinRM is used
/// as the remoting transport. Using the SSH transport requires that SSH is
/// installed and PowerShell remoting is enabled on both client and remote machines.
/// </summary>
[Parameter(ParameterSetName = PSRemotingBaseCmdlet.SSHHostParameterSet)]
[Parameter(ParameterSetName = InvokeCommandCommand.FilePathSSHHostParameterSet)]
[ValidateSet("true")]
public override SwitchParameter SSHTransport
{
get { return base.SSHTransport; }
set { base.SSHTransport = value; }
}
/// <summary>
/// Hashtable array containing SSH connection parameters for each remote target
/// ComputerName (Alias: HostName) (required)
/// UserName (optional)
/// KeyFilePath (Alias: IdentityFilePath) (optional)
/// </summary>
[Parameter(ParameterSetName = PSRemotingBaseCmdlet.SSHHostHashParameterSet, Mandatory = true)]
[Parameter(ParameterSetName = InvokeCommandCommand.FilePathSSHHostHashParameterSet, Mandatory = true)]
[ValidateNotNullOrEmpty()]
public override Hashtable[] SSHConnection
{
get;
set;
}
#endregion
#endregion Parameters
@@ -969,6 +1006,10 @@ namespace Microsoft.PowerShell.Commands
case InvokeCommandCommand.FilePathVMIdParameterSet:
case InvokeCommandCommand.FilePathVMNameParameterSet:
case InvokeCommandCommand.FilePathContainerIdParameterSet:
case InvokeCommandCommand.SSHHostParameterSet:
case InvokeCommandCommand.FilePathSSHHostParameterSet:
case InvokeCommandCommand.SSHHostHashParameterSet:
case InvokeCommandCommand.FilePathSSHHostHashParameterSet:
{
if (ResolvedComputerNames.Length != 0 && Operations.Count > 0)
{
@@ -982,18 +1023,6 @@ namespace Microsoft.PowerShell.Commands
}
break;
case InvokeCommandCommand.SSHHostParameterSet:
case InvokeCommandCommand.FilePathSSHHostParameterSet:
{
var job = new PSRemotingJob(new string[] { this.HostName }, Operations,
ScriptBlock.ToString(), ThrottleLimit, _name);
job.PSJobTypeName = RemoteJobType;
job.HideComputerName = _hideComputerName;
this.JobRepository.Add(job);
WriteObject(job);
}
break;
case InvokeCommandCommand.SessionParameterSet:
case InvokeCommandCommand.FilePathSessionParameterSet:
{
@@ -181,6 +181,11 @@ namespace Microsoft.PowerShell.Commands
/// </summary>
protected const string SSHHostParameterSet = "SSHHost";
/// <summary>
/// SSH host parmeter set supporting hash connection parameters
/// </summary>
protected const string SSHHostHashParameterSet = "SSHHostHashParam";
/// <summary>
/// runspace parameter set
/// </summary>
@@ -262,6 +267,16 @@ namespace Microsoft.PowerShell.Commands
#endregion
}
/// <summary>
/// Contains SSH connection information
/// </summary>
internal struct SSHConnection
{
public string ComputerName;
public string UserName;
public string KeyFilePath;
}
/// <summary>
/// Base class for any cmdlet which takes a -Session parameter
/// or a -ComputerName parameter (along with its other associated
@@ -273,6 +288,8 @@ namespace Microsoft.PowerShell.Commands
/// </summary>
public abstract partial class PSRemotingBaseCmdlet : PSRemotingCmdlet
{
#region Enums
/// <summary>
/// State of virtual machine. This is the same as VMState in
/// \vm\ux\powershell\objects\common\Types.cs
@@ -415,6 +432,8 @@ namespace Microsoft.PowerShell.Commands
FastSavingCritical,
}
#endregion
#region Tracer
//PSETWTracer tracer = PSETWTracer.GetETWTracer(PSKeyword.Runspace);
@@ -681,11 +700,12 @@ namespace Microsoft.PowerShell.Commands
#region SSHHostParameters
/// <summary>
/// SSH Target Host Name
/// Host name for an SSH remote connection.
/// </summary>
[Parameter(ParameterSetName = PSRemotingBaseCmdlet.SSHHostParameterSet, Mandatory = true)]
[Parameter(Position = 0, Mandatory = true,
ParameterSetName = PSRemotingBaseCmdlet.SSHHostParameterSet)]
[ValidateNotNullOrEmpty()]
public virtual string HostName
public virtual string[] HostName
{
get;
set;
@@ -694,7 +714,7 @@ namespace Microsoft.PowerShell.Commands
/// <summary>
/// SSH User Name
/// </summary>
[Parameter(ParameterSetName = PSRemotingBaseCmdlet.SSHHostParameterSet, Mandatory = true)]
[Parameter(ParameterSetName = PSRemotingBaseCmdlet.SSHHostParameterSet)]
[ValidateNotNullOrEmpty()]
public virtual string UserName
{
@@ -707,12 +727,41 @@ namespace Microsoft.PowerShell.Commands
/// </summary>
[Parameter(ParameterSetName = PSRemotingBaseCmdlet.SSHHostParameterSet)]
[ValidateNotNullOrEmpty()]
[Alias("IdentityFilePath")]
public virtual string KeyFilePath
{
get;
set;
}
/// <summary>
/// This parameter specifies that SSH is used to establish the remote
/// connection and act as the remoting transport. By default WinRM is used
/// as the remoting transport. Using the SSH transport requires that SSH is
/// installed and PowerShell remoting is enabled on both client and remote machines.
/// </summary>
[Parameter(ParameterSetName = PSRemotingBaseCmdlet.SSHHostParameterSet)]
[ValidateSet("true")]
public virtual SwitchParameter SSHTransport
{
get;
set;
}
/// <summary>
/// Hashtable array containing SSH connection parameters for each remote target
/// ComputerName (Alias: HostName) (required)
/// UserName (optional)
/// KeyFilePath (Alias: IdentityFilePath) (optional)
/// </summary>
[Parameter(ParameterSetName = PSRemotingBaseCmdlet.SSHHostHashParameterSet, Mandatory = true)]
[ValidateNotNullOrEmpty()]
public virtual Hashtable[] SSHConnection
{
get;
set;
}
#endregion
#endregion Properties
@@ -762,6 +811,86 @@ namespace Microsoft.PowerShell.Commands
#endregion
#region Internal Methods
#region SSH Connection Strings
private const string ComputerNameParameter = "ComputerName";
private const string HostNameAlias = "HostName";
private const string UserNameParameter = "UserName";
private const string KeyFilePathParameter = "KeyFilePath";
private const string IdentityFilePathAlias = "IdentityFilePath";
#endregion
/// <summary>
/// Parse the Connection parameter HashTable array.
/// </summary>
/// <returns>Array of SSHConnection objects</returns>
internal SSHConnection[] ParseSSHConnectionHashTable()
{
List<SSHConnection> connections = new List<SSHConnection>();
foreach (var item in this.SSHConnection)
{
if (item.ContainsKey(ComputerNameParameter) && item.ContainsKey(HostNameAlias))
{
throw new PSArgumentException(RemotingErrorIdStrings.SSHConnectionDuplicateHostName);
}
if (item.ContainsKey(KeyFilePathParameter) && item.ContainsKey(IdentityFilePathAlias))
{
throw new PSArgumentException(RemotingErrorIdStrings.SSHConnectionDuplicateKeyPath);
}
SSHConnection connectionInfo = new SSHConnection();
foreach (var key in item.Keys)
{
string paramName = key as string;
if (string.IsNullOrEmpty(paramName))
{
throw new PSArgumentException(RemotingErrorIdStrings.InvalidSSHConnectionParameter);
}
string paramValue = item[paramName] as string;
if (string.IsNullOrEmpty(paramValue))
{
throw new PSArgumentException(RemotingErrorIdStrings.InvalidSSHConnectionParameter);
}
if (paramName.Equals(ComputerNameParameter, StringComparison.OrdinalIgnoreCase) || paramName.Equals(HostNameAlias, StringComparison.OrdinalIgnoreCase))
{
var resolvedComputerName = ResolveComputerName(paramValue);
ValidateComputerName(new string[] { resolvedComputerName });
connectionInfo.ComputerName = resolvedComputerName;
}
else if (paramName.Equals(UserNameParameter, StringComparison.OrdinalIgnoreCase))
{
connectionInfo.UserName = paramValue;
}
else if (paramName.Equals(KeyFilePathParameter, StringComparison.OrdinalIgnoreCase) || paramName.Equals(IdentityFilePathAlias, StringComparison.OrdinalIgnoreCase))
{
connectionInfo.KeyFilePath = paramValue;
}
else
{
throw new PSArgumentException(
StringUtil.Format(RemotingErrorIdStrings.UnknownSSHConnectionParameter, paramName));
}
}
if (string.IsNullOrEmpty(connectionInfo.ComputerName))
{
throw new PSArgumentException(RemotingErrorIdStrings.MissingRequiredSSHParameter);
}
connections.Add(connectionInfo);
}
return connections.ToArray();
}
#endregion
#region Private Methods
/// <summary>
@@ -920,6 +1049,11 @@ namespace Microsoft.PowerShell.Commands
/// </summary>
protected const string FilePathSSHHostParameterSet = "FilePathSSHHost";
/// <summary>
/// SSH Host file path parameter set with HashTable connection parameter
/// </summary>
protected const string FilePathSSHHostHashParameterSet = "FilePathSSHHostHash";
#endregion
#region Parameters
@@ -1169,18 +1303,45 @@ namespace Microsoft.PowerShell.Commands
}// CreateHelpersForSpecifiedComputerNames
/// <summary>
/// Creates helper objects for host names for PSRP over SSH
/// Creates helper objects for SSH remoting computer names
/// remoting.
/// </summary>
protected void CreateHelpersForSpecifiedHostNames()
protected void CreateHelpersForSpecifiedSSHComputerNames()
{
var sshConnectionInfo = new SSHConnectionInfo(this.UserName, this.HostName, this.KeyFilePath);
var typeTable = TypeTable.LoadDefaultTypeFiles();
var remoteRunspace = RunspaceFactory.CreateRunspace(sshConnectionInfo, this.Host, typeTable) as RemoteRunspace;
var pipeline = CreatePipeline(remoteRunspace);
ValidateComputerName(ResolvedComputerNames);
var operation = new ExecutionCmdletHelperComputerName(remoteRunspace, pipeline);
Operations.Add(operation);
foreach (string computerName in ResolvedComputerNames)
{
var sshConnectionInfo = new SSHConnectionInfo(this.UserName, computerName, this.KeyFilePath);
var typeTable = TypeTable.LoadDefaultTypeFiles();
var remoteRunspace = RunspaceFactory.CreateRunspace(sshConnectionInfo, this.Host, typeTable) as RemoteRunspace;
var pipeline = CreatePipeline(remoteRunspace);
var operation = new ExecutionCmdletHelperComputerName(remoteRunspace, pipeline);
Operations.Add(operation);
}
}
/// <summary>
/// Creates helper objects for SSH remoting from HashTable parameters.
/// </summary>
protected void CreateHelpersForSpecifiedSSHHashComputerNames()
{
var sshConnections = ParseSSHConnectionHashTable();
var remoteRunspaces = new List<RemoteRunspace>();
foreach (var sshConnection in sshConnections)
{
var sshConnectionInfo = new SSHConnectionInfo(
sshConnection.UserName,
sshConnection.ComputerName,
sshConnection.KeyFilePath);
var typeTable = TypeTable.LoadDefaultTypeFiles();
var remoteRunspace = RunspaceFactory.CreateRunspace(sshConnectionInfo, this.Host, typeTable) as RemoteRunspace;
var pipeline = CreatePipeline(remoteRunspace);
var operation = new ExecutionCmdletHelperComputerName(remoteRunspace, pipeline);
Operations.Add(operation);
}
}
/// <summary>
@@ -1791,7 +1952,20 @@ namespace Microsoft.PowerShell.Commands
case PSExecutionCmdlet.SSHHostParameterSet:
case PSExecutionCmdlet.FilePathSSHHostParameterSet:
CreateHelpersForSpecifiedHostNames();
{
String[] resolvedComputerNames = null;
ResolveComputerNames(HostName, out resolvedComputerNames);
ResolvedComputerNames = resolvedComputerNames;
CreateHelpersForSpecifiedSSHComputerNames();
}
break;
case PSExecutionCmdlet.SSHHostHashParameterSet:
case PSExecutionCmdlet.FilePathSSHHostHashParameterSet:
{
CreateHelpersForSpecifiedSSHHashComputerNames();
}
break;
case PSExecutionCmdlet.FilePathSessionParameterSet:
@@ -13,7 +13,7 @@ using System.Management.Automation.Remoting;
using System.Management.Automation.Internal;
using System.Management.Automation.Runspaces;
using Dbg = System.Management.Automation.Diagnostics;
using System.Collections;
namespace Microsoft.PowerShell.Commands
{
@@ -44,6 +44,18 @@ namespace Microsoft.PowerShell.Commands
#region Parameters
#region SSH Parameter Set
/// <summary>
/// Host name for an SSH remote connection
/// </summary>
[Parameter(Position = 0, Mandatory = true, ValueFromPipeline = true,
ParameterSetName = PSRemotingBaseCmdlet.SSHHostParameterSet)]
[ValidateNotNullOrEmpty()]
public new string HostName { get; set; }
#endregion
/// <summary>
/// Computer name parameter.
/// </summary>
@@ -172,6 +184,18 @@ namespace Microsoft.PowerShell.Commands
ParameterSetName = EnterPSSessionCommand.VMNameParameterSet)]
public String ConfigurationName { get; set; }
#region Suppress PSRemotingBaseCmdlet SSH hash parameter set
/// <summary>
/// Suppress SSHConnection parameter set
/// </summary>
public override Hashtable[] SSHConnection
{
get { return null; }
}
#endregion
#endregion
#region Overrides
@@ -1246,7 +1270,7 @@ namespace Microsoft.PowerShell.Commands
/// </summary>
private RemoteRunspace GetRunspaceForSSHSession()
{
var sshConnectionInfo = new SSHConnectionInfo(this.UserName, this.HostName, this.KeyFilePath);
var sshConnectionInfo = new SSHConnectionInfo(this.UserName, ResolveComputerName(HostName), this.KeyFilePath);
var typeTable = TypeTable.LoadDefaultTypeFiles();
var remoteRunspace = RunspaceFactory.CreateRunspace(sshConnectionInfo, this.Host, typeTable) as RemoteRunspace;
remoteRunspace.Open();
@@ -10,6 +10,7 @@ using System.Management.Automation.Runspaces;
using System.Management.Automation.Security;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Collections;
namespace Microsoft.PowerShell.Commands
{
@@ -119,6 +120,8 @@ namespace Microsoft.PowerShell.Commands
}
}
#region Suppress PSRemotingBaseCmdlet parameters
// suppress all the parameters from PSRemotingBaseCmdlet
// which should not be part of Start-PSJob
@@ -152,6 +155,40 @@ namespace Microsoft.PowerShell.Commands
get { return false; }
}
/// <summary>
/// Suppress SSHTransport
/// </summary>
public override SwitchParameter SSHTransport
{
get { return false; }
}
/// <summary>
/// Suppress SSHConnection
/// </summary>
public override Hashtable[] SSHConnection
{
get { return null; }
}
/// <summary>
/// Suppress UserName
/// </summary>
public override string UserName
{
get { return null; }
}
/// <summary>
/// Suppress KeyFilePath
/// </summary>
public override string KeyFilePath
{
get { return null; }
}
#endregion
/// <summary>
/// Credential to use for this job
/// </summary>
@@ -244,6 +244,12 @@ namespace Microsoft.PowerShell.Commands
}
break;
case NewPSSessionCommand.SSHHostHashParameterSet:
{
remoteRunspaces = CreateRunspacesForSSHHostHashParameterSet();
}
break;
default:
{
Dbg.Assert(false, "Missing parameter set in switch statement");
@@ -1061,13 +1067,38 @@ namespace Microsoft.PowerShell.Commands
/// <returns></returns>
private List<RemoteRunspace> CreateRunspacesForSSHHostParameterSet()
{
// Resolve all the machine names
String[] resolvedComputerNames;
ResolveComputerNames(HostName, out resolvedComputerNames);
ValidateComputerName(resolvedComputerNames);
var remoteRunspaces = new List<RemoteRunspace>();
var sshConnectionInfo = new SSHConnectionInfo(
this.UserName,
this.HostName,
this.KeyFilePath);
var typeTable = TypeTable.LoadDefaultTypeFiles();
remoteRunspaces.Add(RunspaceFactory.CreateRunspace(sshConnectionInfo, this.Host, typeTable) as RemoteRunspace);
foreach (var computerName in resolvedComputerNames)
{
var sshConnectionInfo = new SSHConnectionInfo(
this.UserName,
computerName,
this.KeyFilePath);
var typeTable = TypeTable.LoadDefaultTypeFiles();
remoteRunspaces.Add(RunspaceFactory.CreateRunspace(sshConnectionInfo, this.Host, typeTable) as RemoteRunspace);
}
return remoteRunspaces;
}
private List<RemoteRunspace> CreateRunspacesForSSHHostHashParameterSet()
{
var sshConnections = ParseSSHConnectionHashTable();
var remoteRunspaces = new List<RemoteRunspace>();
foreach (var sshConnection in sshConnections)
{
var sshConnectionInfo = new SSHConnectionInfo(
sshConnection.UserName,
sshConnection.ComputerName,
sshConnection.KeyFilePath);
var typeTable = TypeTable.LoadDefaultTypeFiles();
remoteRunspaces.Add(RunspaceFactory.CreateRunspace(sshConnectionInfo, this.Host, typeTable) as RemoteRunspace);
}
return remoteRunspaces;
}
@@ -1873,7 +1873,6 @@ namespace System.Management.Automation.Runspaces
string computerName,
string keyFilePath)
{
if (userName == null) { throw new PSArgumentNullException("userName"); }
if (computerName == null) { throw new PSArgumentNullException("computerName"); }
this.UserName = userName;
@@ -1980,9 +1979,9 @@ namespace System.Management.Automation.Runspaces
// Extract an optional domain name if provided.
string domainName = null;
string userName = this.UserName;
string userName = this.UserName ?? GetCurrentUserName();
#if !UNIX
var parts = this.UserName.Split(Utils.Separators.Backslash);
var parts = userName.Split(Utils.Separators.Backslash);
if (parts.Length == 2)
{
domainName = parts[0];
@@ -2027,6 +2026,19 @@ namespace System.Management.Automation.Runspaces
#endregion
#region Private Methods
private string GetCurrentUserName()
{
#if UNIX
return System.Environment.GetEnvironmentVariable("USER") ?? string.Empty;
#else
return System.Security.Principal.WindowsIdentity.GetCurrent().Name;
#endif
}
#endregion
#region SSH Process Creation
#if UNIX
@@ -1516,7 +1516,12 @@ namespace System.Management.Automation.Remoting.Client
while (true)
{
string error = reader.ReadLine();
if (!string.IsNullOrEmpty(error) && (error.IndexOf("WARNING:", StringComparison.OrdinalIgnoreCase) > -1))
if (string.IsNullOrEmpty(error))
{
// Ignore blank error messages.
continue;
}
if (error.IndexOf("WARNING:", StringComparison.OrdinalIgnoreCase) > -1)
{
// Handle as interactive warning message.
Console.WriteLine(error);
@@ -1621,4 +1621,19 @@ All WinRM sessions connected to Windows PowerShell session configurations, such
<data name="SSHClientEndNoErrorMessage" xml:space="preserve">
<value>The SSH client session has ended with no error message.</value>
</data>
<data name="MissingRequiredSSHParameter" xml:space="preserve">
<value>The provided SSHConnection hashtable is missing the required ComputerName or HostName parameter.</value>
</data>
<data name="InvalidSSHConnectionParameter" xml:space="preserve">
<value>The provided SSHConnection hashtable parameter name or element is null or empty.</value>
</data>
<data name="UnknownSSHConnectionParameter" xml:space="preserve">
<value>The provided SSHConnection hashtable parameter {0} is not supported.</value>
</data>
<data name="SSHConnectionDuplicateHostName" xml:space="preserve">
<value>The provided SSHConnection hashtable contains both a ComputerName and HostName parameter. Only one can be specified.</value>
</data>
<data name="SSHConnectionDuplicateKeyPath" xml:space="preserve">
<value>The provided SSHConnection hashtable contains both a KeyFilePath and IdentityFilePath parameter. Only one can be specified.</value>
</data>
</root>
@@ -0,0 +1,57 @@
##
## SSH Remoting cmdlet tests
##
Describe "SSHTransport switch parameter value" -Tags 'Feature' {
BeforeAll {
$TestCasesSSHTransport = @(
@{scriptBlock = {New-PSSession -HostName localhost -UserName UserA -SSHTransport:$false}; testName = 'New-PSSession SSHTransport parameter cannot have false value'}
@{scriptBlock = {Enter-PSSession -HostName localhost -UserName UserA -SSHTransport:$false}; testName = 'Enter-PSSession SSHTransport parameter cannot have false value'}
@{scriptBlock = {Invoke-Command -ScriptBlock {"Hello"} -HostName localhost -UserName UserA -SSHTransport:$false}; testName = 'Invoke-Command SSHTransport parameter cannot have false value'}
)
}
It "<testName>" -TestCases $TestCasesSSHTransport {
param($scriptBlock)
try
{
& $scriptBlock
throw "Parameter argument should not be valid"
}
catch
{
$_.FullyQualifiedErrorId | Should Match "ParameterArgumentValidationError"
}
}
}
Describe "SSHConnection parameter hashtable error conditions" -Tags 'Feature' {
BeforeAll {
$TestCasesSSHConnection = @(
@{scriptBlock = {New-PSSession -SSHConnection @{ ComputerName = "localhost"; "" = "noParameter" }}; testName = 'SSHConnection parameter hashtable cannot contain empty parameter names'}
@{scriptBlock = {New-PSSession -SSHConnection @{ HostName = $null }}; testName = 'SSHConnection parameter hashtable cannot contain empty parameter values'}
@{scriptBlock = {New-PSSession -SSHConnection @{ ComputerName = "localhost"; UnknownParameter = "Hello" }}; testName = 'SSHConnection parameter hashtable cannot contain unknown parameter names'}
@{scriptBlock = {New-PSSession -SSHConnection @{ UserName = "UserName"; KeyFilePath = "path" }}; testName = 'SSHConnection parmeter hashtable must contain the ComputerName parameter'}
@{scriptBlock = {New-PSSession -SSHConnection @{ ComputerName = "computerA"; hostname = "computerB" }}; testName = 'SSHConnection parameter hashtable cannot contain both ComputerName and HostName parameters' }
@{scriptBlock = {New-PSSession -SSHConnection @{ keyfilepath = "pathA"; IdentityFilePath = "pathB" }}; testName = 'SSHConnection parameter hashtable cannot contain both KeyFilePath and IdentityFilePath parameters' }
)
}
It "<testName>" -TestCases $TestCasesSSHConnection {
param ($scriptBlock)
try
{
& $scriptBlock
throw "Parameter set should not be valid"
}
catch
{
$_.FullyQualifiedErrorId | Should Match "Argument,Microsoft.PowerShell.Commands.NewPSSessionCommand"
}
}
}