mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-12 11:08:31 -05:00
Security: Added user setting for extension policies (#2426)
* added user setting for extension policy * fix extension action tests
This commit is contained in:
committed by
Karl Burtram
parent
2b4de52af4
commit
9ea02bf125
@@ -24,6 +24,9 @@ import { readFile } from 'vs/base/node/pfs';
|
||||
import { writeFileAndFlushSync } from 'vs/base/node/extfs';
|
||||
import { generateUuid, isUUID } from 'vs/base/common/uuid';
|
||||
import { values } from 'vs/base/common/map';
|
||||
// {{SQL CARBON EDIT}}
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ExtensionsPolicy, ExtensionsPolicyKey } from 'vs/workbench/parts/extensions/common/extensions';
|
||||
|
||||
interface IRawGalleryExtensionFile {
|
||||
assetType: string;
|
||||
@@ -367,7 +370,9 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
|
||||
constructor(
|
||||
@IRequestService private requestService: IRequestService,
|
||||
@IEnvironmentService private environmentService: IEnvironmentService,
|
||||
@ITelemetryService private telemetryService: ITelemetryService
|
||||
@ITelemetryService private telemetryService: ITelemetryService,
|
||||
// {{SQL CARBON EDIT}}
|
||||
@IConfigurationService private configurationService: IConfigurationService
|
||||
) {
|
||||
const config = product.extensionsGallery;
|
||||
this.extensionsGalleryUrl = config && config.serviceUrl;
|
||||
@@ -508,6 +513,12 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
|
||||
}
|
||||
|
||||
let actualTotal = filteredExtensions.length;
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
let extensionPolicy = this.configurationService.getValue<string>(ExtensionsPolicyKey);
|
||||
if (extensionPolicy === ExtensionsPolicy.allowMicrosoft) {
|
||||
filteredExtensions = filteredExtensions.filter(ext => ext.publisher && ext.publisher.displayName === 'Microsoft');
|
||||
}
|
||||
return { galleryExtensions: filteredExtensions, total: actualTotal };
|
||||
}
|
||||
|
||||
@@ -551,7 +562,9 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
|
||||
headers
|
||||
}).then(context => {
|
||||
|
||||
if (context.res.statusCode >= 400 && context.res.statusCode < 500) {
|
||||
// {{SQL CARBON EDIT}}
|
||||
let extensionPolicy: string = this.configurationService.getValue<string>(ExtensionsPolicyKey);
|
||||
if (context.res.statusCode >= 400 && context.res.statusCode < 500 || extensionPolicy === ExtensionsPolicy.allowNone) {
|
||||
return { galleryExtensions: [], total: 0 };
|
||||
}
|
||||
|
||||
|
||||
@@ -101,6 +101,8 @@ export const AutoUpdateConfigurationKey = 'extensions.autoUpdate';
|
||||
export const AutoCheckUpdatesConfigurationKey = 'extensions.autoCheckUpdates';
|
||||
export const ShowRecommendationsOnlyOnDemandKey = 'extensions.showRecommendationsOnlyOnDemand';
|
||||
export const CloseExtensionDetailsOnViewChangeKey = 'extensions.closeExtensionDetailsOnViewChange';
|
||||
// {{SQL CARBON EDIT}}
|
||||
export const ExtensionsPolicyKey = 'extensions.extensionsPolicy';
|
||||
|
||||
export interface IExtensionsConfiguration {
|
||||
autoUpdate: boolean;
|
||||
@@ -108,4 +110,13 @@ export interface IExtensionsConfiguration {
|
||||
ignoreRecommendations: boolean;
|
||||
showRecommendationsOnlyOnDemand: boolean;
|
||||
closeExtensionDetailsOnViewChange: boolean;
|
||||
// {{SQL CARBON EDIT}}
|
||||
extensionsPolicy: string;
|
||||
}
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
export enum ExtensionsPolicy {
|
||||
allowAll = 'allowAll',
|
||||
allowNone = 'allowNone',
|
||||
allowMicrosoft = 'allowMicrosoft'
|
||||
}
|
||||
@@ -23,7 +23,8 @@ import { ShowRecommendedExtensionsAction, InstallWorkspaceRecommendedExtensionsA
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { IWorkspaceContextService, IWorkspaceFolder, IWorkspace, IWorkspaceFoldersChangeEvent, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { IExtensionsConfiguration, ConfigurationKey, ShowRecommendationsOnlyOnDemandKey, IExtensionsViewlet } from 'vs/workbench/parts/extensions/common/extensions';
|
||||
// {{SQL CARBON EDIT}}
|
||||
import { IExtensionsConfiguration, ConfigurationKey, ShowRecommendationsOnlyOnDemandKey, IExtensionsViewlet, ExtensionsPolicyKey, ExtensionsPolicy } from 'vs/workbench/parts/extensions/common/extensions';
|
||||
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import * as pfs from 'vs/base/node/pfs';
|
||||
@@ -111,7 +112,9 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
|
||||
) {
|
||||
super();
|
||||
|
||||
if (!this.isEnabled()) {
|
||||
// {{SQL CARBON EDIT}}
|
||||
let extensionPolicy: string = this.configurationService.getValue<string>(ExtensionsPolicyKey);
|
||||
if (!this.isEnabled() || extensionPolicy === ExtensionsPolicy.allowNone) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,8 @@ import { ExtensionTipsService } from 'vs/workbench/parts/extensions/electron-bro
|
||||
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
|
||||
import { IOutputChannelRegistry, Extensions as OutputExtensions } from 'vs/workbench/parts/output/common/output';
|
||||
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
import { VIEWLET_ID, IExtensionsWorkbenchService } from '../common/extensions';
|
||||
// {{SQL CARBON EDIT}}
|
||||
import { VIEWLET_ID, IExtensionsWorkbenchService, ExtensionsPolicy } from '../common/extensions';
|
||||
import { ExtensionsWorkbenchService } from 'vs/workbench/parts/extensions/node/extensionsWorkbenchService';
|
||||
import {
|
||||
OpenExtensionsViewletAction, InstallExtensionsAction, ShowOutdatedExtensionsAction, ShowRecommendedExtensionsAction, ShowRecommendedKeymapExtensionsAction, ShowPopularExtensionsAction,
|
||||
@@ -231,6 +232,13 @@ Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration)
|
||||
type: 'boolean',
|
||||
description: localize('extensionsCloseExtensionDetailsOnViewChange', "When enabled, editors with extension details will be automatically closed upon navigating away from the Extensions View."),
|
||||
default: false
|
||||
},
|
||||
// {{SQL CARBON EDIT}}
|
||||
'extensions.extensionsPolicy': {
|
||||
type: 'string',
|
||||
description: localize('extensionsPolicy', "Sets the security policy for downloading extensions."),
|
||||
scope: ConfigurationScope.APPLICATION,
|
||||
default: ExtensionsPolicy.allowAll
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -16,7 +16,8 @@ import * as json from 'vs/base/common/json';
|
||||
import { ActionItem, IActionItem, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IExtension, ExtensionState, IExtensionsWorkbenchService, VIEWLET_ID, IExtensionsViewlet, AutoUpdateConfigurationKey } from 'vs/workbench/parts/extensions/common/extensions';
|
||||
// {{SQL CARBON EDIT}}
|
||||
import { IExtension, ExtensionState, IExtensionsWorkbenchService, VIEWLET_ID, IExtensionsViewlet, AutoUpdateConfigurationKey, ExtensionsPolicyKey, ExtensionsPolicy } from 'vs/workbench/parts/extensions/common/extensions';
|
||||
import { ExtensionsConfigurationInitialContent } from 'vs/workbench/parts/extensions/common/extensionsFileTemplate';
|
||||
import { LocalExtensionType, IExtensionEnablementService, IExtensionTipsService, EnablementState, ExtensionsLabel, IExtensionManagementServer, IExtensionManagementServerService, IExtensionRecommendation, ExtensionRecommendationSource, IExtensionGalleryService, IGalleryExtension, ILocalExtension, IExtensionsConfigContent } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
@@ -2660,72 +2661,82 @@ export class InstallVSIXAction extends Action {
|
||||
@INotificationService private notificationService: INotificationService,
|
||||
@IWindowService private windowService: IWindowService,
|
||||
// {{SQL CARBON EDIT}}
|
||||
@IConfigurationService private configurationService: IConfigurationService,
|
||||
@IStorageService private storageService: IStorageService
|
||||
) {
|
||||
super(id, label, 'extension-action install-vsix', true);
|
||||
}
|
||||
|
||||
run(): TPromise<any> {
|
||||
return this.windowService.showOpenDialog({
|
||||
title: localize('installFromVSIX', "Install from VSIX"),
|
||||
filters: [{ name: 'VSIX Extensions', extensions: ['vsix'] }],
|
||||
properties: ['openFile'],
|
||||
buttonLabel: mnemonicButtonLabel(localize({ key: 'installButton', comment: ['&& denotes a mnemonic'] }, "&&Install"))
|
||||
}).then(result => {
|
||||
if (!result) {
|
||||
return TPromise.as(null);
|
||||
}
|
||||
return TPromise.join(result.map(vsix => {
|
||||
// {{SQL CARBON EDIT}}
|
||||
if (!this.storageService.getBoolean(vsix)) {
|
||||
this.notificationService.prompt(
|
||||
Severity.Warning,
|
||||
localize('thirdPartyExtension.vsix', 'This is a third party extension and might involve security risks. Are you sure you want to install this extension?'),
|
||||
[
|
||||
{
|
||||
label: localize('thirdPartExt.yes', 'Yes'),
|
||||
run: () => {
|
||||
this.extensionsWorkbenchService.install(vsix).then(() => {
|
||||
this.notificationService.prompt(
|
||||
Severity.Info,
|
||||
localize('InstallVSIXAction.success', "Successfully installed the extension. Reload to enable it."),
|
||||
[{
|
||||
label: localize('InstallVSIXAction.reloadNow', "Reload Now"),
|
||||
run: () => this.windowService.reloadWindow()
|
||||
}]
|
||||
);
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
label: localize('thirdPartyExt.no', 'No'),
|
||||
run: () => { return TPromise.as(null); }
|
||||
},
|
||||
{
|
||||
label: localize('thirdPartyExt.dontShowAgain', 'Don\'t Show Again'),
|
||||
isSecondary: true,
|
||||
run: () => {
|
||||
this.storageService.store(vsix, true);
|
||||
return TPromise.as(null);
|
||||
}
|
||||
}
|
||||
]
|
||||
);
|
||||
} else {
|
||||
this.extensionsWorkbenchService.install(vsix).then(() => {
|
||||
this.notificationService.prompt(
|
||||
Severity.Info,
|
||||
localize('InstallVSIXAction.success', "Successfully installed the extension. Reload to enable it."),
|
||||
[{
|
||||
label: localize('InstallVSIXAction.reloadNow', "Reload Now"),
|
||||
run: () => this.windowService.reloadWindow()
|
||||
}]
|
||||
);
|
||||
});
|
||||
// {{SQL CARBON EDIT}}
|
||||
let extensionPolicy = this.configurationService.getValue<string>(ExtensionsPolicyKey);
|
||||
if (extensionPolicy === ExtensionsPolicy.allowAll) {
|
||||
return this.windowService.showOpenDialog({
|
||||
title: localize('installFromVSIX', "Install from VSIX"),
|
||||
filters: [{ name: 'VSIX Extensions', extensions: ['vsix'] }],
|
||||
properties: ['openFile'],
|
||||
buttonLabel: mnemonicButtonLabel(localize({ key: 'installButton', comment: ['&& denotes a mnemonic'] }, "&&Install"))
|
||||
}).then(result => {
|
||||
if (!result) {
|
||||
return TPromise.as(null);
|
||||
}
|
||||
return TPromise.join(result.map(vsix => {
|
||||
// {{SQL CARBON EDIT}}
|
||||
if (!this.storageService.getBoolean(vsix)) {
|
||||
this.notificationService.prompt(
|
||||
Severity.Warning,
|
||||
localize('thirdPartyExtension.vsix', 'This is a third party extension and might involve security risks. Are you sure you want to install this extension?'),
|
||||
[
|
||||
{
|
||||
label: localize('thirdPartExt.yes', 'Yes'),
|
||||
run: () => {
|
||||
this.extensionsWorkbenchService.install(vsix).then(() => {
|
||||
this.notificationService.prompt(
|
||||
Severity.Info,
|
||||
localize('InstallVSIXAction.success', "Successfully installed the extension. Reload to enable it."),
|
||||
[{
|
||||
label: localize('InstallVSIXAction.reloadNow', "Reload Now"),
|
||||
run: () => this.windowService.reloadWindow()
|
||||
}]
|
||||
);
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
label: localize('thirdPartyExt.no', 'No'),
|
||||
run: () => { return TPromise.as(null); }
|
||||
},
|
||||
{
|
||||
label: localize('thirdPartyExt.dontShowAgain', 'Don\'t Show Again'),
|
||||
isSecondary: true,
|
||||
run: () => {
|
||||
this.storageService.store(vsix, true);
|
||||
return TPromise.as(null);
|
||||
}
|
||||
}
|
||||
]
|
||||
);
|
||||
} else {
|
||||
this.extensionsWorkbenchService.install(vsix).then(() => {
|
||||
this.notificationService.prompt(
|
||||
Severity.Info,
|
||||
localize('InstallVSIXAction.success', "Successfully installed the extension. Reload to enable it."),
|
||||
[{
|
||||
label: localize('InstallVSIXAction.reloadNow', "Reload Now"),
|
||||
run: () => this.windowService.reloadWindow()
|
||||
}]
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
}));
|
||||
});
|
||||
// {{SQL CARBON EDIT}}
|
||||
} else {
|
||||
this.notificationService.error(localize('InstallVSIXAction.allowNone', 'Your extension policy does not allow downloading extensions. Please change your extension policy and try again.'));
|
||||
return TPromise.as(null);
|
||||
}
|
||||
|
||||
}));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
|
||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { IExtension, IExtensionDependencies, ExtensionState, IExtensionsWorkbenchService, AutoUpdateConfigurationKey, AutoCheckUpdatesConfigurationKey } from 'vs/workbench/parts/extensions/common/extensions';
|
||||
// {{SQL CARBON EDIT}}
|
||||
import { IExtension, IExtensionDependencies, ExtensionState, IExtensionsWorkbenchService, AutoUpdateConfigurationKey, AutoCheckUpdatesConfigurationKey, ExtensionsPolicyKey, ExtensionsPolicy } from 'vs/workbench/parts/extensions/common/extensions';
|
||||
import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IURLService, IURLHandler } from 'vs/platform/url/common/url';
|
||||
import { ExtensionsInput } from 'vs/workbench/parts/extensions/common/extensionsInput';
|
||||
@@ -701,6 +702,8 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService,
|
||||
}
|
||||
|
||||
install(extension: string | IExtension): TPromise<void> {
|
||||
// {{SQL CARBON EDIT}}
|
||||
let extensionPolicy = this.configurationService.getValue<string>(ExtensionsPolicyKey);
|
||||
if (typeof extension === 'string') {
|
||||
return this.progressService.withProgress({
|
||||
location: ProgressLocation.Extensions,
|
||||
@@ -729,7 +732,16 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService,
|
||||
title: nls.localize('installingMarketPlaceExtension', 'Installing extension from Marketplace....'),
|
||||
source: `${extension.id}`
|
||||
// {{SQL CARBON EDIT}}
|
||||
}, () => this.downloadOrBrowse(ext));
|
||||
}, () => {
|
||||
if (extensionPolicy === ExtensionsPolicy.allowMicrosoft) {
|
||||
if (ext.publisherDisplayName === 'Microsoft') {
|
||||
return this.downloadOrBrowse(ext);
|
||||
} else {
|
||||
return TPromise.as(null);
|
||||
}
|
||||
}
|
||||
return this.downloadOrBrowse(ext);
|
||||
});
|
||||
}
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
|
||||
@@ -60,7 +60,8 @@ suite('ExtensionsActions Test', () => {
|
||||
instantiationService.stub(IWindowService, TestWindowService);
|
||||
|
||||
instantiationService.stub(IWorkspaceContextService, new TestContextService());
|
||||
instantiationService.stub(IConfigurationService, { onDidUpdateConfiguration: () => { }, onDidChangeConfiguration: () => { }, getConfiguration: () => ({}) });
|
||||
// {{SQL CARBON EDIT}}
|
||||
instantiationService.stub(IConfigurationService, { onDidUpdateConfiguration: () => { }, onDidChangeConfiguration: () => { }, getConfiguration: () => ({}), getValue: () => { } });
|
||||
|
||||
instantiationService.stub(IExtensionGalleryService, ExtensionGalleryService);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user