Skip to content

Commit

Permalink
Add default auth type configuration setting for Azure resources (micr…
Browse files Browse the repository at this point in the history
…osoft#16999)

* Adding user config for default auth type

* adding feature

* removing the SqlLogin default from the model

* fixing bug, removing dead code

* removing unneeded instance of configurationService

* fixing line break

* removing extra parameter

* removing comments

* Fix test breaks

* Fix build break

* More breaks

* Address code review feedback

Co-authored-by: Troy Witthoeft <[email protected]>
  • Loading branch information
kburtram and TroyWitthoeft authored Sep 8, 2021
1 parent e9c48da commit 73ee6c3
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export class AzureResourceDatabaseTreeDataProvider extends ResourceTreeDataProvi
databaseName: database.name,
userName: database.loginName,
password: '',
authenticationType: 'SqlLogin',
authenticationType: '',
savePassword: true,
groupFullName: '',
groupId: '',
Expand Down
5 changes: 5 additions & 0 deletions src/sql/platform/connection/common/connectionManagement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,11 @@ export interface IConnectionManagementService {

getUniqueConnectionProvidersByNameMap(providerNameToDisplayNameMap: { [providerDisplayName: string]: string }): { [providerDisplayName: string]: string };

/**
* Gets the default authentication type from the configuration service
*/
getDefaultAuthenticationTypeId(): string;

/**
* Cancels the connection
*/
Expand Down
3 changes: 3 additions & 0 deletions src/sql/platform/connection/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ export const defaultEngine = 'defaultEngine';

export const passwordChars = '***************';

/* default authentication type setting name*/
export const defaultAuthenticationType = 'defaultAuthenticationType';

/* authentication types */
export const sqlLogin = 'SqlLogin';
export const integrated = 'Integrated';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,11 @@ export class TestConnectionManagementService implements IConnectionManagementSer
return undefined!;
}

getDefaultAuthenticationTypeId(): string {
return undefined!;
}


getConnections(activeConnectionsOnly?: boolean): ConnectionProfile[] {
return [];
}
Expand Down
2 changes: 1 addition & 1 deletion src/sql/workbench/common/sqlWorkbenchUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ export function getSqlConfigSection(workspaceConfigService: IConfigurationServic

export function getSqlConfigValue<T>(workspaceConfigService: IConfigurationService, configName: string): T {
let config = workspaceConfigService.getValue<{ [key: string]: any }>(ConnectionConstants.sqlConfigSectionName);
return config[configName];
return config ? config[configName] : undefined;
}
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,18 @@ configurationRegistry.registerConfiguration({
'default': 25,
'description': localize('sql.maxRecentConnectionsDescription', "The maximum number of recently used connections to store in the connection list.")
},
'sql.defaultAuthenticationType': {
'type': 'string',
'enum': ['SqlLogin', 'AzureMFA', `AzureMFAAndUser`, 'Integrated'],
'description': localize('sql.defaultAuthenticationTypeDescription', "Default authentication type to use when connecting to Azure resources. "),
'enumDescriptions': [
localize('sql.defaultAuthenticationType.SqlLogin', "Sql Login"),
localize('sql.defaultAuthenticationType.AzureMFA', "Azure Active Directory - Universal with MFA support"),
localize('sql.defaultAuthenticationType.AzureMFAAndUser', "Azure Active Directory - Password"),
localize('sql.defaultAuthenticationType.Integrated', "Windows Authentication"),
],
'default': 'AzureMFA'
},
'sql.defaultEngine': {
'type': 'string',
'description': localize('sql.defaultEngineDescription', "Default SQL Engine to use. This drives default language provider in .sql files and the default to use when creating a new connection."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,16 @@ export class ConnectionDialogService implements IConnectionDialogService {
return defaultProvider || Constants.mssqlProviderName;
}

private getDefaultAuthenticationTypeName(): string {
let defaultAuthenticationType: string;
if (!defaultAuthenticationType && this._configurationService) {
defaultAuthenticationType = WorkbenchUtils.getSqlConfigValue<string>(this._configurationService, Constants.defaultAuthenticationType);
}

return defaultAuthenticationType || Constants.sqlLogin; // as a fallback, default to sql login if the value from settings is not available

}

private handleOnConnect(params: INewConnectionParams, profile?: IConnectionProfile): void {
this._logService.debug('ConnectionDialogService: onConnect event is received');
if (!this._connecting) {
Expand Down Expand Up @@ -383,6 +393,14 @@ export class ConnectionDialogService implements IConnectionDialogService {
if (model && !model.providerName) {
model.providerName = providerName;
}

const defaultAuthenticationType = this.getDefaultAuthenticationTypeName();
let authenticationTypeName = model ? model.authenticationType : defaultAuthenticationType;
authenticationTypeName = authenticationTypeName ? authenticationTypeName : defaultAuthenticationType;
if (model && !model.authenticationType) {
model.authenticationType = authenticationTypeName;
}

let newProfile = new ConnectionProfile(this._capabilitiesService, model || providerName);
newProfile.saveProfile = true;
newProfile.generateNewId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,11 @@ export class ConnectionManagementService extends Disposable implements IConnecti
// Fill in the Azure account token if needed and open the connection dialog if it fails
let tokenFillSuccess = await this.fillInOrClearToken(newConnection);

// If there is no authentication type set, set it using configuration
if (!newConnection.authenticationType || newConnection.authenticationType === '') {
newConnection.authenticationType = this.getDefaultAuthenticationTypeId();
}

// If the password is required and still not loaded show the dialog
if ((!foundPassword && this._connectionStore.isPasswordRequired(newConnection) && !newConnection.password) || !tokenFillSuccess) {
return this.showConnectionDialogOnError(connection, owner, { connected: false, errorMessage: undefined, callStack: undefined, errorCode: undefined }, options);
Expand Down Expand Up @@ -792,6 +797,11 @@ export class ConnectionManagementService extends Disposable implements IConnecti
return defaultProvider && this._providers.has(defaultProvider) ? defaultProvider : undefined;
}

public getDefaultAuthenticationTypeId(): string {
let defaultAuthenticationType = WorkbenchUtils.getSqlConfigValue<string>(this._configurationService, Constants.defaultAuthenticationType);
return defaultAuthenticationType;
}

/**
* 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import * as azdata from 'azdata';
import * as WorkbenchUtils from 'sql/workbench/common/sqlWorkbenchUtils';
import { TreeNode } from 'sql/workbench/services/objectExplorer/common/treeNode';
import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService';
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
Expand All @@ -14,6 +15,7 @@ import { hash } from 'vs/base/common/hash';
import { Disposable } from 'vs/base/common/lifecycle';
import { generateUuid } from 'vs/base/common/uuid';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; //TODO: Needed?
import { TreeItemCollapsibleState } from 'vs/workbench/common/views';
import { localize } from 'vs/nls';
import { NodeType } from 'sql/workbench/services/objectExplorer/common/nodeType';
Expand Down Expand Up @@ -41,7 +43,8 @@ export class OEShimService extends Disposable implements IOEShimService {
constructor(
@IObjectExplorerService private oe: IObjectExplorerService,
@IConnectionManagementService private cm: IConnectionManagementService,
@ICapabilitiesService private capabilities: ICapabilitiesService
@ICapabilitiesService private capabilities: ICapabilitiesService,
@IConfigurationService private configurationService: IConfigurationService
) {
super();
}
Expand Down Expand Up @@ -133,6 +136,10 @@ export class OEShimService extends Disposable implements IOEShimService {

public async getChildren(node: ITreeItem, viewId: string): Promise<ITreeItem[]> {
if (node.payload) {
if (node.payload.authenticationType !== undefined && node.payload.authenticationType === '') {
node.payload.authenticationType = this.getDefaultAuthenticationType(this.configurationService); // we need to set auth type here, because it's value is part of the session key
}

const sessionId = await this.getOrCreateSession(viewId, node);
const requestHandle = this.nodeHandleMap.get(generateNodeMapKey(viewId, node)) || node.handle;
const treeNode = new TreeNode(undefined!, undefined!, undefined!, requestHandle, undefined!); // hack since this entire system is a hack anyways
Expand Down Expand Up @@ -222,6 +229,10 @@ export class OEShimService extends Disposable implements IOEShimService {
}
return undefined;
}

public getDefaultAuthenticationType(configurationService: IConfigurationService): string {
return WorkbenchUtils.getSqlConfigValue<string>(configurationService, 'defaultAuthenticationType');
}
}

function generateSessionMapKey(viewId: string, node: ITreeItem): number {
Expand Down

0 comments on commit 73ee6c3

Please sign in to comment.