Modify connection management to support Active Directory authType for non-SQL DBs (#8434)

* First attempt to add Azure MFA login for PostgreSQL

* Finish merge with master

* Fix auth type default selection

* Add AzureMFAAndUser auth type for Orcas

* Fix formatting

* Update change log

* Incorporate some review comments

* Missed an occurrence of AzureResource

* Try to move all changes out of azdata.d.ts and sqlops.d.ts

* Concrete implementation of ConnectionProfile in azdata no longer has azureAccount

* Use enum names instead of numbers in config files
This commit is contained in:
Rich Smith
2019-11-26 10:32:59 -08:00
committed by Karl Burtram
parent d9997cebfc
commit b631530753
20 changed files with 231 additions and 52 deletions

View File

@@ -72,6 +72,8 @@ export class ConnectionManagementService extends Disposable implements IConnecti
private _mementoContext: Memento;
private _mementoObj: any;
private static readonly CONNECTION_MEMENTO = 'ConnectionManagement';
private static readonly _azureResources: AzureResource[] =
[AzureResource.ResourceManagement, AzureResource.Sql, AzureResource.OssRdbms];
constructor(
private _connectionStore: ConnectionStore,
@@ -700,22 +702,40 @@ export class ConnectionManagementService extends Disposable implements IConnecti
return defaultProvider && this._providers.has(defaultProvider) ? defaultProvider : undefined;
}
/**
* Previously, the only resource available for AAD access tokens was for Azure SQL / SQL Server.
* Use that as a default if the provider extension does not configure a different one. If one is
* configured, then use it.
* @param connection The connection to fill in or update
*/
private getAzureResourceForConnection(connection: interfaces.IConnectionProfile): azdata.AzureResource {
let provider = this._providers.get(connection.providerName);
if (!provider || !provider.properties || !provider.properties.azureResource) {
return AzureResource.Sql;
}
let result = find(ConnectionManagementService._azureResources, r => AzureResource[r] === provider.properties.azureResource);
return result ? result : AzureResource.Sql;
}
/**
* Fills in the Azure account token if it's needed for this connection and doesn't already have one
* and clears it if it isn't.
* @param connection The connection to fill in or update
*/
private async fillInOrClearAzureToken(connection: interfaces.IConnectionProfile): Promise<boolean> {
if (connection.authenticationType !== Constants.azureMFA) {
if (connection.authenticationType !== Constants.azureMFA && connection.authenticationType !== Constants.azureMFAAndUser) {
connection.options['azureAccountToken'] = undefined;
return true;
}
if (connection.options['azureAccountToken']) {
return true;
}
let azureResource = this.getAzureResourceForConnection(connection);
let accounts = await this._accountManagementService.getAccountsForProvider('azurePublicCloud');
if (accounts && accounts.length > 0) {
let account = find(accounts, account => account.key.accountId === connection.userName);
let accountName = (connection.authenticationType !== Constants.azureMFA) ? connection.azureAccount : connection.userName;
let account = find(accounts, account => account.key.accountId === accountName);
if (account) {
if (account.isStale) {
try {
@@ -725,7 +745,7 @@ export class ConnectionManagementService extends Disposable implements IConnecti
return false;
}
}
let tokensByTenant = await this._accountManagementService.getSecurityToken(account, AzureResource.Sql);
let tokensByTenant = await this._accountManagementService.getSecurityToken(account, azureResource);
let token: string;
let tenantId = connection.azureTenantId;
if (tenantId && tokensByTenant[tenantId]) {