mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-01 17:23:35 -05:00
Initial commit for dSTS Auth (#13802)
* Initial commit for dSTS Auth * Removed getDstsToken from accountManagementService. Renamed azureAccount to token. * Renamed dstsToken to _token in connectionWidget * Code Review Feedback. Renamed token to authToken in onFetchDatabases. * Removed dsts options from Kusto package.json
This commit is contained in:
@@ -47,8 +47,8 @@ export class ConnectionController implements IConnectionComponentController {
|
||||
onCreateNewServerGroup: () => this.onCreateNewServerGroup(),
|
||||
onAdvancedProperties: () => this.handleOnAdvancedProperties(),
|
||||
onSetAzureTimeOut: () => this.handleonSetAzureTimeOut(),
|
||||
onFetchDatabases: (serverName: string, authenticationType: string, userName?: string, password?: string, azureAccount?: string) => this.onFetchDatabases(
|
||||
serverName, authenticationType, userName, password, azureAccount).then(result => {
|
||||
onFetchDatabases: (serverName: string, authenticationType: string, userName?: string, password?: string, authToken?: string) => this.onFetchDatabases(
|
||||
serverName, authenticationType, userName, password, authToken).then(result => {
|
||||
return result;
|
||||
}),
|
||||
onAzureTenantSelection: (azureTenantId?: string) => this.onAzureTenantSelection(azureTenantId),
|
||||
@@ -56,7 +56,7 @@ export class ConnectionController implements IConnectionComponentController {
|
||||
this._providerName = providerName;
|
||||
}
|
||||
|
||||
protected async onFetchDatabases(serverName: string, authenticationType: string, userName?: string, password?: string, azureAccount?: string): Promise<string[]> {
|
||||
protected async onFetchDatabases(serverName: string, authenticationType: string, userName?: string, password?: string, authToken?: string): Promise<string[]> {
|
||||
let tempProfile = this._model;
|
||||
tempProfile.serverName = serverName;
|
||||
tempProfile.authenticationType = authenticationType;
|
||||
@@ -64,7 +64,7 @@ export class ConnectionController implements IConnectionComponentController {
|
||||
tempProfile.password = password;
|
||||
tempProfile.groupFullName = '';
|
||||
tempProfile.saveProfile = false;
|
||||
tempProfile.azureAccount = azureAccount;
|
||||
tempProfile.azureAccount = authToken;
|
||||
let uri = this._connectionManagementService.getConnectionUri(tempProfile);
|
||||
if (this._databaseCache.has(uri)) {
|
||||
let cachedDatabases: string[] = this._databaseCache.get(uri);
|
||||
|
||||
@@ -42,7 +42,7 @@ export interface IConnectionComponentCallbacks {
|
||||
onCreateNewServerGroup?: () => void;
|
||||
onAdvancedProperties?: () => void;
|
||||
onSetAzureTimeOut?: () => void;
|
||||
onFetchDatabases?: (serverName: string, authenticationType: string, userName?: string, password?: string, azureAccount?: string) => Promise<string[]>;
|
||||
onFetchDatabases?: (serverName: string, authenticationType: string, userName?: string, password?: string, token?: string) => Promise<string[]>;
|
||||
onAzureTenantSelection?: (azureTenantId?: string) => void;
|
||||
}
|
||||
|
||||
|
||||
@@ -251,7 +251,7 @@ export class ConnectionManagementService extends Disposable implements IConnecti
|
||||
* @param connectionProfile Connection Profile
|
||||
*/
|
||||
public async addSavedPassword(connectionProfile: interfaces.IConnectionProfile): Promise<interfaces.IConnectionProfile> {
|
||||
await this.fillInOrClearAzureToken(connectionProfile);
|
||||
await this.fillInOrClearToken(connectionProfile);
|
||||
return this._connectionStore.addSavedPassword(connectionProfile).then(result => result.profile);
|
||||
}
|
||||
|
||||
@@ -310,7 +310,7 @@ 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.fillInOrClearAzureToken(newConnection);
|
||||
let tokenFillSuccess = await this.fillInOrClearToken(newConnection);
|
||||
|
||||
// If the password is required and still not loaded show the dialog
|
||||
if ((!foundPassword && this._connectionStore.isPasswordRequired(newConnection) && !newConnection.password) || !tokenFillSuccess) {
|
||||
@@ -468,7 +468,7 @@ export class ConnectionManagementService extends Disposable implements IConnecti
|
||||
if (callbacks.onConnectStart) {
|
||||
callbacks.onConnectStart();
|
||||
}
|
||||
let tokenFillSuccess = await this.fillInOrClearAzureToken(connection);
|
||||
let tokenFillSuccess = await this.fillInOrClearToken(connection);
|
||||
if (!tokenFillSuccess) {
|
||||
throw new Error(nls.localize('connection.noAzureAccount', "Failed to get Azure account token for connection"));
|
||||
}
|
||||
@@ -803,17 +803,38 @@ export class ConnectionManagementService extends Disposable implements IConnecti
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills in the Azure account token if it's needed for this connection and doesn't already have one
|
||||
* Fills in the 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 && connection.authenticationType !== Constants.azureMFAAndUser) {
|
||||
private async fillInOrClearToken(connection: interfaces.IConnectionProfile): Promise<boolean> {
|
||||
if (connection.authenticationType !== Constants.azureMFA
|
||||
&& connection.authenticationType !== Constants.azureMFAAndUser
|
||||
&& connection.authenticationType !== Constants.dstsAuth) {
|
||||
connection.options['azureAccountToken'] = undefined;
|
||||
return true;
|
||||
}
|
||||
|
||||
let azureResource = this.getAzureResourceForConnection(connection);
|
||||
const accounts = await this._accountManagementService.getAccounts();
|
||||
|
||||
if (connection.authenticationType === Constants.dstsAuth) {
|
||||
let dstsAccounts = accounts.filter(a => a.key.providerId.startsWith('dstsAuth'));
|
||||
if (dstsAccounts.length <= 0) {
|
||||
connection.options['azureAccountToken'] = undefined;
|
||||
return false;
|
||||
}
|
||||
|
||||
dstsAccounts[0].key.providerArgs = {
|
||||
serverName: connection.serverName,
|
||||
databaseName: connection.databaseName
|
||||
};
|
||||
|
||||
let tokenPromise = await this._accountManagementService.getAccountSecurityToken(dstsAccounts[0], undefined, undefined);
|
||||
connection.options['azureAccountToken'] = tokenPromise.token;
|
||||
return true;
|
||||
}
|
||||
|
||||
const azureAccounts = accounts.filter(a => a.key.providerId.startsWith('azure'));
|
||||
if (azureAccounts && azureAccounts.length > 0) {
|
||||
let accountId = (connection.authenticationType === Constants.azureMFA || connection.authenticationType === Constants.azureMFAAndUser) ? connection.azureAccount : connection.userName;
|
||||
|
||||
@@ -40,7 +40,8 @@ export enum AuthenticationType {
|
||||
SqlLogin = 'SqlLogin',
|
||||
Integrated = 'Integrated',
|
||||
AzureMFA = 'AzureMFA',
|
||||
AzureMFAAndUser = 'AzureMFAAndUser'
|
||||
AzureMFAAndUser = 'AzureMFAAndUser',
|
||||
dSTSAuth = 'dstsAuth'
|
||||
}
|
||||
|
||||
export class ConnectionWidget extends lifecycle.Disposable {
|
||||
@@ -65,6 +66,7 @@ export class ConnectionWidget extends lifecycle.Disposable {
|
||||
private _defaultDatabaseName: string = localize('defaultDatabaseOption', "<Default>");
|
||||
private _loadingDatabaseName: string = localize('loadingDatabaseOption', "Loading...");
|
||||
private _serverGroupDisplayString: string = localize('serverGroup', "Server group");
|
||||
private _token: string;
|
||||
protected _container: HTMLElement;
|
||||
protected _serverGroupSelectBox: SelectBox;
|
||||
protected _authTypeSelectBox: SelectBox;
|
||||
@@ -75,7 +77,7 @@ export class ConnectionWidget extends lifecycle.Disposable {
|
||||
protected _databaseNameInputBox: Dropdown;
|
||||
protected _advancedButton: Button;
|
||||
private static readonly _authTypes: AuthenticationType[] =
|
||||
[AuthenticationType.AzureMFA, AuthenticationType.AzureMFAAndUser, AuthenticationType.Integrated, AuthenticationType.SqlLogin];
|
||||
[AuthenticationType.AzureMFA, AuthenticationType.AzureMFAAndUser, AuthenticationType.Integrated, AuthenticationType.SqlLogin, AuthenticationType.dSTSAuth];
|
||||
private static readonly _osByName = {
|
||||
Windows: OperatingSystem.Windows,
|
||||
Macintosh: OperatingSystem.Macintosh,
|
||||
@@ -364,7 +366,7 @@ export class ConnectionWidget extends lifecycle.Disposable {
|
||||
this._databaseDropdownExpanded = true;
|
||||
if (this.serverName) {
|
||||
this._databaseNameInputBox.values = [this._loadingDatabaseName];
|
||||
this._callbacks.onFetchDatabases(this.serverName, this.authenticationType, this.userName, this._password, this.azureAccount).then(databases => {
|
||||
this._callbacks.onFetchDatabases(this.serverName, this.authenticationType, this.userName, this._password, this.authToken).then(databases => {
|
||||
if (databases) {
|
||||
this._databaseNameInputBox.values = databases.sort((a, b) => a.localeCompare(b));
|
||||
} else {
|
||||
@@ -504,6 +506,22 @@ export class ConnectionWidget extends lifecycle.Disposable {
|
||||
this._tableContainer.classList.remove('hide-username');
|
||||
this._tableContainer.classList.add('hide-password');
|
||||
this._tableContainer.classList.remove('hide-azure-accounts');
|
||||
} else if (currentAuthType === AuthenticationType.dSTSAuth) {
|
||||
this._accountManagementService.getAccountsForProvider('dstsAuth').then(accounts => {
|
||||
if (accounts && accounts.length > 0) {
|
||||
accounts[0].key.providerArgs = {
|
||||
serverName: this.serverName,
|
||||
databaseName: this.databaseName
|
||||
};
|
||||
|
||||
this._accountManagementService.getAccountSecurityToken(accounts[0], undefined, undefined).then(securityToken => {
|
||||
this._token = securityToken.token;
|
||||
});
|
||||
}
|
||||
});
|
||||
this._tableContainer.classList.add('hide-username');
|
||||
this._tableContainer.classList.add('hide-password');
|
||||
this._tableContainer.classList.add('hide-azure-accounts');
|
||||
} else {
|
||||
this._azureAccountDropdown.disable();
|
||||
this._azureAccountDropdown.hideMessage();
|
||||
@@ -826,8 +844,14 @@ export class ConnectionWidget extends lifecycle.Disposable {
|
||||
return this._authTypeSelectBox ? this.getAuthTypeName(this._authTypeSelectBox.value) : undefined;
|
||||
}
|
||||
|
||||
public get azureAccount(): string {
|
||||
return this.authenticationType === AuthenticationType.AzureMFAAndUser || this.authenticationType === AuthenticationType.AzureMFA ? this._azureAccountDropdown.value : undefined;
|
||||
public get authToken(): string | undefined {
|
||||
if (this.authenticationType === AuthenticationType.AzureMFAAndUser || this.authenticationType === AuthenticationType.AzureMFA) {
|
||||
return this._azureAccountDropdown.value;
|
||||
}
|
||||
if (this.authenticationType === AuthenticationType.dSTSAuth) {
|
||||
return this._token;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private validateAzureAccountSelection(showMessage: boolean = true): boolean {
|
||||
@@ -883,7 +907,7 @@ export class ConnectionWidget extends lifecycle.Disposable {
|
||||
model.userName = this.userName;
|
||||
model.password = this.password;
|
||||
model.authenticationType = this.authenticationType;
|
||||
model.azureAccount = this.azureAccount;
|
||||
model.azureAccount = this.authToken;
|
||||
model.savePassword = this._rememberPasswordCheckBox.checked;
|
||||
model.connectionName = this.connectionName;
|
||||
model.databaseName = this.databaseName;
|
||||
|
||||
Reference in New Issue
Block a user