Skip to content

Commit 62fd74d

Browse files
authoredSep 23, 2024··
fix: azure signing logic should not have logic flow dependent on custom signtool hook (#8524)
1 parent d1cb6bd commit 62fd74d

File tree

7 files changed

+74
-54
lines changed

7 files changed

+74
-54
lines changed
 

‎.changeset/tiny-knives-behave.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"app-builder-lib": patch
3+
---
4+
5+
fix: moving cscInfo logic into signtoolManager to distinguish the logic between custom sign, csc info, and azure signing

‎packages/app-builder-lib/src/codeSign/windowsSignAzureManager.ts

+17-8
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,15 @@ export class WindowsSignAzureManager {
1010
const vm = await this.packager.vm.value
1111
const ps = await getPSCmd(vm)
1212

13-
log.debug(null, "installing required package provider (NuGet) and module (TrustedSigning) with scope CurrentUser")
14-
await vm.exec(ps, ["Install-PackageProvider", "-Name", "NuGet", "-MinimumVersion", "2.8.5.201", "-Force", "-Scope", "CurrentUser"])
15-
await vm.exec(ps, ["Install-Module", "-Name", "TrustedSigning", "-RequiredVersion", "0.4.1", "-Force", "-Repository", "PSGallery", "-Scope", "CurrentUser"])
13+
log.info(null, "installing required module (TrustedSigning) with scope CurrentUser")
14+
try {
15+
await vm.exec(ps, ["-NoProfile", "-NonInteractive", "-Command", "Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Scope CurrentUser"])
16+
} catch (error: any) {
17+
// Might not be needed, seems GH runners already have NuGet set up.
18+
// Logging to debug just in case users run into this. If NuGet isn't present, Install-Module -Name TrustedSigning will fail, so we'll get the logs at that point
19+
log.debug({ message: error.message || error.stack }, "unable to install PackageProvider Nuget. Might be a false alarm though as some systems already have it installed")
20+
}
21+
await vm.exec(ps, ["-NoProfile", "-NonInteractive", "-Command", "Install-Module -Name TrustedSigning -RequiredVersion 0.4.1 -Force -Repository PSGallery -Scope CurrentUser"])
1622

1723
// Preemptively check env vars once during initialization
1824
// Options: https://learn.microsoft.com/en-us/dotnet/api/azure.identity.environmentcredential?view=azure-dotnet#definition
@@ -75,15 +81,18 @@ export class WindowsSignAzureManager {
7581

7682
const { endpoint, certificateProfileName, ...extraSigningArgs }: WindowsAzureSigningConfiguration = options.options.azureSignOptions!
7783
const params = {
78-
...extraSigningArgs,
84+
FileDigest: "SHA256",
85+
...extraSigningArgs, // allows overriding FileDigest if provided in config
7986
Endpoint: endpoint,
8087
CertificateProfileName: certificateProfileName,
8188
Files: options.path,
8289
}
83-
const paramsString = Object.entries(params).reduce((res, [field, value]) => {
84-
return [...res, `-${field}`, value]
85-
}, [] as string[])
86-
await vm.exec(ps, ["Invoke-TrustedSigning", ...paramsString])
90+
const paramsString = Object.entries(params)
91+
.reduce((res, [field, value]) => {
92+
return [...res, `-${field}`, value]
93+
}, [] as string[])
94+
.join(" ")
95+
await vm.exec(ps, ["-NoProfile", "-NonInteractive", "-Command", `Invoke-TrustedSigning ${paramsString}`])
8796

8897
return true
8998
}

‎packages/app-builder-lib/src/codeSign/windowsSignToolManager.ts

+26-1
Original file line numberDiff line numberDiff line change
@@ -174,11 +174,36 @@ export class WindowsSignToolManager {
174174
hashes = Array.isArray(hashes) ? hashes : [hashes]
175175
}
176176

177-
const cscInfo = await this.cscInfo.value
178177
const name = this.packager.appInfo.productName
179178
const site = await this.packager.appInfo.computePackageUrl()
180179

181180
const customSign = await resolveFunction(this.packager.appInfo.type, chooseNotNull(options.options.signtoolOptions?.sign, options.options.sign), "sign")
181+
182+
const cscInfo = await this.cscInfo.value
183+
if (cscInfo) {
184+
let logInfo: any = {
185+
file: log.filePath(options.path),
186+
}
187+
if ("file" in cscInfo) {
188+
logInfo = {
189+
...logInfo,
190+
certificateFile: cscInfo.file,
191+
}
192+
} else {
193+
logInfo = {
194+
...logInfo,
195+
subject: cscInfo.subject,
196+
thumbprint: cscInfo.thumbprint,
197+
store: cscInfo.store,
198+
user: cscInfo.isLocalMachineStore ? "local machine" : "current user",
199+
}
200+
}
201+
log.info(logInfo, "signing")
202+
} else if (!customSign) {
203+
log.error({ signHook: customSign, cscInfo }, "no signing info identified, signing is skipped")
204+
return false
205+
}
206+
182207
const executor = customSign || ((config: CustomWindowsSignTaskConfiguration, packager: WinPackager) => this.doSign(config, packager))
183208
let isNest = false
184209
for (const hash of hashes) {

‎packages/app-builder-lib/src/targets/nsis/NsisTarget.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ export class NsisTarget extends Target {
403403
} else {
404404
await execWine(installerPath, null, [], { env: { __COMPAT_LAYER: "RunAsInvoker" } })
405405
}
406-
await packager.sign(uninstallerPath, "signing NSIS uninstaller")
406+
await packager.sign(uninstallerPath)
407407

408408
delete defines.BUILD_UNINSTALLER
409409
// platform-specific path, not wine

‎packages/app-builder-lib/src/winPackager.ts

+6-43
Original file line numberDiff line numberDiff line change
@@ -122,56 +122,19 @@ export class WinPackager extends PlatformPackager<WindowsConfiguration> {
122122
)
123123
}
124124

125-
async sign(file: string, logMessagePrefix?: string): Promise<boolean> {
125+
async sign(file: string): Promise<boolean> {
126126
const signOptions: WindowsSignOptions = {
127127
path: file,
128128
options: this.platformSpecificBuildOptions,
129129
}
130130

131-
const cscInfo = await (await this.signtoolManager.value).cscInfo.value
132-
if (cscInfo == null) {
133-
if (chooseNotNull(this.platformSpecificBuildOptions.signtoolOptions?.sign, this.platformSpecificBuildOptions.sign) != null) {
134-
return signWindows(signOptions, this)
135-
} else if (this.forceCodeSigning) {
136-
throw new InvalidConfigurationError(
137-
`App is not signed and "forceCodeSigning" is set to true, please ensure that code signing configuration is correct, please see https://electron.build/code-signing`
138-
)
139-
}
140-
return false
141-
}
142-
143-
if (logMessagePrefix == null) {
144-
logMessagePrefix = "signing"
145-
}
146-
147-
if ("file" in cscInfo) {
148-
log.info(
149-
{
150-
file: log.filePath(file),
151-
certificateFile: cscInfo.file,
152-
},
153-
logMessagePrefix
154-
)
155-
} else {
156-
const info = cscInfo
157-
log.info(
158-
{
159-
file: log.filePath(file),
160-
subject: info.subject,
161-
thumbprint: info.thumbprint,
162-
store: info.store,
163-
user: info.isLocalMachineStore ? "local machine" : "current user",
164-
},
165-
logMessagePrefix
131+
const didSignSuccessfully = await this.doSign(signOptions)
132+
if (!didSignSuccessfully && this.forceCodeSigning) {
133+
throw new InvalidConfigurationError(
134+
`App is not signed and "forceCodeSigning" is set to true, please ensure that code signing configuration is correct, please see https://electron.build/code-signing`
166135
)
167136
}
168-
169-
return this.doSign({
170-
...signOptions,
171-
options: {
172-
...this.platformSpecificBuildOptions,
173-
},
174-
})
137+
return didSignSuccessfully
175138
}
176139

177140
private async doSign(options: WindowsSignOptions) {

‎test/snapshots/windows/winCodeSignTest.js.snap

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3+
exports[`azure signing without credentials 1`] = `"ERR_ELECTRON_BUILDER_INVALID_CONFIGURATION"`;
4+
35
exports[`electronDist 1`] = `"ENOENT"`;
46

57
exports[`forceCodeSigning 1`] = `"ERR_ELECTRON_BUILDER_INVALID_CONFIGURATION"`;

‎test/src/windows/winCodeSignTest.ts

+17-1
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,25 @@ test.ifAll.ifNotCiMac(
106106
test.ifAll.ifNotCiMac(
107107
"electronDist",
108108
appThrows({
109-
targets: Platform.WINDOWS.createTarget(DIR_TARGET),
109+
targets: windowsDirTarget,
110110
config: {
111111
electronDist: "foo",
112112
},
113113
})
114114
)
115+
116+
test.ifAll.ifNotCiMac(
117+
"azure signing without credentials",
118+
appThrows({
119+
targets: windowsDirTarget,
120+
config: {
121+
forceCodeSigning: true,
122+
win: {
123+
azureSignOptions: {
124+
endpoint: "https://weu.codesigning.azure.net/",
125+
certificateProfileName: "profilenamehere",
126+
},
127+
},
128+
},
129+
})
130+
)

0 commit comments

Comments
 (0)
Please sign in to comment.