Azure / azure-powershell

Microsoft Azure PowerShell
Other
4.12k stars 3.76k forks source link

Connect-AzAccount - VSCode Remote-SSH - pwsh #24926

Open coolhome opened 1 month ago

coolhome commented 1 month ago

Description

When using Connect-AzAccount the following is produced:

WARNING: Interactive authentication is not supported in this session, please run cmdlet 'Connect-AzAccount -UseDeviceAuthentication'.

My setup is the following:

VSCode Remote-SSH will open xdg-open from the remote machine to my local machine browser

I was able to track down the issue to this function which would return false in my case because there is no DISPLAY, this is a SSH connection.

https://github.com/Azure/azure-powershell/blob/784c5e04022795d7c70b2e3a23bb2e57caf21c8f/src/Accounts/Accounts/Account/ConnectAzureRmAccount.cs#L510-L514

https://github.com/Azure/azure-powershell/blob/784c5e04022795d7c70b2e3a23bb2e57caf21c8f/src/Accounts/Authentication/Utilities/CommonUtilities.cs#L28-L36

I think these common utilities check could be remove and rely on Microsoft.Identity.Client exception throwing if its unable to open interactively.

https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/blob/f9253a67e69d4c34f30d26063006d6f788d71591/src/client/Microsoft.Identity.Client/Platforms/netcore/NetCorePlatformProxy.cs#L189-L228

A workaround is as simple as setting $env:DISPLAY = ":0.0" before running Connect-AzAccount. I just set this up in ~/.config/powershell/profile.ps1 so it is always loaded.

Issue script & Debug output

Connect-AzAccount                       
DEBUG: 1:59:29 PM - [ConfigManager] Got nothing from [DisplaySecretsWarning], Module = [], Cmdlet = []. Returning default value [False].
DEBUG: 1:59:29 PM - ConnectAzureRmAccountCommand begin processing with ParameterSet 'UserWithSubscriptionId'.
DEBUG: 1:59:29 PM - [ConfigManager] Got nothing from [DisplayBreakingChangeWarning], Module = [], Cmdlet = []. Returning default value [True].
DEBUG: 1:59:29 PM - [ConfigManager] Got nothing from [DefaultSubscriptionForLogin], Module = [], Cmdlet = []. Returning default value [].
WARNING: Interactive authentication is not supported in this session, please run cmdlet 'Connect-AzAccount -UseDeviceAuthentication'.
DEBUG: 1:59:29 PM - [ConfigManager] Got nothing from [DisplayRegionIdentified], Module = [], Cmdlet = []. Returning default value [True].
DEBUG: 1:59:29 PM - [ConfigManager] Got nothing from [CheckForUpgrade], Module = [], Cmdlet = []. Returning default value [True].
DEBUG: AzureQoSEvent:  Module: Az.Accounts:2.19.0; CommandName: Connect-AzAccount; PSVersion: 7.4.2; IsSuccess: True; Duration: 00:00:00.0037181
DEBUG: 1:59:29 PM - [ConfigManager] Got nothing from [EnableDataCollection], Module = [], Cmdlet = []. Returning default value [True].
DEBUG: 1:59:29 PM - ConnectAzureRmAccountCommand end processing.

Environment data

Name                           Value
----                           -----
PSVersion                      7.4.2
PSEdition                      Core
GitCommitId                    7.4.2
OS                             Red Hat Enterprise Linux 9.2 (Plow)
Platform                       Unix
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Module versions

ModuleType Version    PreRelease Name                                ExportedCommands
---------- -------    ---------- ----                                ----------------
Script     2.19.0                Az.Accounts                         {Add-AzEnvironment, Clear-AzConfig, Clear-AzContext, Clear-AzDefault…}

Error output

Technically no error was produced, just a warning and exits.
coolhome commented 1 month ago

While this change would unlocks part of the problem for VSCode Remote-SSH there is still an issue where the local forwarding port 8400 just hangs. I think its because the VSCode Azure Account locally is running on port 8400, and VSCode Remote does not know what local ports are used. Azure CLI / python identity library has some code to make sure the port does not conflict.

I think this would need to be different based on context. https://github.com/Azure/azure-powershell/blob/784c5e04022795d7c70b2e3a23bb2e57caf21c8f/src/Accounts/Authenticators/InteractiveUserAuthenticator.cs#L81-L85

coolhome commented 1 month ago

When it comes to conflicting local ports possibly from another Connect-AzAccount, then this is a related issue: https://github.com/Azure/azure-powershell/issues/23711

az login lets the system choose an available port which is probably less likely to collide.

--

When it comes to the request hanging, I think it's because on the MSAL is listening on port 8400 on TCP6 only.

tcp        0      0 127.0.0.1:39075         0.0.0.0:*               LISTEN      2212482/code-dc96b8 
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1013/sshd: /usr/sbi 
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      1/systemd           
tcp6       0      0 :::22                   :::*                    LISTEN      1013/sshd: /usr/sbi 
tcp6       0      0 :::111                  :::*                    LISTEN      1/systemd           
tcp6       0      0 ::1:8400                :::*                    LISTEN      2212716/pwsh

To mitigate locally setting this will force IPv4.

export DOTNET_SYSTEM_NET_DISABLEIPV6=true
pwsh

The localhost webserver is using hostname, which binds to ipv6 on my system. The solution is likely to support Ipv6 forwarding in vscode remote-ssh - https://github.com/microsoft/vscode-remote-release/issues/7029 or change the redirect uri to use 0.0.0.0 which is what az login is doing.

$server =[System.Net.HttpListener]::new()
$server.Prefixes.Add("http://localhost:8400/"
$server.Start()

# tcp6       0      0 ::1:8400                :::*                    LISTEN      2270420/pwsh

// Obviously this is expected to IPv4
$server =[System.Net.HttpListener]::new()
$server.Prefixes.Add("http://*:8400/"
$server.Start()

# tcp        0      0 0.0.0.0:8400            0.0.0.0:*               LISTEN      2270420/pwsh

// Obviously this is expected to IPv4
$server =[System.Net.HttpListener]::new()
$server.Prefixes.Add("http://127.0.0.1:8400/"
$server.Start()

# tcp        0      0 127.0.0.1:8400          0.0.0.0:*               LISTEN      2270420/pwsh

[System.Net.Dns]::GetHostByName("localhost")

HostName  Aliases AddressList
--------  ------- -----------
localhost {}      {::1, 127.0.0.1}

az login

# tcp        0      0 0.0.0.0:36957           0.0.0.0:*               LISTEN      2281151/python3.9   

#