mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-13 17:22:15 -05:00
# Conflicts: # extensions/mssql/config.json
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<AzureAccount[]> {
|
||||
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);
|
||||
|
||||
@@ -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<boolean>(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<void> {
|
||||
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) {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { promises as fs, constants as fsConstants } from 'fs';
|
||||
import { Logger } from '../../utils/Logger';
|
||||
|
||||
export type ReadWriteHook = (contents: string) => Promise<string>;
|
||||
const noOpHook: ReadWriteHook = async (contents): Promise<string> => {
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<void> {
|
||||
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<void> {
|
||||
|
||||
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<string> => {
|
||||
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<string | undefined> {
|
||||
return (await this._credentialService.readCredential(credentialId))?.password;
|
||||
}
|
||||
|
||||
protected async saveEncryptionKey(credentialId: string, password: string): Promise<boolean> {
|
||||
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<void> {
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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}`);
|
||||
|
||||
@@ -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<Keytar | undefined> {
|
||||
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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}));
|
||||
}));
|
||||
|
||||
@@ -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<T extends azureResource.AzureResource> implements azureResource.IAzureResourceTreeDataProvider {
|
||||
public browseConnectionMode: boolean = false;
|
||||
@@ -32,7 +33,7 @@ export abstract class ResourceTreeDataProviderBase<T extends azureResource.Azure
|
||||
treeItem: this.getTreeItemForResource(resource, element.account)
|
||||
}).sort((a, b) => (<any>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<T extends GraphData>(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;
|
||||
}
|
||||
|
||||
@@ -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<any>;
|
||||
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<any>;
|
||||
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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -100,7 +100,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<azurec
|
||||
updatePiiLoggingLevel();
|
||||
|
||||
// Create the provider service and activate
|
||||
initAzureAccountProvider(extensionContext, storagePath, authLibrary!).catch((err) => 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<azurec
|
||||
if (portalEndpoint && subscriptionId && resourceGroup && type && name) {
|
||||
await vscode.env.openExternal(vscode.Uri.parse(`${portalEndpoint}/#resource/subscriptions/${subscriptionId}/resourceGroups/${resourceGroup}/providers/${type}/${name}`));
|
||||
} else {
|
||||
console.log(`Missing required values - subscriptionId : ${subscriptionId} resourceGroup : ${resourceGroup} type: ${type} name: ${name}`);
|
||||
Logger.error(`Missing required values - subscriptionId : ${subscriptionId} resourceGroup : ${resourceGroup} type: ${type} name: ${name}`);
|
||||
void vscode.window.showErrorMessage(loc.unableToOpenAzureLink);
|
||||
}
|
||||
});
|
||||
@@ -248,7 +248,7 @@ async function findOrMakeStoragePath() {
|
||||
await fs.mkdir(defaultLogLocation, { recursive: true });
|
||||
} catch (e) {
|
||||
if (e.code !== 'EEXIST') {
|
||||
console.log(`Creating the base directory failed... ${e}`);
|
||||
Logger.error(`Creating the base directory failed... ${e}`);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -257,13 +257,13 @@ async function findOrMakeStoragePath() {
|
||||
await fs.mkdir(storagePath, { recursive: true });
|
||||
} catch (e) {
|
||||
if (e.code !== 'EEXIST') {
|
||||
console.error(`Initialization of Azure account extension storage failed: ${e}`);
|
||||
console.error('Azure accounts will not be available');
|
||||
Logger.error(`Initialization of Azure account extension storage failed: ${e}`);
|
||||
Logger.error('Azure accounts will not be available');
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Initialized Azure account extension storage.');
|
||||
Logger.verbose('Initialized Azure account extension storage.');
|
||||
return storagePath;
|
||||
}
|
||||
|
||||
@@ -273,7 +273,7 @@ async function initAzureAccountProvider(extensionContext: vscode.ExtensionContex
|
||||
extensionContext.subscriptions.push(accountProviderService);
|
||||
await accountProviderService.activate();
|
||||
} catch (err) {
|
||||
console.log('Unexpected error starting account provider: ' + err.message);
|
||||
Logger.error('Unexpected error starting account provider: ' + err.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ export const extensionName = localize('azurecore.extensionName', "Azure Accounts
|
||||
|
||||
export const requiresReload = localize('azurecore.requiresReload', "Modifying this setting requires reloading the window for all changes to take effect.");
|
||||
export const reload = localize('azurecore.reload', "Reload");
|
||||
export const cancel = localize('azurecore.reload', "Cancel");
|
||||
|
||||
export const australiaCentral = localize('azurecore.australiacentral', "Australia Central");
|
||||
export const australiaCentral2 = localize('azurecore.australiacentral2', "Australia Central 2");
|
||||
@@ -84,3 +85,6 @@ export const invalidTenant = localize('azurecore.invalidTenant', "Invalid tenant
|
||||
export function unableToFetchTokenError(tenant: string): string {
|
||||
return localize('azurecore.unableToFetchToken', "Unable to get token for tenant {0}", tenant);
|
||||
}
|
||||
|
||||
// Error Messages
|
||||
export const azureCredStoreSaveFailedError = localize('azure.credStoreSaveFailedError', `Keys for token cache could not be saved in credential store, this may cause Azure access token persistence issues and connection instabilities. It's likely that SqlTools has reached credential storage limit on Windows, please clear at least 2 credentials that start with "Microsoft.SqlTools|" in Windows Credential Manager and reload.`);
|
||||
|
||||
@@ -690,10 +690,12 @@ crypt@~0.0.1:
|
||||
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
|
||||
integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
|
||||
|
||||
crypto@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/crypto/-/crypto-1.0.1.tgz#2af1b7cad8175d24c8a1b0778255794a21803037"
|
||||
integrity sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==
|
||||
debug@3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
|
||||
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@3.1.0:
|
||||
version "3.1.0"
|
||||
|
||||
Reference in New Issue
Block a user