Skip to content

Commit de9f80d

Browse files
authored
[Account]Redirect DeviceCode Info from warning stream to information stream in Connect-AzAccount (#23665)
* Redirct DeviceCode Info from warning stream to information stream * add change log * writehighlightedinformation * Formmat device code login message * rename writeinformation * polish code
1 parent 53b7258 commit de9f80d

File tree

5 files changed

+79
-10
lines changed

5 files changed

+79
-10
lines changed

src/Accounts/Accounts/Account/ConnectAzureRmAccount.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
using Microsoft.WindowsAzure.Commands.Utilities.Common;
4646
using Microsoft.Azure.PowerShell.Common.Share.Survey;
4747
using Microsoft.Azure.Commands.Profile.Utilities;
48+
using System.Management.Automation.Runspaces;
4849

4950
namespace Microsoft.Azure.Commands.Profile
5051
{
@@ -249,6 +250,7 @@ protected override IAzureContext DefaultContext
249250
protected override void BeginProcessing()
250251
{
251252
base.BeginProcessing();
253+
ValidateActionRequiredMessageCanBePresented();
252254
if (AzureEnvironment.PublicEnvironments.ContainsKey(EnvironmentName.AzureCloud))
253255
{
254256
_environment = AzureEnvironment.PublicEnvironments[EnvironmentName.AzureCloud];
@@ -273,11 +275,19 @@ protected override void BeginProcessing()
273275

274276
_writeWarningEvent -= WriteWarningSender;
275277
_writeWarningEvent += WriteWarningSender;
278+
_writeInformationEvent -= WriteInformationSender;
279+
_writeInformationEvent += WriteInformationSender;
280+
276281
// store the original write warning handler, register a thread safe one
277282
AzureSession.Instance.TryGetComponent(WriteWarningKey, out _originalWriteWarning);
278283
AzureSession.Instance.UnregisterComponent<EventHandler<StreamEventArgs>>(WriteWarningKey);
279284
AzureSession.Instance.RegisterComponent(WriteWarningKey, () => _writeWarningEvent);
280285

286+
// store the original write information handler, register a thread safe one
287+
AzureSession.Instance.TryGetComponent(WriteInformationKey, out _originalWriteInformation);
288+
AzureSession.Instance.UnregisterComponent<EventHandler<StreamEventArgs>>(WriteInformationKey);
289+
AzureSession.Instance.RegisterComponent(WriteInformationKey, () => _writeInformationEvent);
290+
281291
// todo: ideally cancellation token should be passed to authentication factory as a parameter
282292
// however AuthenticationFactory.Authenticate does not support it
283293
// so I store it in AzureSession.Instance as a global variable
@@ -289,11 +299,19 @@ protected override void BeginProcessing()
289299
private event EventHandler<StreamEventArgs> _writeWarningEvent;
290300
private event EventHandler<StreamEventArgs> _originalWriteWarning;
291301

302+
private event EventHandler<StreamEventArgs> _writeInformationEvent;
303+
private event EventHandler<StreamEventArgs> _originalWriteInformation;
304+
292305
private void WriteWarningSender(object sender, StreamEventArgs args)
293306
{
294307
_tasks.Enqueue(new Task(() => this.WriteWarning(args.Message)));
295308
}
296309

310+
private void WriteInformationSender(object sender, StreamEventArgs args)
311+
{
312+
_tasks.Enqueue(new Task(() => this.WriteInformation(args.Message)));
313+
}
314+
297315
protected override void StopProcessing()
298316
{
299317
if (AzureSession.Instance.TryGetComponent("LoginCancellationToken", out CancellationTokenSource cancellationTokenSource))
@@ -562,6 +580,20 @@ public override void ExecuteCmdlet()
562580
}
563581
}
564582

583+
private void ValidateActionRequiredMessageCanBePresented()
584+
{
585+
if (UseDeviceAuthentication.IsPresent && IsWriteInformationIgnored())
586+
{
587+
throw new ActionPreferenceStopException(Resources.DoNotIgnoreInformationIfUserDeviceAuth);
588+
}
589+
}
590+
591+
private bool IsWriteInformationIgnored()
592+
{
593+
return !MyInvocation.BoundParameters.ContainsKey("InformationAction") && ActionPreference.Ignore.ToString().Equals(SessionState?.PSVariable?.GetValue("InformationPreference", ActionPreference.SilentlyContinue)?.ToString() ?? "") ||
594+
MyInvocation.BoundParameters.TryGetValue("InformationAction", out var value) && ActionPreference.Ignore.ToString().Equals(value?.ToString() ?? "", StringComparison.InvariantCultureIgnoreCase);
595+
}
596+
565597
private string PreProcessAuthScope()
566598
{
567599
string mappedScope = AuthScope;
@@ -774,6 +806,9 @@ protected override void EndProcessing()
774806
// unregister the thread-safe write warning, because it won't work out of this cmdlet
775807
AzureSession.Instance.UnregisterComponent<EventHandler<StreamEventArgs>>(WriteWarningKey);
776808
AzureSession.Instance.RegisterComponent(WriteWarningKey, () => _originalWriteWarning);
809+
// unregister the thread-safe write information, because it won't work out of this cmdlet
810+
AzureSession.Instance.UnregisterComponent<EventHandler<StreamEventArgs>>(WriteInformationKey);
811+
AzureSession.Instance.RegisterComponent(WriteInformationKey, () => _originalWriteInformation);
777812
}
778813
}
779814
}

src/Accounts/Accounts/ChangeLog.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,15 @@
1919
-->
2020

2121
## Upcoming Release
22+
* Redirected device code login messages from warning stream to information stream if use device authentication in `Connect-AzAccount`.
23+
* Adjusted output format to be more user-friendly for `Get-AzContext/Tenant/Subscription` and `Invoke-AzRestMethod`, including
24+
- ordering and grouping output items to make items easy to find.
25+
- re-prioritizing positions for output properties to highlight valuable properties.
2226
* Upgraded the reference of Azure PowerShell Common to 1.3.90-preview.
2327
* Upgraded Azure.Identity to 1.10.3 [#23018].
2428
- Renamed token cache from `msal.cache` to `msal.cache.cae` or `masl.cache.nocae`.
2529
* Enabled Continue Access Evaluation (CAE) for all Service Principals login methods.
2630
* Supported signing in with Microsoft Account (MSA) via Web Account Manager (WAM). Enable it by `Set-AzConfig -EnableLoginByWam $true`.
27-
* Adjusted output format to be more user-friendly for `Get-AzContext/Tenant/Subscription` and `Invoke-AzRestMethod`.
2831
* Fixed the multiple `x-ms-unique-id` values issue.
2932

3033
## Version 2.15.0

src/Accounts/Accounts/Properties/Resources.Designer.cs

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Accounts/Accounts/Properties/Resources.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,4 +595,7 @@
595595
<data name="ProfileCredentialsWriteWarning" xml:space="preserve">
596596
<value>Personally identifiable information and confidential data may be written to the file located at '{0}'. Please ensure that appropriate access controls are assigned to the saved file.</value>
597597
</data>
598+
<data name="DoNotIgnoreInformationIfUserDeviceAuth" xml:space="preserve">
599+
<value>Please do not set InformationAction or $InformationPreference to Ignore if you want to use device code authentication.</value>
600+
</data>
598601
</root>

src/Accounts/Authenticators/DeviceCodeAuthenticator.cs

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,6 @@
1212
// limitations under the License.
1313
// ----------------------------------------------------------------------------------
1414

15-
using System;
16-
using System.Threading;
17-
using System.Threading.Tasks;
18-
1915
using Azure.Core;
2016
using Azure.Identity;
2117

@@ -24,6 +20,12 @@
2420
using Microsoft.Azure.Commands.Common.Authentication;
2521
using Microsoft.Azure.Commands.Common.Authentication.Abstractions;
2622
using Microsoft.Azure.Commands.ResourceManager.Common;
23+
using Microsoft.WindowsAzure.Commands.Common;
24+
25+
using System;
26+
using System.Text;
27+
using System.Threading;
28+
using System.Threading.Tasks;
2729

2830
namespace Microsoft.Azure.PowerShell.Authenticators
2931
{
@@ -64,7 +66,7 @@ public override Task<IAccessToken> Authenticate(AuthenticationParameters paramet
6466

6567
private Task DeviceCodeFunc(DeviceCodeInfo info, CancellationToken cancellation)
6668
{
67-
WriteWarning(info.Message);
69+
WriteInfomartion(info.Message, info.UserCode);
6870
return Task.CompletedTask;
6971
}
7072

@@ -73,12 +75,29 @@ public override bool CanAuthenticate(AuthenticationParameters parameters)
7375
return (parameters as DeviceCodeParameters) != null;
7476
}
7577

76-
private void WriteWarning(string message)
78+
79+
private void WriteInfomartion(string message, string userCode)
7780
{
78-
EventHandler<StreamEventArgs> writeWarningEvent;
79-
if (AzureSession.Instance.TryGetComponent(AzureRMCmdlet.WriteWarningKey, out writeWarningEvent))
81+
82+
var loginInfo = new StringBuilder();
83+
string LoginToAzurePhrase = $"{PSStyle.Bold}{PSStyle.BackgroundColor.Blue}[Login to Azure]{PSStyle.Reset} ";
84+
loginInfo.Append(LoginToAzurePhrase);
85+
86+
if (!string.IsNullOrEmpty(userCode))
87+
{
88+
var formattedUserCode = $"{PSStyle.Underline}{userCode}{PSStyle.Reset}";
89+
var formattedMessage = message.Replace(userCode, formattedUserCode);
90+
loginInfo.Append(formattedMessage);
91+
}
92+
else
93+
{
94+
loginInfo.Append(message);
95+
}
96+
97+
EventHandler<StreamEventArgs> writeInforamtionEvent;
98+
if (AzureSession.Instance.TryGetComponent(AzureRMCmdlet.WriteInformationKey, out writeInforamtionEvent))
8099
{
81-
writeWarningEvent(this, new StreamEventArgs() { Message = message });
100+
writeInforamtionEvent(this, new StreamEventArgs() { Message = loginInfo.ToString() });
82101
}
83102
}
84103
}

0 commit comments

Comments
 (0)