Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/platform/extensionManagement/node/extensionSignatureVerificationService.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { getErrorMessage } from '../../../base/common/errors.js';
7
import { isDefined } from '../../../base/common/types.js';
8
import { TargetPlatform } from '../../extensions/common/extensions.js';
9
import { createDecorator } from '../../instantiation/common/instantiation.js';
10
import { ILogService, LogLevel } from '../../log/common/log.js';
11
import { ITelemetryService } from '../../telemetry/common/telemetry.js';
12
import { ExtensionSignatureVerificationCode } from '../common/extensionManagement.js';
13
14
export const IExtensionSignatureVerificationService = createDecorator<IExtensionSignatureVerificationService>('IExtensionSignatureVerificationService');
15
16
export interface IExtensionSignatureVerificationResult {
17
readonly code: ExtensionSignatureVerificationCode;
18
}
19
20
/**
21
* A service for verifying signed extensions.
22
*/
23
export interface IExtensionSignatureVerificationService {
24
readonly _serviceBrand: undefined;
25
26
/**
27
* Verifies an extension file (.vsix) against a signature archive file.
28
* @param extensionId The extension identifier.
29
* @param version The extension version.
30
* @param vsixFilePath The extension file path.
31
* @param signatureArchiveFilePath The signature archive file path.
32
* @returns returns the verification result or undefined if the verification was not executed.
33
*/
34
verify(extensionId: string, version: string, vsixFilePath: string, signatureArchiveFilePath: string, clientTargetPlatform?: TargetPlatform): Promise<IExtensionSignatureVerificationResult | undefined>;
35
}
36
37
declare module vsceSign {
38
export function verify(vsixFilePath: string, signatureArchiveFilePath: string, verbose: boolean): Promise<ExtensionSignatureVerificationResult>;
39
}
40
41
/**
42
* Extension signature verification result
43
*/
44
export interface ExtensionSignatureVerificationResult {
45
readonly code: ExtensionSignatureVerificationCode;
46
readonly didExecute: boolean;
47
readonly internalCode?: number;
48
readonly output?: string;
49
}
50
51
export class ExtensionSignatureVerificationService implements IExtensionSignatureVerificationService {
52
declare readonly _serviceBrand: undefined;
53
54
private moduleLoadingPromise: Promise<typeof vsceSign> | undefined;
55
56
constructor(
57
@ILogService private readonly logService: ILogService,
58
@ITelemetryService private readonly telemetryService: ITelemetryService,
59
) { }
60
61
private vsceSign(): Promise<typeof vsceSign> {
62
if (!this.moduleLoadingPromise) {
63
this.moduleLoadingPromise = this.resolveVsceSign();
64
}
65
66
return this.moduleLoadingPromise;
67
}
68
69
private async resolveVsceSign(): Promise<typeof vsceSign> {
70
const mod = '@vscode/vsce-sign';
71
return import(mod);
72
}
73
74
public async verify(extensionId: string, version: string, vsixFilePath: string, signatureArchiveFilePath: string, clientTargetPlatform?: TargetPlatform): Promise<IExtensionSignatureVerificationResult | undefined> {
75
let module: typeof vsceSign;
76
77
try {
78
module = await this.vsceSign();
79
} catch (error) {
80
this.logService.error('Could not load vsce-sign module', getErrorMessage(error));
81
this.logService.info(`Extension signature verification is not done: ${extensionId}`);
82
return undefined;
83
}
84
85
const startTime = new Date().getTime();
86
let result: ExtensionSignatureVerificationResult;
87
88
try {
89
this.logService.trace(`Verifying extension signature for ${extensionId}...`);
90
result = await module.verify(vsixFilePath, signatureArchiveFilePath, this.logService.getLevel() === LogLevel.Trace);
91
} catch (e) {
92
result = {
93
code: ExtensionSignatureVerificationCode.UnknownError,
94
didExecute: false,
95
output: getErrorMessage(e)
96
};
97
}
98
99
const duration = new Date().getTime() - startTime;
100
101
this.logService.info(`Extension signature verification result for ${extensionId}: ${result.code}. ${isDefined(result.internalCode) ? `Internal Code: ${result.internalCode}. ` : ''}Executed: ${result.didExecute}. Duration: ${duration}ms.`);
102
this.logService.trace(`Extension signature verification output for ${extensionId}:\n${result.output}`);
103
104
type ExtensionSignatureVerificationClassification = {
105
owner: 'sandy081';
106
comment: 'Extension signature verification event';
107
extensionId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'extension identifier' };
108
extensionVersion: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'extension version' };
109
code: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'result code of the verification' };
110
internalCode?: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; 'isMeasurement': true; comment: 'internal code of the verification' };
111
duration: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; 'isMeasurement': true; comment: 'amount of time taken to verify the signature' };
112
didExecute: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'whether the verification was executed' };
113
clientTargetPlatform?: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'target platform of the client' };
114
};
115
type ExtensionSignatureVerificationEvent = {
116
extensionId: string;
117
extensionVersion: string;
118
code: string;
119
internalCode?: number;
120
duration: number;
121
didExecute: boolean;
122
clientTargetPlatform?: string;
123
};
124
this.telemetryService.publicLog2<ExtensionSignatureVerificationEvent, ExtensionSignatureVerificationClassification>('extensionsignature:verification', {
125
extensionId,
126
extensionVersion: version,
127
code: result.code,
128
internalCode: result.internalCode,
129
duration,
130
didExecute: result.didExecute,
131
clientTargetPlatform,
132
});
133
134
return { code: result.code };
135
}
136
}
137
138