From bdd27ae6696a2a4345e8ae26a2223c090eb4a43c Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Wed, 4 Apr 2018 20:46:40 +0900 Subject: [PATCH 1/2] support user@host:port syntax for SSH Transport --- .../remoting/commands/PSRemotingCmdlet.cs | 42 ++++++++++++++++--- .../remoting/commands/newrunspacecommand.cs | 10 +++-- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs b/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs index b7fa3ffd81c..3fce8cb965b 100644 --- a/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs +++ b/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs @@ -825,6 +825,30 @@ internal static void ValidateSpecifiedAuthentication(PSCredential credential, st #endregion + /// + /// Parse a hostname used with SSH Transport to get embedded + /// username and/or port. + /// + /// host name to parse + /// resolved target host + /// resolved target user name + /// resolved target port + protected void ParseSshHostName(string hostname, out string host, out string userName, out int port) + { + var uri = new System.Uri("ssh://" + hostname); + host = uri.Host; + userName = uri.UserInfo; + if (userName == String.Empty) + { + userName = this.UserName; + } + port = uri.Port; + if (port == -1) + { + port = this.Port; + } + } + /// /// Parse the Connection parameter HashTable array. /// @@ -856,8 +880,16 @@ internal SSHConnection[] ParseSSHConnectionHashTable() if (paramName.Equals(ComputerNameParameter, StringComparison.OrdinalIgnoreCase) || paramName.Equals(HostNameAlias, StringComparison.OrdinalIgnoreCase)) { var resolvedComputerName = ResolveComputerName(GetSSHConnectionStringParameter(item[paramName])); - ValidateComputerName(new string[] { resolvedComputerName }); - connectionInfo.ComputerName = resolvedComputerName; + ParseSshHostName(resolvedComputerName, out string host, out string userName, out int port); + connectionInfo.ComputerName = host; + if (userName != String.Empty) + { + connectionInfo.UserName = userName; + } + if (port != -1) + { + connectionInfo.Port = port; + } } else if (paramName.Equals(UserNameParameter, StringComparison.OrdinalIgnoreCase)) { @@ -1337,11 +1369,11 @@ protected virtual void CreateHelpersForSpecifiedComputerNames() /// protected void CreateHelpersForSpecifiedSSHComputerNames() { - ValidateComputerName(ResolvedComputerNames); - foreach (string computerName in ResolvedComputerNames) { - var sshConnectionInfo = new SSHConnectionInfo(this.UserName, computerName, this.KeyFilePath, this.Port); + ParseSshHostName(computerName, out string host, out string userName, out int port); + + var sshConnectionInfo = new SSHConnectionInfo(userName, host, this.KeyFilePath, port); var typeTable = TypeTable.LoadDefaultTypeFiles(); var remoteRunspace = RunspaceFactory.CreateRunspace(sshConnectionInfo, this.Host, typeTable) as RemoteRunspace; var pipeline = CreatePipeline(remoteRunspace); diff --git a/src/System.Management.Automation/engine/remoting/commands/newrunspacecommand.cs b/src/System.Management.Automation/engine/remoting/commands/newrunspacecommand.cs index 9cc14e2afa4..f5840c7ea9a 100644 --- a/src/System.Management.Automation/engine/remoting/commands/newrunspacecommand.cs +++ b/src/System.Management.Automation/engine/remoting/commands/newrunspacecommand.cs @@ -1067,18 +1067,20 @@ private List CreateRunspacesForSSHHostParameterSet() { // Resolve all the machine names String[] resolvedComputerNames; + ResolveComputerNames(HostName, out resolvedComputerNames); - ValidateComputerName(resolvedComputerNames); var remoteRunspaces = new List(); int index = 0; foreach (var computerName in resolvedComputerNames) { + ParseSshHostName(computerName, out string host, out string userName, out int port); + var sshConnectionInfo = new SSHConnectionInfo( - this.UserName, - computerName, + userName, + host, this.KeyFilePath, - this.Port); + port); var typeTable = TypeTable.LoadDefaultTypeFiles(); string rsName = GetRunspaceName(index, out int rsIdUnused); index++; From 1c6af72b19a03318ef381329607b7e1b9545e544 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Thu, 5 Apr 2018 08:46:04 +0900 Subject: [PATCH 2/2] address PR feedback --- .../remoting/commands/PSRemotingCmdlet.cs | 28 +++++++++++++------ .../remoting/commands/PushRunspaceCommand.cs | 3 +- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs b/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs index 3fce8cb965b..9ba8e7186b8 100644 --- a/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs +++ b/src/System.Management.Automation/engine/remoting/commands/PSRemotingCmdlet.cs @@ -835,17 +835,29 @@ internal static void ValidateSpecifiedAuthentication(PSCredential credential, st /// resolved target port protected void ParseSshHostName(string hostname, out string host, out string userName, out int port) { - var uri = new System.Uri("ssh://" + hostname); - host = uri.Host; - userName = uri.UserInfo; - if (userName == String.Empty) + host = hostname; + userName = this.UserName; + port = this.Port; + try { - userName = this.UserName; + Uri uri = new System.Uri("ssh://" + hostname); + host = ResolveComputerName(uri.Host); + ValidateComputerName(new string[]{host}); + if (uri.UserInfo != String.Empty) + { + userName = uri.UserInfo; + } + if (uri.Port != -1) + { + port = uri.Port; + } } - port = uri.Port; - if (port == -1) + catch (UriFormatException) { - port = this.Port; + ThrowTerminatingError(new ErrorRecord( + new ArgumentException(PSRemotingErrorInvariants.FormatResourceString( + RemotingErrorIdStrings.InvalidComputerName)), "PSSessionInvalidComputerName", + ErrorCategory.InvalidArgument, hostname)); } } diff --git a/src/System.Management.Automation/engine/remoting/commands/PushRunspaceCommand.cs b/src/System.Management.Automation/engine/remoting/commands/PushRunspaceCommand.cs index 4014863e5d3..6e26b815ec9 100644 --- a/src/System.Management.Automation/engine/remoting/commands/PushRunspaceCommand.cs +++ b/src/System.Management.Automation/engine/remoting/commands/PushRunspaceCommand.cs @@ -1281,7 +1281,8 @@ private RemoteRunspace GetRunspaceForContainerSession() /// private RemoteRunspace GetRunspaceForSSHSession() { - var sshConnectionInfo = new SSHConnectionInfo(this.UserName, ResolveComputerName(HostName), this.KeyFilePath, this.Port); + ParseSshHostName(HostName, out string host, out string userName, out int port); + var sshConnectionInfo = new SSHConnectionInfo(userName, host, this.KeyFilePath, port); var typeTable = TypeTable.LoadDefaultTypeFiles(); // Use the class _tempRunspace field while the runspace is being opened so that StopProcessing can be handled at that time.