Enable SQL Auth Provider support (#21903)

This commit is contained in:
Cheena Malhotra
2023-03-03 12:49:01 -08:00
committed by GitHub
parent 0ac6f40559
commit aa350f7e49
25 changed files with 198 additions and 59 deletions

View File

@@ -212,8 +212,9 @@ export abstract class AzureAuth implements vscode.Disposable {
}
const resource = this.resources.find(s => s.azureResourceId === azureResource);
if (!resource) {
Logger.error(`Unable to find Azure resource ${azureResource} for account ${account.displayInfo.userId} and tenant ${tenantId}`);
Logger.error(`Unable to find Azure resource ${azureResource}`);
return undefined;
}
@@ -300,7 +301,7 @@ export abstract class AzureAuth implements vscode.Disposable {
* re-authentication process for their tenant.
*/
public async refreshTokenAdal(tenant: Tenant, resource: Resource, refreshToken: RefreshToken | undefined): Promise<OAuthTokenResponse | undefined> {
Logger.pii('Refreshing token', [{ name: 'token', objOrArray: refreshToken }], []);
Logger.piiSanitized('Refreshing token', [{ name: 'token', objOrArray: refreshToken }], []);
if (refreshToken) {
const postData: RefreshTokenPostData = {
grant_type: 'refresh_token',
@@ -324,10 +325,12 @@ export abstract class AzureAuth implements vscode.Disposable {
*/
public async getTokenMsal(accountId: string, azureResource: azdata.AzureResource, tenantId: string): Promise<AuthenticationResult | azdata.PromptFailedResult | null> {
const resource = this.resources.find(s => s.azureResourceId === azureResource);
if (!resource) {
Logger.error(`Error: Could not fetch the azure resource ${azureResource} `);
Logger.error(`Unable to find Azure resource ${azureResource}`);
return null;
}
// Resource endpoint must end with '/' to form a valid scope for MSAL token request.
const endpoint = resource.endpoint.endsWith('/') ? resource.endpoint : resource.endpoint + '/';
@@ -399,7 +402,7 @@ export abstract class AzureAuth implements vscode.Disposable {
const tokenUrl = `${this.loginEndpointUrl}${tenant.id}/oauth2/token`;
const response = await this.makePostRequest(tokenUrl, postData);
Logger.pii('Token: ', [{ name: 'access token', objOrArray: response.data }, { name: 'refresh token', objOrArray: response.data }], []);
Logger.piiSanitized('Token: ', [{ name: 'access token', objOrArray: response.data }, { name: 'refresh token', objOrArray: response.data }], []);
if (response.data.error === 'interaction_required') {
return this.handleInteractionRequiredAdal(tenant, resource);
}
@@ -550,13 +553,13 @@ export abstract class AzureAuth implements vscode.Disposable {
private async saveTokenAdal(tenant: Tenant, resource: Resource, accountKey: azdata.AccountKey, { accessToken, refreshToken, expiresOn }: OAuthTokenResponse) {
const msg = localize('azure.cacheErrorAdd', "Error when adding your account to the cache.");
if (!tenant.id || !resource.id) {
Logger.pii('Tenant ID or resource ID was undefined', [], [], tenant, resource);
Logger.piiSanitized('Tenant ID or resource ID was undefined', [], [], tenant, resource);
throw new AzureAuthError(msg, 'Adding account to cache failed', undefined);
}
try {
Logger.pii(`Saving access token`, [{ name: 'access_token', objOrArray: accessToken }], []);
Logger.piiSanitized(`Saving access token`, [{ name: 'access_token', objOrArray: accessToken }], []);
await this.tokenCache.saveCredential(`${accountKey.accountId}_access_${resource.id}_${tenant.id}`, JSON.stringify(accessToken));
Logger.pii(`Saving refresh token`, [{ name: 'refresh_token', objOrArray: refreshToken }], []);
Logger.piiSanitized(`Saving refresh token`, [{ name: 'refresh_token', objOrArray: refreshToken }], []);
await this.tokenCache.saveCredential(`${accountKey.accountId}_refresh_${resource.id}_${tenant.id}`, JSON.stringify(refreshToken));
this.memdb.set(`${accountKey.accountId}_${tenant.id}_${resource.id}`, expiresOn);
} catch (ex) {
@@ -570,7 +573,7 @@ export abstract class AzureAuth implements vscode.Disposable {
const parseMsg = localize('azure.cacheErrorParse', "Error when parsing your account from the cache");
if (!tenant.id || !resource.id) {
Logger.pii('Tenant ID or resource ID was undefined', [], [], tenant, resource);
Logger.piiSanitized('Tenant ID or resource ID was undefined', [], [], tenant, resource);
throw new AzureAuthError(getMsg, 'Getting account from cache failed', undefined);
}
@@ -597,7 +600,7 @@ export abstract class AzureAuth implements vscode.Disposable {
if (refreshTokenString) {
refreshToken = JSON.parse(refreshTokenString);
}
Logger.pii('GetSavedToken ', [{ name: 'access', objOrArray: accessToken }, { name: 'refresh', objOrArray: refreshToken }], [], `expiresOn=${expiresOn}`);
Logger.piiSanitized('GetSavedToken ', [{ name: 'access', objOrArray: accessToken }, { name: 'refresh', objOrArray: refreshToken }], [], `expiresOn=${expiresOn}`);
return {
accessToken, refreshToken, expiresOn
};
@@ -683,7 +686,7 @@ export abstract class AzureAuth implements vscode.Disposable {
}
};
const messageBody = localize('azurecore.consentDialog.body', "Your tenant '{0} ({1})' requires you to re-authenticate again to access {2} resources. Press Open to start the authentication process.", tenant.displayName, tenant.id, resource.id);
const messageBody = localize('azurecore.consentDialog.body', "Your tenant '{0} ({1})' requires you to re-authenticate again to access {2} resources. Press Open to start the authentication process.", tenant.displayName, tenant.id, resource.endpoint);
const result = await vscode.window.showInformationMessage(messageBody, { modal: true }, openItem, closeItem, dontAskAgainItem);
if (result?.action) {
@@ -788,7 +791,7 @@ export abstract class AzureAuth implements vscode.Disposable {
// Intercept response and print out the response for future debugging
const response = await axios.post(url, qs.stringify(postData), config);
Logger.pii('POST request ', [{ name: 'data', objOrArray: postData }, { name: 'response', objOrArray: response.data }], [], url);
Logger.piiSanitized('POST request ', [{ name: 'data', objOrArray: postData }, { name: 'response', objOrArray: response.data }], [], url);
return response;
}
@@ -802,7 +805,7 @@ export abstract class AzureAuth implements vscode.Disposable {
};
const response = await axios.get(url, config);
Logger.pii('GET request ', [{ name: 'response', objOrArray: response.data.value ?? response.data }], [], url,);
Logger.piiSanitized('GET request ', [{ name: 'response', objOrArray: response.data.value ?? response.data }], [], url,);
return response;
}

View File

@@ -144,7 +144,7 @@ export class AzureAccountProvider implements azdata.AccountProvider, vscode.Disp
await this.initCompletePromise;
const azureAuth = this.getAuthMethod(account);
if (azureAuth) {
Logger.pii(`Getting account security token for ${JSON.stringify(account.key)} (tenant ${tenantId}). Auth Method = ${azureAuth.userFriendlyName}`, [], []);
Logger.piiSanitized(`Getting account security token for ${JSON.stringify(account.key)} (tenant ${tenantId}). Auth Method = ${azureAuth.userFriendlyName}`, [], []);
if (this.authLibrary === Constants.AuthLibrary.MSAL) {
tenantId = tenantId || account.properties.owningTenant.id;
let authResult = await azureAuth.getTokenMsal(account.key.accountId, resource, tenantId);

View File

@@ -201,7 +201,7 @@ export class AzureAccountProviderService implements vscode.Disposable {
break;
}
} else {
Logger.verbose(message);
Logger.pii(message);
}
}
}

View File

@@ -24,7 +24,7 @@ export class MsalCachePluginProvider {
private _lockTaken: boolean = false;
private getLockfilePath(): string {
return this._msalFilePath + '.lock';
return this._msalFilePath + '.lockfile';
}
public getCachePlugin(): ICachePlugin {

View File

@@ -47,7 +47,15 @@ export class Logger {
this.write(LogLevel.Verbose, msg, vals);
}
/**
* Logs a message containing PII (when enabled).
* @param msg The initial message to log
*/
static pii(msg: any, ...vals: any[]) {
if (this.piiLogging) {
Logger.write(LogLevel.Pii, msg, vals);
}
}
/**
* Logs a message containing PII (when enabled). Provides the ability to sanitize or shorten values to hide information or reduce the amount logged.
@@ -56,7 +64,7 @@ export class Logger {
* @param stringsToShorten Set of strings to shorten
* @param vals Any other values to add on to the end of the log message
*/
static pii(msg: any, objsToSanitize: { name: string, objOrArray: any | any[] }[], stringsToShorten: { name: string, value: string }[], ...vals: any[]) {
static piiSanitized(msg: any, objsToSanitize: { name: string, objOrArray: any | any[] }[], stringsToShorten: { name: string, value: string }[], ...vals: any[]) {
if (this.piiLogging) {
msg = [
msg,