Skip to content

Commit afdbcef

Browse files
committed
Verify signatures of real signed vsixs
1 parent 773247f commit afdbcef

File tree

5 files changed

+93
-7
lines changed

5 files changed

+93
-7
lines changed
File renamed without changes.

azure-pipelines/build-vsix.yml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,9 @@ stages:
134134
versionSpec: 3.11
135135

136136
# Non-windows signing requires .NET 8 installed on the machine.
137-
- task: UseDotNet@2
138-
displayName: Use .NET Core sdk 8.0.x
139-
inputs:
137+
- task: UseDotNet@2
138+
displayName: Use .NET Core sdk 8.0.x
139+
inputs:
140140
version: 8.0.x
141141

142142
# If we're in an official build, install the signing plugin
@@ -176,6 +176,12 @@ stages:
176176
SignType: $(signType)
177177
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
178178

179+
- ${{ if eq(parameters.isOfficial, true) }}:
180+
- script: gulp verifyVsix
181+
condition: and( succeeded(), eq('$(SignType)', 'Real'))
182+
displayName: 🔑 Verify VSIX Signature Files
183+
workingDirectory: '$(Build.SourcesDirectory)/vsix'
184+
179185
- task: CopyFiles@2
180186
inputs:
181187
SourceFolder: '$(Build.SourcesDirectory)/vsix'

tasks/signingTasks.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import * as fs from 'fs';
88
import * as gulp from 'gulp';
99
import { rootPath } from './projectPaths';
1010
import path from 'path';
11+
import { verifySignature } from './vsceTasks';
1112
// There are no typings for this library.
1213
// eslint-disable-next-line @typescript-eslint/no-var-requires
1314
//const argv = require('yargs').argv;
@@ -20,6 +21,10 @@ gulp.task('signVsix', async () => {
2021
await signVsix();
2122
});
2223

24+
gulp.task('verifyVsix', async () => {
25+
await verifyVsix();
26+
});
27+
2328
// Development task to install the signing plugin locally.
2429
// Required to run test sigining tasks locally.
2530
gulp.task('installSignPlugin', async () => {
@@ -43,7 +48,7 @@ async function signJs(): Promise<void> {
4348
const logPath = getLogPath();
4449
const signType = process.env.SignType;
4550
if (!signType) {
46-
console.warn('SignType environment variable is not set, skipping JS signing');
51+
console.warn('SignType environment variable is not set, skipping JS signing.');
4752
return;
4853
}
4954

@@ -64,7 +69,7 @@ async function signVsix(): Promise<void> {
6469
const logPath = getLogPath();
6570
const signType = process.env.SignType;
6671
if (!signType) {
67-
console.warn('SignType environment variable is not set, skipping VSIX signing');
72+
console.warn('SignType environment variable is not set, skipping VSIX signing.');
6873
return;
6974
}
7075

@@ -80,6 +85,25 @@ async function signVsix(): Promise<void> {
8085
]);
8186
}
8287

88+
async function verifyVsix(): Promise<void> {
89+
const signType = process.env.SignType;
90+
if (!signType) {
91+
console.warn('SignType environment variable is not set, skipping VSIX verification.');
92+
return;
93+
}
94+
95+
if (signType === 'test') {
96+
console.log('Test signing verification is not supported. Skipping VSIX verification.');
97+
return;
98+
}
99+
100+
const vsixs = fs.readdirSync('.').filter((file) => path.extname(file) === '.vsix');
101+
for (const vsixFile in vsixs) {
102+
console.log(`Verifying signature of ${vsixFile}`);
103+
await verifySignature(vsixFile);
104+
}
105+
}
106+
83107
function getLogPath(): string {
84108
const logPath = path.join(rootPath, 'out', 'logs');
85109
if (!fs.existsSync(logPath)) {

tasks/spawnNode.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,29 @@ export default async function spawnNode(args?: string[], options?: SpawnSyncOpti
2727

2828
const buffer = spawnSync(nodePath, args, optionsWithFullEnvironment);
2929

30-
return { code: buffer.status, signal: buffer.signal };
30+
return { code: buffer.status, signal: buffer.signal, stdout: buffer.stdout };
31+
}
32+
33+
export async function spawnNodeWithOutput(args?: string[], options?: SpawnSyncOptions) {
34+
if (!options) {
35+
options = {
36+
env: {},
37+
};
38+
}
39+
40+
const optionsWithFullEnvironment: SpawnSyncOptions = {
41+
cwd: rootPath,
42+
...options,
43+
env: {
44+
...process.env,
45+
...options.env,
46+
},
47+
stdio: 'pipe',
48+
};
49+
50+
console.log(`starting ${nodePath} ${args ? args.join(' ') : ''}`);
51+
52+
const buffer = spawnSync(nodePath, args, optionsWithFullEnvironment);
53+
54+
return { code: buffer.status, signal: buffer.signal, stdout: buffer.stdout };
3155
}

tasks/vsceTasks.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import * as path from 'path';
77
import * as util from '../src/common';
88
import * as fs from 'fs';
9-
import spawnNode from '../tasks/spawnNode';
9+
import spawnNode, { spawnNodeWithOutput } from '../tasks/spawnNode';
1010
import { vscePath } from './projectPaths';
1111

1212
/// Packaging (VSIX) Tasks
@@ -82,3 +82,35 @@ export async function generateVsixManifest(vsixPath: string) {
8282
throw new Error(`'${vsceArgs.join(' ')}' failed with code ${spawnResult.code}.`);
8383
}
8484
}
85+
86+
export async function verifySignature(vsixPath: string) {
87+
const vsceArgs = [];
88+
if (!(await util.fileExists(vscePath))) {
89+
throw new Error(`vsce does not exist at expected location: '${vscePath}'`);
90+
}
91+
92+
vsceArgs.push(vscePath);
93+
vsceArgs.push('verify-signature');
94+
vsceArgs.push('--packagePath');
95+
vsceArgs.push(vsixPath);
96+
97+
const parsed = path.parse(vsixPath);
98+
const outputFolder = parsed.dir;
99+
const vsixNameWithoutExtension = parsed.name;
100+
101+
vsceArgs.push('--manifestPath');
102+
vsceArgs.push(path.join(outputFolder, `${vsixNameWithoutExtension}.manifest`));
103+
104+
vsceArgs.push('--signaturePath');
105+
vsceArgs.push(path.join(outputFolder, `${vsixNameWithoutExtension}.signature.p7s`));
106+
107+
const spawnResult = await spawnNodeWithOutput(vsceArgs);
108+
if (spawnResult.code != 0) {
109+
throw new Error(`'${vsceArgs.join(' ')}' failed with code ${spawnResult.code}.`);
110+
} else if (spawnResult.stdout != 'Signature verification result: Success') {
111+
console.log(spawnResult.stdout);
112+
throw new Error(`Signature verification failed - '${vsceArgs.join(' ')}'.`);
113+
}
114+
115+
console.log(`Signature verification succeeded for ${vsixPath}`);
116+
}

0 commit comments

Comments
 (0)