sudo command to run in remote interactive session.
sudo : sudo: no tty present and no askpass program specified
+ CategoryInfo : NotSpecified: (sudo: no tty pr...ogram specified:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
Name Value
PSVersion 5.1.10032.0
PSEdition PowerShellCore
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 3.0.0.0
GitCommitId v0.6.0-392-ga5b5dc576b8006c0d0a83a5c538f382d9fa65dc6
CLRVersion
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
Hit this trying to implement a way to run the Azure Arc for Server agent (which requires sudo) over a PSRP session... It'd be really great to have this.
@SteveL-MSFT @TylerLeonhardt I see this issue has been open for many years now, probably because there is no easy fix. This is pretty much the only major limitation of pwsh on Linux to make it a viable shell alternative. Is this ticket the best place to discuss actively working towards making it happen?
I suppose one approach could be to make a special "pwsh-askpass" that could really just be "pwsh" launched in "--askpass" mode, where it would implement a regular askpass interactive prompt. The twist would be that we'd detect the parent pwsh shell, and use one of the PowerShell mechanisms for IPC, allowing us to somehow prompt interactively in the PowerShell client side.
Bonus points for properly delegating credentials over PSRP such that they never appear in logs anywhere (actually, that should be a requirement, but an intermediate solution would be acceptable). What do you think?
Conceptually that makes sense to me. Assuming a pwsh-askpass can connect to the parent pwsh where the actual remote host is, we'd maybe do something similar to what Get-Credential or Read-Host -AsSecureString does:

@TylerLeonhardt do you think this would require an improvement to the PowerShell remoting protocol? I know MS-PSRP treats credentials differently when transferring them to the remote system, maybe all we need is to use a secure string to benefit from that. What you suggested looks perfectly fine in terms of usability at least for a V1 (right now it is just plain unusable).
For a V2, I wonder if we couldn't go one step further and make it possible to override the client-side "askpass" implementation, to allow PowerShell clients to either show a GUI prompt, or even make a special module that would grab the username+password from one of the new secret management modules.
Anyway, back to just getting a V1 done for now. Here is my understanding:
I'm thinking that one could literally try making a PoC using a single PowerShell script called "pwsh-askpass" that you make executable. One quicky and dirty way to get started would be to make it output a hardcoded password just to see if the plumbing is done right at the "askpass" level. Once that is confirmed, we can work towards prompting the password for real.
As for attaching to the parent pwsh runspace, I don't know if it is feasible the way I described, but this presentation on PowerShell Remoting Internals does show a lot of interesting things that could be used as a starting point: https://www.youtube.com/watch?v=MyQGk29w-BM&t=780s
Yep this all sounds great to me. In PowerShell, you can get the parent process by doing:
(Get-Process $PID).Parent
We'd probably continue grabbing .Parent until we find another PowerShell... Then use Enter-PSHostProcess to enter said parent.
That's when it gets interesting. I don't know how to trigger that secure string prompt but it's possible that all you need to do is the Read-Host without having to go into another runspace...
.... This actually could work.
@awakecoding, @TylerLeonhardt thanks for reviving this. What is discussed here sounds possible. I too was thinking about using askpass to provide the password, but I am not very knowledgeable about it. I suspect the remoting protocol (PSRP) will have to be updated as mentioned above.
So I fiddled with this a tad...
❯❯❯ Enter-PSSession $windows
[tyleonha-desk1.redmond.corp.microsoft.com]: PS C:\Users\tyleonha\Documents> $rs = [runspacefactory]::CreateRunspace($Host)
[tyleonha-desk1.redmond.corp.microsoft.com]: PS C:\Users\tyleonha\Documents> $rs.Open()
[tyleonha-desk1.redmond.corp.microsoft.com]: PS C:\Users\tyleonha\Documents> $ps = [PowerShell]::Create($rs)
[tyleonha-desk1.redmond.corp.microsoft.com]: PS C:\Users\tyleonha\Documents> $ps.AddCommand("Read-Host").AddParameter("AsSecureString").Invoke()
WARNING: A script or application on the remote computer TYLEONHA-DESK1.REDMOND.CORP.MICROSOFT.COM is asking to read a line securely. Enter sensitive information, such as your credentials, only if you trust the remote computer and the application or script that is requesting it.
****
System.Security.SecureString
[tyleonha-desk1.redmond.corp.microsoft.com]: PS C:\Users\tyleonha\Documents>
Looks like as long as the _other_ runspace has the RemoteHost, then it might work...
$host.UI.ReadLineAsSecureString()
is also an option...
The outstanding questions I have are:
PSHost object we need?I did some further experimentation and discussed it with some of the people in #powershell-help. For the first step, which is to get sudo to use our own askpass program, it turns out that you need to do two things:
I do not yet know of a way to make it accept our own askpass program without adding the -A argument, but I would consider this a minor issue for now that we can solve later. The end goal is to make it without having to modify scripts calling sudo directly. As a matter of fact, I came up with a quick and dirty solution to work around it for now, using a fake "sudo" program that I added at the beginning of PATH such that it would get picked up instead of the real one.
I created a directory called "/yolo" and placed two simple scripts in there:
Here is what it looks like:
export PATH=/yolo:$PATH
wayk@pwsh-demo:~$ sudo whoami
root
wayk@pwsh-demo:~$ cat /yolo/sudo
#!/bin/sh
export SUDO_ASKPASS=/yolo/askpass
/usr/bin/sudo -A -n $@
wayk@pwsh-demo:~$ cat /yolo/askpass
#!/bin/sh
echo "password"
I consider the first part of the PoC (finding a way to inject our own askpass program that gets picked up by sudo) completed with the above, moving on to getting the askpass program to prompt inside the parent PowerShell runspace. We can come back to finding better, less hackish ways to achieve the same result afterwards.
Just to add some more info to the conversation here is a quick and dirty script that @SeeminglyScience wrote (slightly tweaked)
#!/usr/bin/env pwsh
# Parent is sudo, grandparent is the pwsh process
$parentPid = (Get-Process -Id $pid).Parent.Parent.Id
$ci = [Management.Automation.Runspaces.NamedPipeConnectionInfo]::new($parentPid)
$rs = $ps = $null
try {
$rs = [runspacefactory]::CreateRunspace($ci)
$rs.Open()
$ps = [powershell]::Create()
$ps.Runspace = $rs
$null = $ps.AddScript{
$rs = Get-Runspace 1
$remoteHost = $rs.GetType().GetProperty('Host', 60).GetValue($rs)
$remoteHost.UI.ReadLine()
}
return $ps.Invoke()
} finally {
if ($null -ne $ps) {
$ps.Dispose()
}
if ($null -ne $rs) {
$rs.Dispose()
}
}
Making that executable will allow sudo to prompt the user for the password and will work over a PSRemoting session. While this "works" it is not a workable solution because:
ReadLine() echos the input characters to the console exposing your passwordThe last 2 issues aren't the end of the world and should be easily fixed but the first 2 are problematic. I was hoping to utilise secure strings as PSRP has a really nice mechanism to exchange the values themselves. Unfortunately it seems like the secure string session key exchange in PSRP does not work on Linux so I can't call ReadLineAsSecureString.
Using secure strings across PSRemoting should be achievable cross platform as it doesn't rely on DPAPI but rather an ephemeral 16 byte key that's encrypted using an RSA public key. All these things should be achievable in OpenSSL so hopefully it could be implemented one day.
Just for further info on secure strings through PSRemoting this is the error I get when trying to copy one to a remote session
$cred = Get-Credential
Invoke-Command hostname -ScriptBlock { $using:cred }
OpenError:
$Error[0] | Select *
PSMessageDetails :
Exception : System.Management.Automation.Internal.PSCryptoException
at System.Management.Automation.Internal.PSCryptoNativeUtils.CryptAcquireContext(PSSafeCryptProvHandle& phProv,
String szContainer, String szProvider, UInt32 dwProvType, UInt32 dwFlags)
at System.Management.Automation.Internal.PSRSACryptoServiceProvider.GenerateKeyPair()
at System.Management.Automation.Internal.PSRemotingCryptoHelperClient.ExportLocalPublicKey(String& publicKeyAsString)
at System.Management.Automation.Remoting.ClientRemoteSessionImpl.StartKeyExchange()
TargetObject : server2019.domain.test
CategoryInfo : OpenError: (server2019.domain.test:String) [], PSCryptoException
FullyQualifiedErrorId : PSSessionStateBroken
ErrorDetails :
InvocationInfo :
ScriptStackTrace :
PipelineIterationInfo : {}
$error[0].Exception | Select *
TargetSite : Boolean CryptAcquireContext(System.Management.Automation.Internal.PSSafeCryptProvHandle ByRef, System.String, System.String,
UInt32, UInt32)
StackTrace : at System.Management.Automation.Internal.PSCryptoNativeUtils.CryptAcquireContext(PSSafeCryptProvHandle& phProv, String
szContainer, String szProvider, UInt32 dwProvType, UInt32 dwFlags)
at System.Management.Automation.Internal.PSRSACryptoServiceProvider.GenerateKeyPair()
at System.Management.Automation.Internal.PSRemotingCryptoHelperClient.ExportLocalPublicKey(String& publicKeyAsString)
at System.Management.Automation.Remoting.ClientRemoteSessionImpl.StartKeyExchange()
Message :
Data : {}
InnerException :
HelpLink :
Source : System.Management.Automation
HResult : -2146233088
Looks like https://github.com/PowerShell/PowerShell/pull/11185 has fixed the SecureString issue making it cross platform. I still need to test the latest preview to make sure but it definitely seems to be possible.
Thanks for looking into this. Yes, PowerShell remoting does now support passing SecureString objects over all platforms, but unfortunately was only added to 7.1+ versions.
I am not worried about prompting for sudo password over a remote session, that can be handled with remote host calls, and probably an update to the protocol (PSRP). My main concern was how to interface with sudo, and it looks like @awakecoding 'AskPass' is the mechanism to use. It would be nice if there was some sort of API hook, but the above PoC may be workable.

Anyone interested in prototyping this?
Most helpful comment
Just to add some more info to the conversation here is a quick and dirty script that @SeeminglyScience wrote (slightly tweaked)
Making that executable will allow
sudoto prompt the user for the password and will work over a PSRemoting session. While this "works" it is not a workable solution because:ReadLine()echos the input characters to the console exposing your passwordThe last 2 issues aren't the end of the world and should be easily fixed but the first 2 are problematic. I was hoping to utilise secure strings as PSRP has a really nice mechanism to exchange the values themselves. Unfortunately it seems like the secure string session key exchange in PSRP does not work on Linux so I can't call ReadLineAsSecureString.
Using secure strings across PSRemoting should be achievable cross platform as it doesn't rely on DPAPI but rather an ephemeral 16 byte key that's encrypted using an RSA public key. All these things should be achievable in OpenSSL so hopefully it could be implemented one day.
Just for further info on secure strings through PSRemoting this is the error I get when trying to copy one to a remote session