diff --git a/extensions/azurecore/package.json b/extensions/azurecore/package.json index 2a862c52fc..d01bd86138 100644 --- a/extensions/azurecore/package.json +++ b/extensions/azurecore/package.json @@ -353,7 +353,6 @@ "@azure/msal-node": "^1.9.0", "@azure/storage-blob": "^12.6.0", "axios": "^0.27.2", - "crypto": "^1.0.1", "lockfile": "1.0.4", "msal": "^1.4.16", "node-fetch": "^2.6.7", diff --git a/extensions/azurecore/src/account-provider/auths/azureAuth.ts b/extensions/azurecore/src/account-provider/auths/azureAuth.ts index 9a08c45929..903854f78c 100644 --- a/extensions/azurecore/src/account-provider/auths/azureAuth.ts +++ b/extensions/azurecore/src/account-provider/auths/azureAuth.ts @@ -18,7 +18,7 @@ import { import { Deferred } from '../interfaces'; import * as url from 'url'; import * as Constants from '../../constants'; -import { SimpleTokenCache } from '../simpleTokenCache'; +import { SimpleTokenCache } from '../utils/simpleTokenCache'; import { MemoryDatabase } from '../utils/memoryDatabase'; import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'; import { Logger } from '../../utils/Logger'; diff --git a/extensions/azurecore/src/account-provider/auths/azureAuthCodeGrant.ts b/extensions/azurecore/src/account-provider/auths/azureAuthCodeGrant.ts index f5c009bcde..7b8b753c03 100644 --- a/extensions/azurecore/src/account-provider/auths/azureAuthCodeGrant.ts +++ b/extensions/azurecore/src/account-provider/auths/azureAuthCodeGrant.ts @@ -8,7 +8,7 @@ import { AzureAccountProviderMetadata, AzureAuthType, Resource, Tenant } from 'a import { Deferred } from '../interfaces'; import * as vscode from 'vscode'; import * as crypto from 'crypto'; -import { SimpleTokenCache } from '../simpleTokenCache'; +import { SimpleTokenCache } from '../utils/simpleTokenCache'; import { SimpleWebServer } from '../utils/simpleWebServer'; import { AzureAuthError } from './azureAuthError'; import { Logger } from '../../utils/Logger'; diff --git a/extensions/azurecore/src/account-provider/auths/azureDeviceCode.ts b/extensions/azurecore/src/account-provider/auths/azureDeviceCode.ts index fa1f90bbbb..177e1ccae7 100644 --- a/extensions/azurecore/src/account-provider/auths/azureDeviceCode.ts +++ b/extensions/azurecore/src/account-provider/auths/azureDeviceCode.ts @@ -21,7 +21,7 @@ import { } from 'azurecore'; import { Deferred } from '../interfaces'; import { AuthenticationResult, DeviceCodeRequest, PublicClientApplication } from '@azure/msal-node'; -import { SimpleTokenCache } from '../simpleTokenCache'; +import { SimpleTokenCache } from '../utils/simpleTokenCache'; import { Logger } from '../../utils/Logger'; const localize = nls.loadMessageBundle(); diff --git a/extensions/azurecore/src/account-provider/azureAccountProvider.ts b/extensions/azurecore/src/account-provider/azureAccountProvider.ts index 7b577f789e..a4fda4c2ab 100644 --- a/extensions/azurecore/src/account-provider/azureAccountProvider.ts +++ b/extensions/azurecore/src/account-provider/azureAccountProvider.ts @@ -14,7 +14,7 @@ import { } from 'azurecore'; import { Deferred } from './interfaces'; import { AuthenticationResult, PublicClientApplication } from '@azure/msal-node'; -import { SimpleTokenCache } from './simpleTokenCache'; +import { SimpleTokenCache } from './utils/simpleTokenCache'; import { Logger } from '../utils/Logger'; import { MultiTenantTokenResponse, Token, AzureAuth } from './auths/azureAuth'; import { AzureAuthCodeGrant } from './auths/azureAuthCodeGrant'; @@ -105,7 +105,7 @@ export class AzureAccountProvider implements azdata.AccountProvider, vscode.Disp private async _initialize(storedAccounts: AzureAccount[]): Promise { const accounts: AzureAccount[] = []; - console.log(`Initializing stored accounts ${JSON.stringify(accounts)}`); + Logger.verbose(`Initializing stored accounts ${JSON.stringify(accounts)}`); const updatedAccounts = filterAccounts(storedAccounts, this.authLibrary); for (let account of updatedAccounts) { const azureAuth = this.getAuthMethod(account); diff --git a/extensions/azurecore/src/account-provider/azureAccountProviderService.ts b/extensions/azurecore/src/account-provider/azureAccountProviderService.ts index 6424e6bbd1..0443d1de21 100644 --- a/extensions/azurecore/src/account-provider/azureAccountProviderService.ts +++ b/extensions/azurecore/src/account-provider/azureAccountProviderService.ts @@ -3,11 +3,13 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as path from 'path'; import * as azdata from 'azdata'; import * as events from 'events'; import * as nls from 'vscode-nls'; import * as vscode from 'vscode'; -import { SimpleTokenCache } from './simpleTokenCache'; +import { promises as fsPromises } from 'fs'; +import { SimpleTokenCache } from './utils/simpleTokenCache'; import providerSettings from './providerSettings'; import { AzureAccountProvider as AzureAccountProvider } from './azureAccountProvider'; import { AzureAccountProviderMetadata } from 'azurecore'; @@ -144,8 +146,8 @@ export class AzureAccountProviderService implements vscode.Disposable { const isSaw: boolean = vscode.env.appName.toLowerCase().indexOf(Constants.Saw) > 0; const noSystemKeychain = vscode.workspace.getConfiguration(Constants.AzureSection).get(Constants.NoSystemKeyChainSection); const tokenCacheKey = `azureTokenCache-${provider.metadata.id}`; - // Hardcode the MSAL Cache Key so there is only one cache location - const tokenCacheKeyMsal = `azureTokenCacheMsal-azure_publicCloud`; + const tokenCacheKeyMsal = Constants.MSALCacheName; + await this.clearOldCacheIfExists(); try { if (!this._credentialProvider) { throw new Error('Credential provider not registered'); @@ -156,7 +158,7 @@ export class AzureAccountProviderService implements vscode.Disposable { await simpleTokenCache.init(); // MSAL Cache Plugin - this._cachePluginProvider = new MsalCachePluginProvider(tokenCacheKeyMsal, this._userStoragePath); + this._cachePluginProvider = new MsalCachePluginProvider(tokenCacheKeyMsal, this._userStoragePath, this._credentialProvider); const msalConfiguration: Configuration = { auth: { @@ -185,6 +187,22 @@ export class AzureAccountProviderService implements vscode.Disposable { } } + /** + * Clears old cache file that is no longer needed on system. + */ + private async clearOldCacheIfExists(): Promise { + let filePath = path.join(this._userStoragePath, Constants.oldMsalCacheFileName); + try { + await fsPromises.access(filePath); + await fsPromises.unlink('file:' + filePath); + Logger.verbose(`Old cache file removed successfully.`); + } catch (e) { + if (e.code !== 'ENOENT') { + Logger.verbose(`Error occurred while removing old cache file: ${e}`); + } // else file doesn't exist. + } + } + private getLoggerCallback(): ILoggerCallback { return (level: number, message: string, containsPii: boolean) => { if (!containsPii) { diff --git a/extensions/azurecore/src/account-provider/utils/fileDatabase.ts b/extensions/azurecore/src/account-provider/utils/fileDatabase.ts index 4e96e1ab34..c5a4154093 100644 --- a/extensions/azurecore/src/account-provider/utils/fileDatabase.ts +++ b/extensions/azurecore/src/account-provider/utils/fileDatabase.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { promises as fs, constants as fsConstants } from 'fs'; +import { Logger } from '../../utils/Logger'; export type ReadWriteHook = (contents: string) => Promise; const noOpHook: ReadWriteHook = async (contents): Promise => { @@ -97,7 +98,7 @@ export class FileDatabase { fileContents = await fs.readFile(this.dbPath, { encoding: 'utf8' }); fileContents = await this.readHook(fileContents); } catch (ex) { - console.log(`file db does not exist ${ex}`); + Logger.error(`Error occurred when initializing File Database from file system cache, ADAL cache will be reset: ${ex}`); await this.createFile(); this.db = {}; this.isDirty = true; @@ -107,7 +108,7 @@ export class FileDatabase { try { this.db = JSON.parse(fileContents); } catch (ex) { - console.log(`DB was corrupted, resetting it ${ex}`); + Logger.error(`Error occurred when reading file database contents as JSON, ADAL cache will be reset: ${ex}`); await this.createFile(); this.db = {}; } @@ -139,7 +140,7 @@ export class FileDatabase { this.isDirty = false; } catch (ex) { - console.log(`File saving is erroring! ${ex}`); + Logger.error(`Error occurred while saving cache contents to file storage, this may cause issues with ADAL cache persistence: ${ex}`); } finally { this.isSaving = false; } diff --git a/extensions/azurecore/src/account-provider/utils/fileEncryptionHelper.ts b/extensions/azurecore/src/account-provider/utils/fileEncryptionHelper.ts index b8ea6f9008..881afb4ea2 100644 --- a/extensions/azurecore/src/account-provider/utils/fileEncryptionHelper.ts +++ b/extensions/azurecore/src/account-provider/utils/fileEncryptionHelper.ts @@ -3,32 +3,50 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as azdata from 'azdata'; +import * as os from 'os'; import * as crypto from 'crypto'; +import * as vscode from 'vscode'; +import { AuthLibrary } from '../../constants'; +import * as LocalizedConstants from '../../localizedConstants'; +import { Logger } from '../../utils/Logger'; export class FileEncryptionHelper { constructor( - private _credentialService: azdata.CredentialProvider, - private _fileName: string, - ) { } + private readonly _authLibrary: AuthLibrary, + private readonly _credentialService: azdata.CredentialProvider, + protected readonly _fileName: string + ) { + this._algorithm = this._authLibrary === AuthLibrary.MSAL ? 'aes-256-cbc' : 'aes-256-gcm'; + this._bufferEncoding = this._authLibrary === AuthLibrary.MSAL ? 'utf16le' : 'hex'; + this._binaryEncoding = this._authLibrary === AuthLibrary.MSAL ? 'base64' : 'hex'; + } + private _algorithm: string; + private _bufferEncoding: BufferEncoding; + private _binaryEncoding: crypto.HexBase64BinaryEncoding; private _ivBuffer: Buffer | undefined; private _keyBuffer: Buffer | undefined; - async init(): Promise { - const iv = await this._credentialService.readCredential(`${this._fileName}-iv`); - const key = await this._credentialService.readCredential(`${this._fileName}-key`); - if (!iv?.password || !key?.password) { + public async init(): Promise { + + const ivCredId = `${this._fileName}-iv`; + const keyCredId = `${this._fileName}-key`; + + const iv = await this.readEncryptionKey(ivCredId); + const key = await this.readEncryptionKey(keyCredId); + + if (!iv || !key) { this._ivBuffer = crypto.randomBytes(16); this._keyBuffer = crypto.randomBytes(32); - try { - await this._credentialService.saveCredential(`${this._fileName}-iv`, this._ivBuffer.toString('hex')); - await this._credentialService.saveCredential(`${this._fileName}-key`, this._keyBuffer.toString('hex')); - } catch (ex) { - console.log(ex); + + if (!await this.saveEncryptionKey(ivCredId, this._ivBuffer.toString(this._bufferEncoding)) + || !await this.saveEncryptionKey(keyCredId, this._keyBuffer.toString(this._bufferEncoding))) { + Logger.error(`Encryption keys could not be saved in credential store, this will cause access token persistence issues.`); + await this.showCredSaveErrorOnWindows(); } } else { - this._ivBuffer = Buffer.from(iv.password, 'hex'); - this._keyBuffer = Buffer.from(key.password, 'hex'); + this._ivBuffer = Buffer.from(iv, this._bufferEncoding); + this._keyBuffer = Buffer.from(key, this._bufferEncoding); } } @@ -36,21 +54,68 @@ export class FileEncryptionHelper { if (!this._keyBuffer || !this._ivBuffer) { await this.init(); } - const cipherIv = crypto.createCipheriv('aes-256-gcm', this._keyBuffer!, this._ivBuffer!); - return `${cipherIv.update(content, 'utf8', 'hex')}${cipherIv.final('hex')}%${cipherIv.getAuthTag().toString('hex')}`; - }; + const cipherIv = crypto.createCipheriv(this._algorithm, this._keyBuffer!, this._ivBuffer!); + let cipherText = `${cipherIv.update(content, 'utf8', this._binaryEncoding)}${cipherIv.final(this._binaryEncoding)}`; + if (this._authLibrary === AuthLibrary.ADAL) { + cipherText += `%${(cipherIv as crypto.CipherGCM).getAuthTag().toString(this._binaryEncoding)}`; + } + return cipherText; + } fileOpener = async (content: string): Promise => { if (!this._keyBuffer || !this._ivBuffer) { await this.init(); } - const decipherIv = crypto.createDecipheriv('aes-256-gcm', this._keyBuffer!, this._ivBuffer!); - const split = content.split('%'); - if (split.length !== 2) { - throw new Error('File didn\'t contain the auth tag.'); + let plaintext = content; + const decipherIv = crypto.createDecipheriv(this._algorithm, this._keyBuffer!, this._ivBuffer!); + if (this._authLibrary === AuthLibrary.ADAL) { + const split = content.split('%'); + if (split.length !== 2) { + throw new Error('File didn\'t contain the auth tag.'); + } + (decipherIv as crypto.DecipherGCM).setAuthTag(Buffer.from(split[1], this._binaryEncoding)); + plaintext = split[0]; } - decipherIv.setAuthTag(Buffer.from(split[1], 'hex')); - return `${decipherIv.update(split[0], 'hex', 'utf8')}${decipherIv.final('utf8')}`; - }; + return `${decipherIv.update(plaintext, this._binaryEncoding, 'utf8')}${decipherIv.final('utf8')}`; + } + protected async readEncryptionKey(credentialId: string): Promise { + return (await this._credentialService.readCredential(credentialId))?.password; + } + + protected async saveEncryptionKey(credentialId: string, password: string): Promise { + let status: boolean = false; + try { + await this._credentialService.saveCredential(credentialId, password) + .then((result) => { + status = result; + if (result) { + Logger.info(`FileEncryptionHelper: Successfully saved encryption key ${credentialId} for ${this._authLibrary} persistent cache encryption in system credential store.`); + } + }, (e => { + throw Error(`FileEncryptionHelper: Could not save encryption key: ${credentialId}: ${e}`); + })); + } catch (ex) { + if (os.platform() === 'win32') { + Logger.error(`FileEncryptionHelper: Please try cleaning saved credentials from Windows Credential Manager created by Azure Data Studio to allow creating new credentials.`); + } + Logger.error(ex); + throw ex; + } + return status; + } + + protected async showCredSaveErrorOnWindows(): Promise { + if (os.platform() === 'win32') { + await vscode.window.showWarningMessage(LocalizedConstants.azureCredStoreSaveFailedError, + LocalizedConstants.reloadChoice, LocalizedConstants.cancel) + .then(async (selection) => { + if (selection === LocalizedConstants.reloadChoice) { + await vscode.commands.executeCommand('workbench.action.reloadWindow'); + } + }, error => { + Logger.error(error); + }); + } + } } diff --git a/extensions/azurecore/src/account-provider/utils/msalCachePlugin.ts b/extensions/azurecore/src/account-provider/utils/msalCachePlugin.ts index e7207c56be..13f5c212e8 100644 --- a/extensions/azurecore/src/account-provider/utils/msalCachePlugin.ts +++ b/extensions/azurecore/src/account-provider/utils/msalCachePlugin.ts @@ -8,20 +8,23 @@ import { promises as fsPromises } from 'fs'; import * as lockFile from 'lockfile'; import * as path from 'path'; -import { AccountsClearTokenCacheCommand } from '../../constants'; +import * as azdata from 'azdata'; +import { AccountsClearTokenCacheCommand, AuthLibrary } from '../../constants'; import { Logger } from '../../utils/Logger'; +import { FileEncryptionHelper } from './fileEncryptionHelper'; export class MsalCachePluginProvider { constructor( private readonly _serviceName: string, private readonly _msalFilePath: string, + private readonly _credentialService: azdata.CredentialProvider ) { this._msalFilePath = path.join(this._msalFilePath, this._serviceName); - this._serviceName = this._serviceName.replace(/-/, '_'); - Logger.verbose(`MsalCachePluginProvider: Using cache path ${_msalFilePath} and serviceName ${_serviceName}`); + this._fileEncryptionHelper = new FileEncryptionHelper(AuthLibrary.MSAL, this._credentialService, this._serviceName); } private _lockTaken: boolean = false; + private _fileEncryptionHelper: FileEncryptionHelper; private getLockfilePath(): string { return this._msalFilePath + '.lockfile'; @@ -33,8 +36,9 @@ export class MsalCachePluginProvider { await this.waitAndLock(lockFilePath); try { const cache = await fsPromises.readFile(this._msalFilePath, { encoding: 'utf8' }); + const decryptedData = await this._fileEncryptionHelper.fileOpener(cache!); try { - cacheContext.tokenCache.deserialize(cache); + cacheContext.tokenCache.deserialize(decryptedData); } catch (e) { // Handle deserialization error in cache file in case file gets corrupted. // Clearing cache here will ensure account is marked stale so re-authentication can be triggered. @@ -49,7 +53,8 @@ export class MsalCachePluginProvider { } else { Logger.error(`MsalCachePlugin: Failed to read from cache file: ${e}`); - throw e; + Logger.verbose(`MsalCachePlugin: Error occurred when trying to read cache file, file contents will be cleared: ${e.message}`); + await fsPromises.writeFile(this._msalFilePath, '', { encoding: 'utf8' }); } } finally { lockFile.unlockSync(lockFilePath); @@ -62,7 +67,8 @@ export class MsalCachePluginProvider { await this.waitAndLock(lockFilePath); try { const data = cacheContext.tokenCache.serialize(); - await fsPromises.writeFile(this._msalFilePath, data, { encoding: 'utf8' }); + const encryptedData = await this._fileEncryptionHelper.fileSaver(data!); + await fsPromises.writeFile(this._msalFilePath, encryptedData, { encoding: 'utf8' }); Logger.verbose(`MsalCachePlugin: Token written to cache successfully.`); } catch (e) { Logger.error(`MsalCachePlugin: Failed to write to cache file. ${e}`); diff --git a/extensions/azurecore/src/account-provider/simpleTokenCache.ts b/extensions/azurecore/src/account-provider/utils/simpleTokenCache.ts similarity index 95% rename from extensions/azurecore/src/account-provider/simpleTokenCache.ts rename to extensions/azurecore/src/account-provider/utils/simpleTokenCache.ts index d2bb498428..128a3d8dad 100644 --- a/extensions/azurecore/src/account-provider/simpleTokenCache.ts +++ b/extensions/azurecore/src/account-provider/utils/simpleTokenCache.ts @@ -4,9 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import * as keytarType from 'keytar'; import { join, parse } from 'path'; -import { FileDatabase } from './utils/fileDatabase'; +import { FileDatabase } from './fileDatabase'; import * as azdata from 'azdata'; -import { FileEncryptionHelper } from './utils/fileEncryptionHelper'; +import { FileEncryptionHelper } from './fileEncryptionHelper'; +import { AuthLibrary } from '../../constants'; function getSystemKeytar(): Keytar | undefined { try { @@ -25,7 +26,7 @@ const separator = 'ยง'; async function getFileKeytar(filePath: string, credentialService: azdata.CredentialProvider): Promise { const fileName = parse(filePath).base; - const fileEncryptionHelper: FileEncryptionHelper = new FileEncryptionHelper(credentialService, fileName); + const fileEncryptionHelper: FileEncryptionHelper = new FileEncryptionHelper(AuthLibrary.ADAL, credentialService, fileName); const db = new FileDatabase(filePath, fileEncryptionHelper.fileOpener, fileEncryptionHelper.fileSaver); await db.initialize(); diff --git a/extensions/azurecore/src/account-provider/utils/simpleWebServer.ts b/extensions/azurecore/src/account-provider/utils/simpleWebServer.ts index 706a928c62..c4df204df4 100644 --- a/extensions/azurecore/src/account-provider/utils/simpleWebServer.ts +++ b/extensions/azurecore/src/account-provider/utils/simpleWebServer.ts @@ -5,6 +5,7 @@ import * as http from 'http'; import * as url from 'url'; import { AddressInfo } from 'net'; +import { Logger } from '../../utils/Logger'; export type WebHandler = (req: http.IncomingMessage, reqUrl: url.UrlWithParsedQuery, res: http.ServerResponse) => void; @@ -24,7 +25,7 @@ export class SimpleWebServer { const time = new Date().getTime(); if (time - this.lastUsed > this.autoShutoffTimer) { - console.log('Shutting off webserver...'); + Logger.verbose('Shutting off webserver...'); this.shutdown().catch(console.error); } }, 1000); diff --git a/extensions/azurecore/src/azureDataGridProvider.ts b/extensions/azurecore/src/azureDataGridProvider.ts index 18d229a796..832bdafb10 100644 --- a/extensions/azurecore/src/azureDataGridProvider.ts +++ b/extensions/azurecore/src/azureDataGridProvider.ts @@ -12,6 +12,7 @@ import * as azureResourceUtils from './azureResource/utils'; import * as constants from './constants'; import * as loc from './localizedConstants'; import * as utils from './utils'; +import { Logger } from './utils/Logger'; const typesClause = [ azureResource.AzureResourceType.sqlDatabase, @@ -60,10 +61,10 @@ export class AzureDataGridProvider implements azdata.DataGridProvider { }); items.push(...newItems); } catch (err) { - console.log(err); + Logger.error(err); } } catch (err) { - console.log(err); + Logger.error(err); } })); })); diff --git a/extensions/azurecore/src/azureResource/providers/resourceTreeDataProviderBase.ts b/extensions/azurecore/src/azureResource/providers/resourceTreeDataProviderBase.ts index ae1e0d611d..4e4feec498 100644 --- a/extensions/azurecore/src/azureResource/providers/resourceTreeDataProviderBase.ts +++ b/extensions/azurecore/src/azureResource/providers/resourceTreeDataProviderBase.ts @@ -10,6 +10,7 @@ import { IAzureResourceService } from '../interfaces'; import { AzureResourceErrorMessageUtil } from '../utils'; import { ResourceGraphClient } from '@azure/arm-resourcegraph'; import { AzureAccount, azureResource } from 'azurecore'; +import { Logger } from '../../utils/Logger'; export abstract class ResourceTreeDataProviderBase implements azureResource.IAzureResourceTreeDataProvider { public browseConnectionMode: boolean = false; @@ -32,7 +33,7 @@ export abstract class ResourceTreeDataProviderBase (a.treeItem.label).localeCompare(b.treeItem.label)); } catch (error) { - console.log(AzureResourceErrorMessageUtil.getErrorMessage(error)); + Logger.error(AzureResourceErrorMessageUtil.getErrorMessage(error)); throw error; } } @@ -102,7 +103,7 @@ export async function queryGraphResources(resourceClient: R } } catch (err2) { // Just log, we still want to throw the original error if something happens parsing the error - console.log(`Unexpected error while parsing error from querying resources : ${err2}`); + Logger.error(`Unexpected error while parsing error from querying resources : ${err2}`); } throw err; } diff --git a/extensions/azurecore/src/azureResource/services/terminalService.ts b/extensions/azurecore/src/azureResource/services/terminalService.ts index 3f90da6715..56a507313b 100644 --- a/extensions/azurecore/src/azureResource/services/terminalService.ts +++ b/extensions/azurecore/src/azureResource/services/terminalService.ts @@ -10,6 +10,7 @@ import * as WS from 'ws'; import { IAzureTerminalService } from '../interfaces'; import { AzureAccount, Tenant } from 'azurecore'; +import { Logger } from '../../utils/Logger'; const localize = nls.loadMessageBundle(); @@ -68,8 +69,8 @@ export class AzureTerminalService implements IAzureTerminalService { let userSettingsResult: AxiosResponse; try { userSettingsResult = await axios.get(userSettingsUri, settings); - } catch (ex) { - console.log(ex, ex.response); + } catch (ex) {// Log as info as exception is handled + Logger.info(ex, ex.response); await handleNeverUsed(); return; } @@ -85,8 +86,8 @@ export class AzureTerminalService implements IAzureTerminalService { let provisionResult: AxiosResponse; try { provisionResult = await axios.put(consoleRequestUri, {}, settings); - } catch (ex) { - console.log(ex, ex.response); + } catch (ex) {// Log as info as exception is handled + Logger.info(ex, ex.response); await handleNeverUsed(); return; } @@ -215,7 +216,7 @@ class AzureTerminal implements vscode.Pseudoterminal { this.socket?.ping(); }, 5000); } catch (ex) { - console.log(ex); + Logger.error(ex); } } @@ -234,7 +235,7 @@ class AzureTerminal implements vscode.Pseudoterminal { } }); } catch (ex) { - console.log(`Error establishing terminal. ${ex}, ${ex.response}`); + Logger.info(`Error establishing terminal. ${ex}, ${ex.response}`); await handleNeverUsed(); return undefined; } @@ -246,8 +247,8 @@ class AzureTerminal implements vscode.Pseudoterminal { } if (!terminalUri) { - console.log(terminalResult); - throw new Error(terminalResult.data); + Logger.error(terminalResult); + throw Error(terminalResult.data); } return terminalUri; diff --git a/extensions/azurecore/src/constants.ts b/extensions/azurecore/src/constants.ts index 301a775b2d..38857189bd 100644 --- a/extensions/azurecore/src/constants.ts +++ b/extensions/azurecore/src/constants.ts @@ -39,6 +39,8 @@ export const AzureTenantConfigSection = AzureSection + '.' + TenantSection + '.' export const NoSystemKeyChainSection = 'noSystemKeychain'; +export const oldMsalCacheFileName = 'azureTokenCacheMsal-azure_publicCloud'; + /** MSAL Account version */ export const AccountVersion = '2.0'; @@ -61,6 +63,8 @@ export const dataGridProviderId = 'azure-resources'; export const AzureTokenFolderName = 'Azure Accounts'; +export const MSALCacheName = 'accessTokenCache'; + export const DefaultAuthLibrary = 'ADAL'; export enum BuiltInCommands { diff --git a/extensions/azurecore/src/extension.ts b/extensions/azurecore/src/extension.ts index 8723dee367..c3f24584e7 100644 --- a/extensions/azurecore/src/extension.ts +++ b/extensions/azurecore/src/extension.ts @@ -100,7 +100,7 @@ export async function activate(context: vscode.ExtensionContext): Promise console.log(err)); + initAzureAccountProvider(extensionContext, storagePath, authLibrary!).catch((err) => Logger.error(err)); registerAzureServices(appContext); const azureResourceTree = new AzureResourceTreeProvider(appContext, authLibrary); @@ -119,7 +119,7 @@ export async function activate(context: vscode.ExtensionContext): Promise