Skip to content

Commit 70d5de1

Browse files
authored
Fix Windows code signing (#6233)
1 parent 7fbe1bd commit 70d5de1

File tree

4 files changed

+188
-90
lines changed

4 files changed

+188
-90
lines changed

appveyor.yml

+77-4
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,47 @@ skip_tags: true # Don't rebuild on tags.
1616
init:
1717
- ps: Install-Product node 16
1818
- cmd: set NODE_OPTIONS=--max-old-space-size=8192
19+
cache:
20+
- '%APPDATA%\npm-cache' # npm cache
21+
- newIDE\app\node_modules -> newIDE\app\package-lock.json
22+
- newIDE\electron-app\node_modules -> newIDE\electron-app\package-lock.json
23+
- GDevelop.js\node_modules -> GDevelop.js\package-lock.json
1924
install:
25+
# Download and install SSL.com eSigner CKA.
26+
# See https://www.ssl.com/how-to/how-to-integrate-esigner-cka-with-ci-cd-tools-for-automated-code-signing/.
27+
#
28+
# This is necessary because of "signing to be FIPS-140 compliant". See
29+
# https://github.com/electron-userland/electron-builder/issues/6158
30+
#
31+
# Make sure to DISABLE "malware blocker" in SSL.com to avoid errors like:
32+
# Error information: "Error: SignerSign() failed." (-2146893821/0x80090003)
33+
- ps: >-
34+
# Download and Unzip eSignerCKA Setup
35+
36+
Set-StrictMode -Version 'Latest'
37+
38+
Invoke-WebRequest -OutFile eSigner_CKA_Setup.zip "https://github.com/SSLcom/eSignerCKA/releases/download/v1.0.6/SSL.COM-eSigner-CKA_1.0.6.zip"
39+
40+
Expand-Archive -Force eSigner_CKA_Setup.zip
41+
42+
Remove-Item eSigner_CKA_Setup.zip
43+
44+
Move-Item -Destination "eSigner_CKA_Installer.exe" -Path "eSigner_CKA_*\*.exe"
45+
46+
# Install it. See https://www.ssl.com/how-to/how-to-integrate-esigner-cka-with-ci-cd-tools-for-automated-code-signing/
47+
48+
New-Item -ItemType Directory -Force -Path "C:\projects\gdevelop\eSignerCKA"
49+
50+
./eSigner_CKA_Installer.exe /CURRENTUSER /VERYSILENT /SUPPRESSMSGBOXES /DIR="C:\projects\gdevelop\eSignerCKA" | Out-Null
51+
52+
# Disable logger.
53+
54+
# $LogConfig = Get-Content -Path C:\projects\gdevelop\eSignerCKA/log4net.config
55+
56+
# $LogConfig[0] = '<log4net threshold="OFF">'
57+
58+
# $LogConfig | Set-Content -Path C:\projects\gdevelop\eSignerCKA/log4net.config
59+
2060
# Build GDevelop.js (and run tests to ensure it works).
2161
# (in a subshell to avoid Emscripten polluting the Node.js and npm version for the rest of the build)
2262
- cmd: >-
@@ -39,7 +79,7 @@ install:
3979
# setuptools will make distutils available again (but we should migrate our packages probably).
4080
- cmd: >-
4181
pip install setuptools
42-
82+
4383
cd newIDE\app
4484
4585
npm -v && npm install
@@ -50,21 +90,54 @@ install:
5090
5191
cd ..\..
5292
53-
# Package the app for Windows (and sign it with the certificate set in environment variables).
93+
# Package the app for Windows (and sign it).
5494
# Don't sign the appx (it will be signed by the Microsoft Store).
5595
build_script:
5696
- ps: >-
5797
cd newIDE\electron-app
5898
99+
# Prepare certificate. See https://www.ssl.com/how-to/automate-ev-code-signing-with-signtool-or-certutil-esigner/?_gl=1*vuybcy*_gcl_au*MTEwODg1NDM2Mi4xNzA1ODU1NjM4#automated-code-signing
100+
101+
C:\projects\gdevelop\eSignerCKA/eSignerCKATool.exe config -mode product -user "$Env:ESIGNER_USER_NAME" -pass "$Env:ESIGNER_USER_PASSWORD" -totp "$Env:ESIGNER_USER_TOTP" -key "C:\projects\gdevelop\eSignerCKA\master.key" -r
102+
103+
C:\projects\gdevelop\eSignerCKA/eSignerCKATool.exe unload
104+
105+
C:\projects\gdevelop\eSignerCKA/eSignerCKATool.exe load
106+
107+
# Find certificate so we can tell electron-builder which one to use.
108+
109+
$CodeSigningCert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert | Select-Object -First 1
110+
111+
echo Certificate: $CodeSigningCert
112+
113+
# Use a custom signtool path because of the signtool.exe bundled withy electron-builder not working for some reason.
114+
# Can also be found in versioned folders like "C:/Program Files (x86)/Windows Kits/10/bin/10.0.22000.0/x86/signtool.exe".
115+
116+
$Env:SIGNTOOL_PATH = "C:\Program Files (x86)\Windows Kits\10\App Certification Kit\signtool.exe"
117+
118+
# Extract thumbprint and subject name of the certificate (will be passed to electron-builder).
119+
120+
$Env:GD_SIGNTOOL_THUMBPRINT = $CodeSigningCert.Thumbprint
121+
122+
$Env:GD_SIGNTOOL_SUBJECT_NAME = ($CodeSigningCert.Subject -replace ", ?", "`n" | ConvertFrom-StringData).CN
123+
124+
# Build the nsis installer (signed: electron-builder will use SignTool.exe with the certificate)
125+
59126
node scripts/build.js --win nsis --publish=never
60127
61-
Remove-Item -Path Env:CSC_LINK ; Remove-Item -Path Env:CSC_KEY_PASSWORD ; node scripts/build.js --skip-app-build --win appx --publish=never
128+
# Build the appx (not signed).
129+
130+
$Env:GD_SIGNTOOL_THUMBPRINT = ''
131+
132+
$Env:GD_SIGNTOOL_SUBJECT_NAME = ''
133+
134+
node scripts/build.js --skip-app-build --win appx --publish=never
62135
63136
cd ..\..
64137
65138
# Clean dist folder to keep only installers/binaries.
66139
- cmd: >-
67-
DEL /F/Q/S newIDE\electron-app\dist\win-unpacked
140+
rmdir /s /q newIDE\electron-app\dist\win-unpacked
68141
69142
# Run a few tests on Windows.
70143
test_script:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/**
2+
* @type {import('electron-builder').Configuration}
3+
* @see https://www.electron.build/configuration/configuration
4+
*/
5+
const config = {
6+
appId: 'com.gdevelop-app.ide',
7+
extraResources: [
8+
{
9+
from: '../app/resources/in-app-tutorials',
10+
to: 'in-app-tutorials',
11+
},
12+
{
13+
from: '../app/resources/GDJS',
14+
to: 'GDJS',
15+
},
16+
{
17+
from: '../app/resources/preview_node_modules',
18+
to: 'preview_node_modules',
19+
},
20+
],
21+
linux: {
22+
target: [
23+
{
24+
target: 'AppImage',
25+
arch: ['x64', 'arm64'],
26+
},
27+
{
28+
target: 'zip',
29+
arch: ['x64', 'arm64'],
30+
},
31+
{
32+
target: 'deb',
33+
arch: ['x64', 'arm64'],
34+
},
35+
],
36+
},
37+
mac: {
38+
category: 'public.app-category.developer-tools',
39+
hardenedRuntime: true,
40+
entitlements: './build/entitlements.mac.inherit.plist',
41+
target: {
42+
target: 'default',
43+
arch: ['universal'],
44+
},
45+
},
46+
win: {
47+
executableName: 'GDevelop',
48+
},
49+
nsis: {
50+
oneClick: false,
51+
allowToChangeInstallationDirectory: true,
52+
},
53+
appx: {
54+
publisherDisplayName: 'GDevelop game engine',
55+
displayName: 'GDevelop',
56+
publisher: 'CN=B13CB8D3-97AA-422C-A394-0EE51B9ACAD3',
57+
identityName: 'GDevelopgameengine.GDevelop',
58+
backgroundColor: '#524F9C',
59+
languages: [
60+
'EN-US',
61+
'ZH-HANS',
62+
'DE',
63+
'IT',
64+
'JA',
65+
'PT-BR',
66+
'RU',
67+
'ES',
68+
'FR',
69+
'SL',
70+
],
71+
},
72+
afterSign: 'scripts/electron-builder-after-sign.js',
73+
publish: [
74+
{
75+
provider: 'github',
76+
},
77+
],
78+
};
79+
80+
if (
81+
process.env.GD_SIGNTOOL_SUBJECT_NAME &&
82+
process.env.GD_SIGNTOOL_THUMBPRINT
83+
) {
84+
config.win.certificateSubjectName = process.env.GD_SIGNTOOL_SUBJECT_NAME;
85+
config.win.certificateSha1 = process.env.GD_SIGNTOOL_THUMBPRINT;
86+
87+
// electron-builder default signtool.exe is not sufficient for some reason.
88+
if (!process.env.SIGNTOOL_PATH) {
89+
console.error(
90+
"❌ SIGNTOOL_PATH is not specified - signing won't work with the builtin signtool provided by electron-builder."
91+
);
92+
} else {
93+
console.log(
94+
'ℹ️ SIGNTOOL_PATH is specified and set to:',
95+
process.env.SIGNTOOL_PATH
96+
);
97+
}
98+
99+
// Seems required, see https://github.com/electron-userland/electron-builder/issues/6158#issuecomment-1587045539.
100+
config.win.signingHashAlgorithms = ['sha256'];
101+
console.log('ℹ️ Set Windows build signing options:', config.win);
102+
} else {
103+
console.log('ℹ️ No Windows build signing options set.');
104+
}
105+
106+
module.exports = config;

newIDE/electron-app/package.json

-85
Original file line numberDiff line numberDiff line change
@@ -19,91 +19,6 @@
1919
"import-zipped-electron-extensions": "node scripts/import-zipped-electron-extension.js ReactDeveloperTools app/extensions/",
2020
"copy-electron-remote-to-app-resources": "node scripts/copy-electron-remote-to-app-resources.js"
2121
},
22-
"build": {
23-
"appId": "com.gdevelop-app.ide",
24-
"extraResources": [
25-
{
26-
"from": "../app/resources/in-app-tutorials",
27-
"to": "in-app-tutorials"
28-
},
29-
{
30-
"from": "../app/resources/GDJS",
31-
"to": "GDJS"
32-
},
33-
{
34-
"from": "../app/resources/preview_node_modules",
35-
"to": "preview_node_modules"
36-
}
37-
],
38-
"linux": {
39-
"target": [
40-
{
41-
"target": "AppImage",
42-
"arch": [
43-
"x64",
44-
"arm64"
45-
]
46-
},
47-
{
48-
"target": "zip",
49-
"arch": [
50-
"x64",
51-
"arm64"
52-
]
53-
},
54-
{
55-
"target": "deb",
56-
"arch": [
57-
"x64",
58-
"arm64"
59-
]
60-
}
61-
]
62-
},
63-
"mac": {
64-
"category": "public.app-category.developer-tools",
65-
"hardenedRuntime": true,
66-
"entitlements": "./build/entitlements.mac.inherit.plist",
67-
"target": {
68-
"target": "default",
69-
"arch": [
70-
"universal"
71-
]
72-
}
73-
},
74-
"win": {
75-
"executableName": "GDevelop"
76-
},
77-
"nsis": {
78-
"oneClick": false,
79-
"allowToChangeInstallationDirectory": true
80-
},
81-
"appx": {
82-
"publisherDisplayName": "GDevelop game engine",
83-
"displayName": "GDevelop",
84-
"publisher": "CN=B13CB8D3-97AA-422C-A394-0EE51B9ACAD3",
85-
"identityName": "GDevelopgameengine.GDevelop",
86-
"backgroundColor": "#524F9C",
87-
"languages": [
88-
"EN-US",
89-
"ZH-HANS",
90-
"DE",
91-
"IT",
92-
"JA",
93-
"PT-BR",
94-
"RU",
95-
"ES",
96-
"FR",
97-
"SL"
98-
]
99-
},
100-
"afterSign": "scripts/electron-builder-after-sign.js",
101-
"publish": [
102-
{
103-
"provider": "github"
104-
}
105-
]
106-
},
10722
"devDependencies": {
10823
"@electron/notarize": "^2.1.0",
10924
"adm-zip": "^0.5.10",

newIDE/electron-app/scripts/build.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ let electronBuilderArguments = process.argv
2020
.slice(2)
2121
.filter(arg => arg !== '--skip-app-build');
2222
shell.exec(
23-
[electronBuilder, electronBuilderArguments.join(' ')].join(' '),
23+
[
24+
electronBuilder,
25+
'--config=electron-builder-config.js',
26+
electronBuilderArguments.join(' '),
27+
].join(' '),
2428
code => {
2529
if (code !== 0) {
2630
shell.echo(`❌ Electron build failed with code ${code}.`);

0 commit comments

Comments
 (0)