void EnableAutosave(IAzureSession session, bool writeAutoSaveFile, out ContextAutosaveSettings result) { var store = session.DataStore; string contextPath = Path.Combine(session.ARMProfileDirectory, session.ARMProfileFile); string tokenPath = Path.Combine(session.TokenCacheDirectory, session.TokenCacheFile); if (!IsValidPath(contextPath)) { throw new PSInvalidOperationException(string.Format("'{0}' is not a valid path. You cannot enable context autosave without a valid context path", contextPath)); } if (!IsValidPath(tokenPath)) { throw new PSInvalidOperationException(string.Format("'{0}' is not a valid path. You cannot enable context autosave without a valid token cache path", tokenPath)); } result = new ContextAutosaveSettings { CacheDirectory = session.TokenCacheDirectory, CacheFile = session.TokenCacheFile, ContextDirectory = session.ARMProfileDirectory, ContextFile = session.ARMProfileFile, Mode = ContextSaveMode.CurrentUser }; FileUtilities.DataStore = session.DataStore; session.ARMContextSaveMode = ContextSaveMode.CurrentUser; AzureSession.Instance.TryGetComponent(nameof(PowerShellTokenCacheProvider.PowerShellTokenCacheProviderKey), out PowerShellTokenCacheProvider originalCacheProvider); if (originalCacheProvider is InMemoryTokenCacheProvider inMemoryTokenCacheProvider) { var tokenData = inMemoryTokenCacheProvider.ReadTokenData(); //must use explicit interface type PowerShellTokenCacheProvider below instead of var, otherwise could not retrieve registered component PowerShellTokenCacheProvider newCacheProvider = new SharedTokenCacheProvider(); if (tokenData != null && tokenData.Length > 0) { newCacheProvider.UpdateTokenDataWithoutFlush(tokenData); newCacheProvider.FlushTokenData(); } AzureSession.Instance.RegisterComponent(PowerShellTokenCacheProvider.PowerShellTokenCacheProviderKey, () => newCacheProvider, true); } if (writeAutoSaveFile) { try { FileUtilities.EnsureDirectoryExists(session.ProfileDirectory); string autoSavePath = Path.Combine(session.ProfileDirectory, ContextAutosaveSettings.AutoSaveSettingsFile); session.DataStore.WriteFile(autoSavePath, JsonConvert.SerializeObject(result)); } catch { // do not fail for file system errors in writing the autosave setting // it may impact automation environment and module import. } } }
/// <summary> /// Load global aliases for ARM /// </summary> public void OnImport() { #if DEBUG try { #endif AzureSessionInitializer.InitializeAzureSession(); AzureSessionInitializer.MigrateAdalCache(AzureSession.Instance, GetAzureContextContainer, WriteInitializationWarnings); #if DEBUG if (!TestMockSupport.RunningMocked) { #endif AzureSession.Instance.DataStore = new DiskDataStore(); #if DEBUG } #endif var autoSaveEnabled = AzureSession.Instance.ARMContextSaveMode == ContextSaveMode.CurrentUser; var autosaveVariable = System.Environment.GetEnvironmentVariable(AzureProfileConstants.AzureAutosaveVariable); if (bool.TryParse(autosaveVariable, out bool localAutosave)) { autoSaveEnabled = localAutosave; } try { if (autoSaveEnabled && !TokenCachePersistenceChecker.Verify()) { // 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) { //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)) { AzureSession.Instance.ARMContextSaveMode = ContextSaveMode.Process; autoSaveEnabled = false; } IServicePrincipalKeyStore keyStore = new AzureRmServicePrincipalKeyStore(AzureRmProfileProvider.Instance.Profile); AzureSession.Instance.RegisterComponent(ServicePrincipalKeyStore.Name, () => keyStore); IAuthenticatorBuilder builder = null; if (!AzureSession.Instance.TryGetComponent(AuthenticatorBuilder.AuthenticatorBuilderKey, out builder)) { builder = new DefaultAuthenticatorBuilder(); AzureSession.Instance.RegisterComponent(AuthenticatorBuilder.AuthenticatorBuilderKey, () => builder); } PowerShellTokenCacheProvider provider = null; if (autoSaveEnabled) { provider = new SharedTokenCacheProvider(); } else // if autosave is disabled, or the shared factory fails to initialize, we fallback to in memory { provider = new InMemoryTokenCacheProvider(); } var tokenCache = provider.GetTokenCache(); IAzureEventListenerFactory azureEventListenerFactory = new AzureEventListenerFactory(); AzureSession.Instance.RegisterComponent(nameof(CommonUtilities), () => new CommonUtilities()); AzureSession.Instance.RegisterComponent(PowerShellTokenCacheProvider.PowerShellTokenCacheProviderKey, () => provider); AzureSession.Instance.RegisterComponent(nameof(IAzureEventListenerFactory), () => azureEventListenerFactory); AzureSession.Instance.RegisterComponent(nameof(PowerShellTokenCache), () => tokenCache); AzureSession.Instance.RegisterComponent(nameof(AzureCredentialFactory), () => new AzureCredentialFactory()); AzureSession.Instance.RegisterComponent(nameof(MsalAccessTokenAcquirerFactory), () => new MsalAccessTokenAcquirerFactory()); #if DEBUG } catch (Exception) when(TestMockSupport.RunningMocked) { // This will throw exception for tests, ignore. } #endif }
/// <summary> /// Load global aliases for ARM /// </summary> public void OnImport() { #if DEBUG try { #endif AzureSessionInitializer.InitializeAzureSession(); AzureSessionInitializer.MigrateAdalCache(AzureSession.Instance, GetAzureContextContainer, WriteInitializationWarnings); #if DEBUG if (!TestMockSupport.RunningMocked) { #endif AzureSession.Instance.DataStore = new DiskDataStore(); #if DEBUG } #endif var autoSaveEnabled = AzureSession.Instance.ARMContextSaveMode == ContextSaveMode.CurrentUser; var autosaveVariable = System.Environment.GetEnvironmentVariable(AzureProfileConstants.AzureAutosaveVariable); if (bool.TryParse(autosaveVariable, out bool localAutosave)) { autoSaveEnabled = localAutosave; } try { if (autoSaveEnabled && !TokenCachePersistenceChecker.Verify()) { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { // In Windows and macOS platforms, unknown errors are discovered that fails the persistence check. // Disable context autosaving before msal library provide a fallback method for the case. throw new PSInvalidOperationException(Resources.TokenCachePersistenceCheckError); } // 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) { //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)) { AzureSession.Instance.ARMContextSaveMode = ContextSaveMode.Process; autoSaveEnabled = false; } #pragma warning disable CS0618 // Type or member is obsolete var keyStore = new AzKeyStore(AzureRmProfileProvider.Instance.Profile); #pragma warning restore CS0618 // Type or member is obsolete AzureSession.Instance.RegisterComponent(AzKeyStore.Name, () => keyStore); IAuthenticatorBuilder builder = null; if (!AzureSession.Instance.TryGetComponent(AuthenticatorBuilder.AuthenticatorBuilderKey, out builder)) { builder = new DefaultAuthenticatorBuilder(); AzureSession.Instance.RegisterComponent(AuthenticatorBuilder.AuthenticatorBuilderKey, () => builder); } PowerShellTokenCacheProvider provider = null; if (autoSaveEnabled) { provider = new SharedTokenCacheProvider(); } else // if autosave is disabled, or the shared factory fails to initialize, we fallback to in memory { provider = new InMemoryTokenCacheProvider(); } IAzureEventListenerFactory azureEventListenerFactory = new AzureEventListenerFactory(); AzureSession.Instance.RegisterComponent(nameof(CommonUtilities), () => new CommonUtilities()); // It's tricky to register a component as an Interface // Make sure componentInitializer return the Interface, not the derived type AzureSession.Instance.RegisterComponent(nameof(ISharedUtilities), () => new AzureRmSharedUtilities() as ISharedUtilities); AzureSession.Instance.RegisterComponent(PowerShellTokenCacheProvider.PowerShellTokenCacheProviderKey, () => provider); AzureSession.Instance.RegisterComponent(nameof(IAzureEventListenerFactory), () => azureEventListenerFactory); AzureSession.Instance.RegisterComponent(nameof(AzureCredentialFactory), () => new AzureCredentialFactory()); AzureSession.Instance.RegisterComponent(nameof(MsalAccessTokenAcquirerFactory), () => new MsalAccessTokenAcquirerFactory()); AzureSession.Instance.RegisterComponent <ISshCredentialFactory>(nameof(ISshCredentialFactory), () => new SshCredentialFactory()); #if DEBUG } catch (Exception) when(TestMockSupport.RunningMocked) { // This will throw exception for tests, ignore. } #endif }