diff --git a/src/Accounts/Accounts/Account/ConnectAzureRmAccount.cs b/src/Accounts/Accounts/Account/ConnectAzureRmAccount.cs index 20de1ac242cd..f8f472e8174d 100644 --- a/src/Accounts/Accounts/Account/ConnectAzureRmAccount.cs +++ b/src/Accounts/Accounts/Account/ConnectAzureRmAccount.cs @@ -431,7 +431,11 @@ public override void ExecuteCmdlet() } else { - WriteWarning(Resources.SuggestToUseDeviceCodeAuth); + if (ParameterSetName == UserParameterSet && UseDeviceAuthentication == false) + { + //Display only if user is using Interactive auth + WriteWarning(Resources.SuggestToUseDeviceCodeAuth); + } WriteDebug(ex.ToString()); throw; } @@ -489,23 +493,24 @@ private void SetContextWithOverwritePrompt(Action setContextAction(prof, client, name)); + if (!CheckForExistingContext(profile, name) + || Force.IsPresent + || ShouldContinue(string.Format(Resources.ReplaceContextQuery, name), + string.Format(Resources.ReplaceContextCaption, name))) + { + ModifyContext((prof, client) => setContextAction(prof, client, name)); + } } - } finally { - if(profile != null && originalShouldRefreshContextsFromCache.HasValue) + if (profile != null && originalShouldRefreshContextsFromCache.HasValue) { profile.ShouldRefreshContextsFromCache = originalShouldRefreshContextsFromCache.Value; } } } + //This method may throw exception because of permission issue, exception should be handled from caller private static IAzureContextContainer GetAzureContextContainer() { var provider = new ProtectedProfileProvider(); @@ -522,7 +527,7 @@ public void OnImport() { #endif AzureSessionInitializer.InitializeAzureSession(); - AzureSessionInitializer.MigrateAdalCache(AzureSession.Instance, GetAzureContextContainer); + AzureSessionInitializer.MigrateAdalCache(AzureSession.Instance, GetAzureContextContainer, WriteInitializationWarnings); #if DEBUG if (!TestMockSupport.RunningMocked) { @@ -540,11 +545,21 @@ public void OnImport() autoSaveEnabled = localAutosave; } - if (autoSaveEnabled && !SharedTokenCacheProvider.SupportCachePersistence(out string message)) + try + { + if (autoSaveEnabled && !SharedTokenCacheProvider.SupportCachePersistence(out string message)) + { + // If token cache persistence is not supported, fall back to plain text persistence, and print a warning + // We cannot just throw an exception here because this is called when importing the module + WriteInitializationWarnings(Resources.TokenCacheEncryptionNotSupportedWithFallback); + } + } + catch(Exception ex) { - // If token cache persistence is not supported, fall back to plain text persistence, and print a warning - // We cannot just throw an exception here because this is called when importing the module - WriteInitializationWarnings(Resources.TokenCacheEncryptionNotSupportedWithFallback); + //Likely the exception is related permission, fall back context save mode to process + autoSaveEnabled = false; + AzureSession.Instance.ARMContextSaveMode = ContextSaveMode.Process; + WriteInitializationWarnings(Resources.FallbackContextSaveModeDueCacheCheckError.FormatInvariant(ex.Message)); } if(!InitializeProfileProvider(autoSaveEnabled)) diff --git a/src/Accounts/Accounts/ChangeLog.md b/src/Accounts/Accounts/ChangeLog.md index ff1c97a5d24e..57d4388cdded 100644 --- a/src/Accounts/Accounts/ChangeLog.md +++ b/src/Accounts/Accounts/ChangeLog.md @@ -18,6 +18,7 @@ - Additional information about change #1 --> ## Upcoming Release +* Fixed an issue that error happens if user profile path is inaccessible * Fixed an issue causing Write-Object error during Connect-AzAccount [#13419] * Added parameter "ContainerRegistryEndpointSuffix" to: `Add-AzEnvironment`, `Set-AzEnvironment` * Supported interrupting login by hitting CTRL+C diff --git a/src/Accounts/Accounts/Common/AzureContextModificationCmdlet.cs b/src/Accounts/Accounts/Common/AzureContextModificationCmdlet.cs index 6e5ebe00225e..599a4e7a0fb0 100644 --- a/src/Accounts/Accounts/Common/AzureContextModificationCmdlet.cs +++ b/src/Accounts/Accounts/Common/AzureContextModificationCmdlet.cs @@ -127,12 +127,9 @@ internal bool InitializeProfileProvider(bool useAutoSaveProfile = false) { ProtectedProfileProvider.InitializeResourceManagerProfile(); } - catch (SystemException e) + catch (Exception e) { - if (!(e is IOException) && !(e is UnauthorizedAccessException)) - { - throw e; - } + //Likely the exception is related to IO or permission, fallback to Process save mode WriteInitializationWarnings(string.Format(Resources.ProfileFileNotAccessible, e.Message)); ResourceManagerProfileProvider.InitializeResourceManagerProfile(true); } diff --git a/src/Accounts/Accounts/Properties/Resources.Designer.cs b/src/Accounts/Accounts/Properties/Resources.Designer.cs index 93dbc8ff3455..998663f21f28 100644 --- a/src/Accounts/Accounts/Properties/Resources.Designer.cs +++ b/src/Accounts/Accounts/Properties/Resources.Designer.cs @@ -510,6 +510,15 @@ internal static string ErrorRetrievingAutosaveSetting { } } + /// + /// Looks up a localized string similar to INITIALIZATION: Fallback context save mode to process because of error during checking token cache persistence: {0}.. + /// + internal static string FallbackContextSaveModeDueCacheCheckError { + get { + return ResourceManager.GetString("FallbackContextSaveModeDueCacheCheckError", resourceCulture); + } + } + /// /// Looks up a localized string similar to Cannot find file '{0}'. /// @@ -727,7 +736,7 @@ internal static string ProfileCurrentWrite { } /// - /// Looks up a localized string similar to Fail to access profile file and will try to use process ContextAutosaveSetting mode. Detailed error: '{0}'. + /// Looks up a localized string similar to INITIALIZATION: Fail to access profile file and will try to use process ContextAutosaveSetting mode. Detailed error: '{0}'. /// internal static string ProfileFileNotAccessible { get { @@ -1123,7 +1132,7 @@ internal static string TenantIdNotFound { } /// - /// Looks up a localized string similar to Token cache encryption is not supported in current environment and token cache will be fallen back as plain text.. + /// Looks up a localized string similar to INITIALIZATION: Token cache encryption is not supported in current environment and token cache will be fallen back as plain text.. /// internal static string TokenCacheEncryptionNotSupportedWithFallback { get { diff --git a/src/Accounts/Accounts/Properties/Resources.resx b/src/Accounts/Accounts/Properties/Resources.resx index 2f6c32be4740..b18d22752931 100644 --- a/src/Accounts/Accounts/Properties/Resources.resx +++ b/src/Accounts/Accounts/Properties/Resources.resx @@ -496,10 +496,10 @@ Context autosave is not supported in current environment. Please disable it using 'Disable-AzContextSave'. - Token cache encryption is not supported in current environment and token cache will be fallen back as plain text. + INITIALIZATION: Token cache encryption is not supported in current environment and token cache will be fallen back as plain text. - Fail to access profile file and will try to use process ContextAutosaveSetting mode. Detailed error: '{0}' + INITIALIZATION: Fail to access profile file and will try to use process ContextAutosaveSetting mode. Detailed error: '{0}' The Azure PowerShell team is listening, please let us know how we are doing: {0}. @@ -519,4 +519,7 @@ Please run 'Connect-AzAccount -DeviceCode' if browser is not supported in this session. + + INITIALIZATION: Fallback context save mode to process because of error during checking token cache persistence: {0}. + \ No newline at end of file diff --git a/src/Accounts/Authentication/AzureSessionInitializer.cs b/src/Accounts/Authentication/AzureSessionInitializer.cs index 3460f7416790..0d5ae62ef5ae 100644 --- a/src/Accounts/Authentication/AzureSessionInitializer.cs +++ b/src/Accounts/Authentication/AzureSessionInitializer.cs @@ -99,39 +99,46 @@ static bool MigrateSettings(IDataStore store, string oldProfileDirectory, string return false; } - public static void MigrateAdalCache(IAzureSession session, Func getContextContainer) + public static void MigrateAdalCache(IAzureSession session, Func getContextContainer, Action writeWarning) { - if (session.ARMContextSaveMode == ContextSaveMode.Process) + try { - // Don't attempt to migrate if context autosave is disabled - return; - } + if (session.ARMContextSaveMode == ContextSaveMode.Process) + { + // Don't attempt to migrate if context autosave is disabled + return; + } - var adalCachePath = Path.Combine(session.ProfileDirectory, "TokenCache.dat"); - var msalCachePath = Path.Combine(session.TokenCacheDirectory, "msal.cache"); - var store = session.DataStore; - if (!store.FileExists(adalCachePath) || store.FileExists(msalCachePath)) - { - // Return if - // (1) The ADAL cache doesn't exist (nothing to migrate), or - // (2) The MSAL cache does exist (don't override existing cache) - return; - } + var adalCachePath = Path.Combine(session.ProfileDirectory, "TokenCache.dat"); + var msalCachePath = Path.Combine(session.TokenCacheDirectory, "msal.cache"); + var store = session.DataStore; + if (!store.FileExists(adalCachePath) || store.FileExists(msalCachePath)) + { + // Return if + // (1) The ADAL cache doesn't exist (nothing to migrate), or + // (2) The MSAL cache does exist (don't override existing cache) + return; + } - byte[] adalData; - try - { - adalData = File.ReadAllBytes(adalCachePath); - } - catch - { - // Return if there was an error converting the ADAL data safely - return; - } + byte[] adalData; + try + { + adalData = File.ReadAllBytes(adalCachePath); + } + catch + { + // Return if there was an error converting the ADAL data safely + return; + } - if(adalData != null && adalData.Length > 0) + if (adalData != null && adalData.Length > 0) + { + new AdalTokenMigrator(adalData, getContextContainer).MigrateFromAdalToMsal(); + } + } + catch(Exception e) { - new AdalTokenMigrator(adalData, getContextContainer).MigrateFromAdalToMsal(); + writeWarning(Resources.FailedToMigrateAdal2Msal.FormatInvariant(e.Message)); } } diff --git a/src/Accounts/Authentication/Properties/Resources.Designer.cs b/src/Accounts/Authentication/Properties/Resources.Designer.cs index 22ed78c658e4..1e5e9fe84243 100644 --- a/src/Accounts/Authentication/Properties/Resources.Designer.cs +++ b/src/Accounts/Authentication/Properties/Resources.Designer.cs @@ -258,6 +258,15 @@ public static string ExpiredRefreshToken { } } + /// + /// Looks up a localized string similar to INITIALZATION: Failed to migrate ADAL token to MSAL token with error : {0}. + /// + public static string FailedToMigrateAdal2Msal { + get { + return ResourceManager.GetString("FailedToMigrateAdal2Msal", resourceCulture); + } + } + /// /// Looks up a localized string similar to File path is not valid. /// diff --git a/src/Accounts/Authentication/Properties/Resources.resx b/src/Accounts/Authentication/Properties/Resources.resx index ab5bd4c4253c..7e4cb12261ba 100644 --- a/src/Accounts/Authentication/Properties/Resources.resx +++ b/src/Accounts/Authentication/Properties/Resources.resx @@ -352,13 +352,13 @@ Unable to launch a browser for authorization code login. Reverting to device code login. - - The environment name '{0}' is not found. - Context autosave is not supported on current environment. Please disable it using 'Disable-AzContextSave'. Password is missing and no cache found for the current user. + + INITIALZATION: Failed to migrate ADAL token to MSAL token with error : {0} + \ No newline at end of file