mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Add support for custom endpoints (#23390)
* initial commit, add support for custom endpoints * add template file with public azure endpoints * add throw error, fix compile * update description * move custom provider to settings.json * cleanup * test * wip * try fix build error * wip fix build issue * add typings for package.json * test remove default * fix typings * fix typing * add object definitions * add additional checks * test define object * add default * remove default and extra checks * Organize code well to fix integration tests (#23697) * pr review updates * fix custom setting checker * fix default behavior * add more required, change name for default cloud * add one more required * modify required properties to match with api * Update extensions/azurecore/package.json Co-authored-by: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> * Update extensions/azurecore/package.json Co-authored-by: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> * pr review changes * remove default value from display name * make akv optional * remove default name * remove default * update descriptions, function names * add client ID * small fix * Update extensions/azurecore/package.nls.json Co-authored-by: Charles Gagnon <chgagnon@microsoft.com> * Update extensions/azurecore/package.json Co-authored-by: Charles Gagnon <chgagnon@microsoft.com> * updated names * add custom for configkey * providerSettingsJson -> customProviderSettings --------- Co-authored-by: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> Co-authored-by: Charles Gagnon <chgagnon@microsoft.com>
This commit is contained in:
@@ -72,9 +72,7 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
this.resources = [
|
||||
this.metadata.settings.armResource,
|
||||
this.metadata.settings.graphResource,
|
||||
this.metadata.settings.azureKeyVaultResource
|
||||
];
|
||||
|
||||
if (this.metadata.settings.sqlResource) {
|
||||
this.resources.push(this.metadata.settings.sqlResource);
|
||||
}
|
||||
@@ -90,6 +88,9 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
if (this.metadata.settings.azureLogAnalyticsResource) {
|
||||
this.resources.push(this.metadata.settings.azureLogAnalyticsResource);
|
||||
}
|
||||
if (this.metadata.settings.azureKeyVaultResource) {
|
||||
this.resources.push(this.metadata.settings.azureKeyVaultResource);
|
||||
}
|
||||
if (this.metadata.settings.azureKustoResource) {
|
||||
this.resources.push(this.metadata.settings.azureKustoResource);
|
||||
}
|
||||
|
||||
@@ -150,6 +150,11 @@ export class AzureAccountProviderService implements vscode.Disposable {
|
||||
if (!oldConfigValue && newConfigValue) {
|
||||
providerChanges.push(this.registerAccountProvider(provider));
|
||||
}
|
||||
|
||||
// Case 4: Provider was added from JSON - register provider
|
||||
if (provider.configKey !== 'enablePublicCloud' && provider.configKey !== 'enableUsGovCloud' && provider.configKey !== 'enableChinaCloud') {
|
||||
providerChanges.push(this.registerAccountProvider(provider));
|
||||
}
|
||||
}
|
||||
|
||||
// Process all the changes before continuing
|
||||
|
||||
@@ -5,6 +5,21 @@
|
||||
|
||||
import * as azurecore from 'azurecore';
|
||||
|
||||
export const enum SettingIds {
|
||||
marm = 'marm',
|
||||
graph = 'graph',
|
||||
msgraph = 'msgraph',
|
||||
arm = 'arm',
|
||||
sql = 'sql',
|
||||
ossrdbms = 'ossrdbms',
|
||||
vault = 'vault',
|
||||
ado = 'ado',
|
||||
ala = 'ala',
|
||||
storage = 'storage',
|
||||
kusto = 'kusto',
|
||||
powerbi = 'powerbi'
|
||||
}
|
||||
|
||||
/**
|
||||
* Mapping of configuration key with the metadata to instantiate the account provider
|
||||
*/
|
||||
@@ -20,6 +35,39 @@ export interface ProviderSettings {
|
||||
metadata: azurecore.AzureAccountProviderMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom Provider settings mapping
|
||||
*/
|
||||
export type ProviderSettingsJson = {
|
||||
name: string,
|
||||
settings: {
|
||||
configKey: string,
|
||||
metadata: {
|
||||
displayName: string,
|
||||
id: string,
|
||||
endpoints: {
|
||||
host: string,
|
||||
clientId: string,
|
||||
microsoftResource: string,
|
||||
graphResource: string,
|
||||
msGraphResource?: string,
|
||||
armResource: string,
|
||||
sqlResource: string,
|
||||
azureKeyVaultResource: string,
|
||||
azureLogAnalyticsResource?: string,
|
||||
azureStorageResource: {
|
||||
endpoint: string,
|
||||
endpointSuffix: string
|
||||
}
|
||||
azureKustoResource?: string,
|
||||
powerBiResource?: string,
|
||||
scopes: string,
|
||||
portalEndpoint?: string
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface Subscription {
|
||||
id: string,
|
||||
tenantId: string,
|
||||
|
||||
@@ -4,26 +4,12 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vscode-nls';
|
||||
import { ProviderSettings } from './interfaces';
|
||||
import { ProviderSettings, SettingIds } from './interfaces';
|
||||
import { AzureResource } from 'azdata';
|
||||
import { updateCustomCloudProviderSettings } from '../utils';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
const enum SettingIds {
|
||||
marm = 'marm',
|
||||
graph = 'graph',
|
||||
msgraph = 'msgraph',
|
||||
arm = 'arm',
|
||||
sql = 'sql',
|
||||
ossrdbms = 'ossrdbms',
|
||||
vault = 'vault',
|
||||
ado = 'ado',
|
||||
ala = 'ala',
|
||||
storage = 'storage',
|
||||
kusto = 'kusto',
|
||||
powerbi = 'powerbi'
|
||||
}
|
||||
|
||||
const publicAzureSettings: ProviderSettings = {
|
||||
configKey: 'enablePublicCloud',
|
||||
metadata: {
|
||||
@@ -246,5 +232,7 @@ const chinaAzureSettings: ProviderSettings = {
|
||||
}
|
||||
}
|
||||
};
|
||||
const allSettings = [publicAzureSettings, usGovAzureSettings, chinaAzureSettings];
|
||||
|
||||
let allSettings = [publicAzureSettings, usGovAzureSettings, chinaAzureSettings];
|
||||
allSettings = updateCustomCloudProviderSettings(allSettings);
|
||||
export default allSettings;
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"clouds": [
|
||||
{
|
||||
"name": "Azure Public",
|
||||
"settings": {
|
||||
"configKey": "enablePublicCloud",
|
||||
"metadata": {
|
||||
"displayName": "Azure Public Cloud",
|
||||
"id": "azure_publicCloud",
|
||||
"endpoints": {
|
||||
"host": "https://login.microsoftonline.com/",
|
||||
"microsoftResource": "https://management.core.windows.net/",
|
||||
"graphResource": "https://graph.windows.net/",
|
||||
"msGraphResource": "https://graph.microsoft.com/",
|
||||
"armResource": "https://management.azure.com/",
|
||||
"sqlResource": "https://database.windows.net/",
|
||||
"azureKeyVaultResource": "https://vault.azure.net/",
|
||||
"azureLogAnalyticsResource": "https://api.loganalytics.io/",
|
||||
"azureStorageResource": {
|
||||
"endpoint": "",
|
||||
"endpointSuffix": ".core.windows.net/"
|
||||
},
|
||||
"azureKustoResource": "https://kusto.kusto.windows.net/",
|
||||
"powerBiResource": "https://analysis.windows.net/powerbi/api/",
|
||||
"scopes": "https://management.azure.com/user_impersonation",
|
||||
"portalEndpoint": "https://portal.azure.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
4
extensions/azurecore/src/azurecore.d.ts
vendored
4
extensions/azurecore/src/azurecore.d.ts
vendored
@@ -91,7 +91,7 @@ declare module 'azurecore' {
|
||||
/**
|
||||
* Information that describes the Microsoft resource management resource
|
||||
*/
|
||||
microsoftResource?: Resource
|
||||
microsoftResource: Resource
|
||||
|
||||
/**
|
||||
* Information that describes the AAD graph resource
|
||||
@@ -121,7 +121,7 @@ declare module 'azurecore' {
|
||||
/**
|
||||
* Information that describes the Azure Key Vault resource
|
||||
*/
|
||||
azureKeyVaultResource: Resource;
|
||||
azureKeyVaultResource?: Resource;
|
||||
|
||||
/**
|
||||
* Information that describes the Azure Dev Ops resource
|
||||
|
||||
@@ -47,6 +47,10 @@ export const oldMsalCacheFileName = 'azureTokenCacheMsal-azure_publicCloud';
|
||||
|
||||
export const piiLogging = 'piiLogging';
|
||||
|
||||
export const CustomProviderSettings = 'customProviderSettings';
|
||||
|
||||
export const CustomProviderSettingsSection = AzureSection + '.' + CustomProviderSettings;
|
||||
|
||||
/** MSAL Account version */
|
||||
export const AccountVersion = '2.0';
|
||||
|
||||
|
||||
@@ -293,7 +293,7 @@ async function onDidChangeConfiguration(e: vscode.ConfigurationChangeEvent): Pro
|
||||
if (vscode.workspace.getConfiguration(Constants.AzureSection).get('authenticationLibrary') === 'ADAL') {
|
||||
void vscode.window.showInformationMessage(loc.deprecatedOption);
|
||||
}
|
||||
await utils.displayReloadAds(loc.reloadPrompt);
|
||||
await utils.displayReloadAds('authenticationLibrary');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,9 @@ export const location = localize('azurecore.location', "Location");
|
||||
export const subscription = localize('azurecore.subscription', "Subscription");
|
||||
export const typeIcon = localize('azurecore.typeIcon', "Type Icon");
|
||||
|
||||
export const reloadPrompt = localize('azurecore.reloadPrompt', "Authentication Library has changed, please reload Azure Data Studio.");
|
||||
export function reloadPrompt(sectionName: string): string {
|
||||
return localize('azurecore.reloadPrompt', "{0} setting changed, please reload Azure Data Studio.", sectionName);
|
||||
}
|
||||
export const reloadPromptCacheClear = localize('azurecore.reloadPromptCacheClear', "Token cache has been cleared successfully, please reload Azure Data Studio.");
|
||||
export const reloadChoice = localize('azurecore.reloadChoice', "Reload Azure Data Studio");
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
import * as loc from './localizedConstants';
|
||||
import * as vscode from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
import * as constants from './constants';
|
||||
|
||||
import { AzureRegion, azureResource } from 'azurecore';
|
||||
@@ -13,7 +14,11 @@ import { HttpClient } from './account-provider/auths/httpClient';
|
||||
import { parse } from 'url';
|
||||
import { getProxyAgentOptions } from './proxy';
|
||||
import { HttpsProxyAgentOptions } from 'https-proxy-agent';
|
||||
import { ProviderSettings, ProviderSettingsJson, SettingIds } from './account-provider/interfaces';
|
||||
import { AzureResource } from 'azdata';
|
||||
import { Logger } from './utils/Logger';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
const configProxy = 'proxy';
|
||||
const configProxyStrictSSL = 'proxyStrictSSL';
|
||||
const configProxyAuthorization = 'proxyAuthorization';
|
||||
@@ -161,6 +166,118 @@ export async function updateTenantIgnoreList(tenantIgnoreList: string[]): Promis
|
||||
await configuration.update(constants.Filter, tenantIgnoreList, vscode.ConfigurationTarget.Global);
|
||||
}
|
||||
|
||||
export function updateCustomCloudProviderSettings(defaultSettings: ProviderSettings[]): ProviderSettings[] {
|
||||
let providerSettingsJson: ProviderSettingsJson[] | undefined = vscode.workspace.getConfiguration(constants.AzureSection).get(constants.CustomProviderSettings) as ProviderSettingsJson[];
|
||||
vscode.workspace.onDidChangeConfiguration(async (changeEvent) => {
|
||||
const impactProvider = changeEvent.affectsConfiguration(constants.CustomProviderSettingsSection);
|
||||
if (impactProvider === true) {
|
||||
await displayReloadAds(constants.CustomProviderSettingsSection);
|
||||
}
|
||||
});
|
||||
if (providerSettingsJson && providerSettingsJson.length > 0) {
|
||||
try {
|
||||
for (let cloudProvider of providerSettingsJson) {
|
||||
// build provider setting
|
||||
let newSettings = buildCustomCloudProviderSettings(cloudProvider);
|
||||
defaultSettings.push(newSettings)
|
||||
Logger.info(`Custom provider settings loaded for ${cloudProvider.settings.metadata.displayName}`);
|
||||
}
|
||||
void vscode.window.showInformationMessage(localize('providerSettings.success', 'Successfully loaded custom endpoints from settings'));
|
||||
|
||||
} catch (error) {
|
||||
void vscode.window.showErrorMessage(localize('providerSettings.error', 'Could not load endpoints from settings, please check the logs for more details.'));
|
||||
console.error(error.message);
|
||||
throw Error(error.message);
|
||||
}
|
||||
}
|
||||
return defaultSettings;
|
||||
}
|
||||
|
||||
function buildCustomCloudProviderSettings(customProvider: ProviderSettingsJson): ProviderSettings {
|
||||
// build provider setting
|
||||
let newSettings: ProviderSettings = {
|
||||
configKey: 'enableCustom' + customProvider.settings.metadata.id,
|
||||
metadata: {
|
||||
displayName: customProvider.settings.metadata.displayName,
|
||||
id: customProvider.settings.metadata.id,
|
||||
settings: {
|
||||
host: customProvider.settings.metadata.endpoints.host,
|
||||
clientId: customProvider.settings.metadata.endpoints.clientId,
|
||||
microsoftResource: {
|
||||
id: SettingIds.marm,
|
||||
endpoint: customProvider.settings.metadata.endpoints.microsoftResource,
|
||||
azureResourceId: AzureResource.MicrosoftResourceManagement
|
||||
},
|
||||
armResource: {
|
||||
id: SettingIds.arm,
|
||||
endpoint: customProvider.settings.metadata.endpoints.armResource,
|
||||
azureResourceId: AzureResource.ResourceManagement
|
||||
},
|
||||
graphResource: {
|
||||
id: SettingIds.graph,
|
||||
endpoint: customProvider.settings.metadata.endpoints.graphResource,
|
||||
azureResourceId: AzureResource.Graph
|
||||
},
|
||||
azureStorageResource: {
|
||||
id: SettingIds.storage,
|
||||
endpoint: customProvider.settings.metadata.endpoints.azureStorageResource.endpoint,
|
||||
endpointSuffix: customProvider.settings.metadata.endpoints.azureStorageResource.endpointSuffix,
|
||||
azureResourceId: AzureResource.AzureStorage
|
||||
},
|
||||
sqlResource: {
|
||||
id: SettingIds.sql,
|
||||
endpoint: customProvider.settings.metadata.endpoints.sqlResource,
|
||||
azureResourceId: AzureResource.Sql
|
||||
},
|
||||
redirectUri: 'http://localhost',
|
||||
scopes: [
|
||||
'openid', 'email', 'profile', 'offline_access',
|
||||
customProvider.settings.metadata.endpoints.scopes
|
||||
],
|
||||
}
|
||||
}
|
||||
};
|
||||
if (customProvider.settings.metadata.endpoints.msGraphResource) {
|
||||
newSettings.metadata.settings.msGraphResource = {
|
||||
id: SettingIds.msgraph,
|
||||
endpoint: customProvider.settings.metadata.endpoints.msGraphResource,
|
||||
azureResourceId: AzureResource.MsGraph
|
||||
};
|
||||
}
|
||||
if (customProvider.settings.metadata.endpoints.azureLogAnalyticsResource) {
|
||||
newSettings.metadata.settings.azureLogAnalyticsResource = {
|
||||
id: SettingIds.ala,
|
||||
endpoint: customProvider.settings.metadata.endpoints.azureLogAnalyticsResource,
|
||||
azureResourceId: AzureResource.AzureLogAnalytics
|
||||
};
|
||||
}
|
||||
if (customProvider.settings.metadata.endpoints.azureKustoResource) {
|
||||
newSettings.metadata.settings.azureKustoResource = {
|
||||
id: SettingIds.kusto,
|
||||
endpoint: customProvider.settings.metadata.endpoints.azureKustoResource,
|
||||
azureResourceId: AzureResource.AzureKusto
|
||||
};
|
||||
}
|
||||
if (customProvider.settings.metadata.endpoints.azureKeyVaultResource) {
|
||||
newSettings.metadata.settings.azureKeyVaultResource = {
|
||||
id: SettingIds.vault,
|
||||
endpoint: customProvider.settings.metadata.endpoints.azureKeyVaultResource,
|
||||
azureResourceId: AzureResource.AzureKeyVault
|
||||
};
|
||||
}
|
||||
if (customProvider.settings.metadata.endpoints.powerBiResource) {
|
||||
newSettings.metadata.settings.powerBiResource = {
|
||||
id: SettingIds.powerbi,
|
||||
endpoint: customProvider.settings.metadata.endpoints.powerBiResource,
|
||||
azureResourceId: AzureResource.PowerBi
|
||||
};
|
||||
}
|
||||
if (customProvider.settings.metadata.endpoints.portalEndpoint) {
|
||||
newSettings.metadata.settings.portalEndpoint = customProvider.settings.metadata.endpoints.portalEndpoint;
|
||||
}
|
||||
return newSettings;
|
||||
}
|
||||
|
||||
export function getResourceTypeIcon(appContext: AppContext, type: string): string {
|
||||
switch (type) {
|
||||
case azureResource.AzureResourceType.sqlServer:
|
||||
@@ -201,12 +318,13 @@ export function getProxyEnabledHttpClient(): HttpClient {
|
||||
return new HttpClient(proxy, agentOptions);
|
||||
}
|
||||
|
||||
/* Display notification with button to reload
|
||||
* return true if button clicked
|
||||
* return false if button not clicked
|
||||
/**
|
||||
* Display notification with button to reload
|
||||
* @param sectionName Name of section to reload
|
||||
* @returns true if reload clicked, false otherwise.
|
||||
*/
|
||||
export async function displayReloadAds(message: string): Promise<boolean> {
|
||||
const result = await vscode.window.showInformationMessage(message, loc.reloadChoice);
|
||||
export async function displayReloadAds(sectionName: string): Promise<boolean> {
|
||||
const result = await vscode.window.showInformationMessage(loc.reloadPrompt(sectionName), loc.reloadChoice);
|
||||
if (result === loc.reloadChoice) {
|
||||
await vscode.commands.executeCommand('workbench.action.reloadWindow');
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user