mirror of
https://github.com/tutao/tutanota.git
synced 2025-12-08 06:09:50 +00:00
[build, desktop] Enable code integrity & other hardening via fuses
Hardening reduces attack surface and also prevents abusing the app as a shell for malware. Close #9622
This commit is contained in:
parent
12a34dc4a3
commit
c5d0faabe5
1 changed files with 118 additions and 106 deletions
|
|
@ -23,6 +23,123 @@ export default async function generateTemplate({ nameSuffix, version, updateUrl,
|
|||
if (process.env.JENKINS_HOME && process.env.DEBUG_SIGN) throw new Error("Tried to DEBUG_SIGN in CI!")
|
||||
const debugKey = process.env.DEBUG_SIGN ? readFileSync(path.join(process.env.DEBUG_SIGN, "test.pubkey"), { encoding: "utf8" }) : undefined
|
||||
const log = console.log.bind(console)
|
||||
/** @type import("app-builder-lib").FuseOptionsV1*/
|
||||
const electronFuses = {
|
||||
runAsNode: false,
|
||||
enableNodeOptionsEnvironmentVariable: false,
|
||||
enableNodeCliInspectArguments: false,
|
||||
enableEmbeddedAsarIntegrityValidation: true,
|
||||
onlyLoadAppFromAsar: true,
|
||||
grantFileProtocolExtraPrivileges: false,
|
||||
}
|
||||
/** @type import("app-builder-lib").Configuration */
|
||||
const buildOptions = {
|
||||
electronVersion: await getElectronVersion(log),
|
||||
icon: iconPath,
|
||||
appId: appId,
|
||||
productName: nameSuffix.length > 0 ? nameSuffix.slice(1) + " Tuta Mail" : "Tuta Mail",
|
||||
// name of the appImage
|
||||
artifactName: "${name}-${os}.${ext}",
|
||||
asarUnpack: "desktop/*.node",
|
||||
afterSign: notarize ? "buildSrc/notarize.cjs" : undefined,
|
||||
protocols: [
|
||||
{
|
||||
name: "Mailto Links",
|
||||
schemes: ["mailto"],
|
||||
role: "Editor",
|
||||
},
|
||||
],
|
||||
forceCodeSigning: sign,
|
||||
publish: updateUrl
|
||||
? {
|
||||
provider: "generic",
|
||||
url: updateUrl,
|
||||
channel: "latest",
|
||||
publishAutoUpdate: true,
|
||||
useMultipleRangeRequest: false,
|
||||
}
|
||||
: undefined,
|
||||
directories: {
|
||||
output: "installers",
|
||||
},
|
||||
extraResources: {
|
||||
from: path.dirname(iconPath),
|
||||
to: "./icons/",
|
||||
},
|
||||
win: {
|
||||
// relative to the project dir which is ./build/
|
||||
extraFiles: ["mapirs.dll"],
|
||||
verifyUpdateCodeSignature: sign,
|
||||
signExts: [".dll", ".node"],
|
||||
signtoolOptions: {
|
||||
sign: sign ? "./buildSrc/winsigner.cjs" : undefined,
|
||||
signingHashAlgorithms: sign ? ["sha256"] : undefined,
|
||||
},
|
||||
target: [
|
||||
{
|
||||
target: unpacked ? "dir" : "nsis",
|
||||
arch: architecture,
|
||||
},
|
||||
],
|
||||
},
|
||||
nsis: {
|
||||
oneClick: false,
|
||||
perMachine: false,
|
||||
createStartMenuShortcut: true,
|
||||
allowElevation: true,
|
||||
allowToChangeInstallationDirectory: true,
|
||||
include: path.join("..", "..", "buildSrc", "windows-installer.nsh"),
|
||||
warningsAsErrors: true,
|
||||
},
|
||||
mac: {
|
||||
hardenedRuntime: true,
|
||||
type: "distribution",
|
||||
gatekeeperAssess: false,
|
||||
entitlements: "buildSrc/mac-entitlements.plist",
|
||||
entitlementsInherit: "buildSrc/mac-entitlements.plist",
|
||||
icon: path.join(path.dirname(iconPath), "logo-solo-red.png.icns"),
|
||||
extendInfo: {
|
||||
LSUIElement: 1, //hide dock icon on startup
|
||||
},
|
||||
// The build process is somewhat silly as we build two apps for each arch (x64 and arm64).
|
||||
// We do not pre-lipo the NAPI binaries so each of these apps will have libraries for both architectures.
|
||||
// But it doesn't matter because in the end both apps are smashed together into a single package.
|
||||
// If each of the app parts had only one binary we would add them to "singleArchFiles" to tell @electron/universal to not merge them into a
|
||||
// single asar.
|
||||
//
|
||||
// This option tells @electron/universal that it's okay to have a file for the mismatching architecture in the app (which we will have because
|
||||
// we have both binaries).
|
||||
// It will also disable LIPO for this file which is what we want.
|
||||
x64ArchFiles: "**/*.node",
|
||||
target: unpacked
|
||||
? [{ target: "dir", arch: architecture }]
|
||||
: [
|
||||
{
|
||||
target: "zip",
|
||||
arch: architecture,
|
||||
},
|
||||
{
|
||||
target: "dmg",
|
||||
arch: architecture,
|
||||
},
|
||||
],
|
||||
},
|
||||
linux: {
|
||||
// name of the unpacked executable inside the AppImage/Flatpak,
|
||||
// defaults to productName if not specified
|
||||
executableName: appName,
|
||||
icon: path.join(path.dirname(iconPath), "icon/"),
|
||||
synopsis: "Tuta Mail Desktop Client",
|
||||
category: "Network",
|
||||
target: [
|
||||
{
|
||||
target: unpacked ? "dir" : "AppImage",
|
||||
arch: architecture,
|
||||
},
|
||||
],
|
||||
},
|
||||
electronFuses,
|
||||
}
|
||||
return {
|
||||
name: appName,
|
||||
main: "./desktop/DesktopMain.js",
|
||||
|
|
@ -77,111 +194,6 @@ export default async function generateTemplate({ nameSuffix, version, updateUrl,
|
|||
},
|
||||
},
|
||||
dependencies: {},
|
||||
build: {
|
||||
electronVersion: await getElectronVersion(log),
|
||||
icon: iconPath,
|
||||
appId: appId,
|
||||
productName: nameSuffix.length > 0 ? nameSuffix.slice(1) + " Tuta Mail" : "Tuta Mail",
|
||||
// name of the appImage
|
||||
artifactName: "${name}-${os}.${ext}",
|
||||
asarUnpack: "desktop/*.node",
|
||||
afterSign: notarize ? "buildSrc/notarize.cjs" : undefined,
|
||||
protocols: [
|
||||
{
|
||||
name: "Mailto Links",
|
||||
schemes: ["mailto"],
|
||||
role: "Editor",
|
||||
},
|
||||
],
|
||||
forceCodeSigning: sign,
|
||||
publish: updateUrl
|
||||
? {
|
||||
provider: "generic",
|
||||
url: updateUrl,
|
||||
channel: "latest",
|
||||
publishAutoUpdate: true,
|
||||
useMultipleRangeRequest: false,
|
||||
}
|
||||
: undefined,
|
||||
directories: {
|
||||
output: "installers",
|
||||
},
|
||||
extraResources: {
|
||||
from: path.dirname(iconPath),
|
||||
to: "./icons/",
|
||||
},
|
||||
win: {
|
||||
// relative to the project dir which is ./build/
|
||||
extraFiles: ["mapirs.dll"],
|
||||
verifyUpdateCodeSignature: sign,
|
||||
signExts: [".dll", ".node"],
|
||||
signtoolOptions: {
|
||||
sign: sign ? "./buildSrc/winsigner.cjs" : undefined,
|
||||
signingHashAlgorithms: sign ? ["sha256"] : undefined,
|
||||
},
|
||||
target: [
|
||||
{
|
||||
target: unpacked ? "dir" : "nsis",
|
||||
arch: architecture,
|
||||
},
|
||||
],
|
||||
},
|
||||
nsis: {
|
||||
oneClick: false,
|
||||
perMachine: false,
|
||||
createStartMenuShortcut: true,
|
||||
allowElevation: true,
|
||||
allowToChangeInstallationDirectory: true,
|
||||
include: path.join("..", "..", "buildSrc", "windows-installer.nsh"),
|
||||
warningsAsErrors: true,
|
||||
},
|
||||
mac: {
|
||||
hardenedRuntime: true,
|
||||
type: "distribution",
|
||||
gatekeeperAssess: false,
|
||||
entitlements: "buildSrc/mac-entitlements.plist",
|
||||
entitlementsInherit: "buildSrc/mac-entitlements.plist",
|
||||
icon: path.join(path.dirname(iconPath), "logo-solo-red.png.icns"),
|
||||
extendInfo: {
|
||||
LSUIElement: 1, //hide dock icon on startup
|
||||
},
|
||||
// The build process is somewhat silly as we build two apps for each arch (x64 and arm64).
|
||||
// We do not pre-lipo the NAPI binaries so each of these apps will have libraries for both architectures.
|
||||
// But it doesn't matter because in the end both apps are smashed together into a single package.
|
||||
// If each of the app parts had only one binary we would add them to "singleArchFiles" to tell @electron/universal to not merge them into a
|
||||
// single asar.
|
||||
//
|
||||
// This option tells @electron/universal that it's okay to have a file for the mismatching architecture in the app (which we will have because
|
||||
// we have both binaries).
|
||||
// It will also disable LIPO for this file which is what we want.
|
||||
x64ArchFiles: "**/*.node",
|
||||
target: unpacked
|
||||
? [{ target: "dir", arch: architecture }]
|
||||
: [
|
||||
{
|
||||
target: "zip",
|
||||
arch: architecture,
|
||||
},
|
||||
{
|
||||
target: "dmg",
|
||||
arch: architecture,
|
||||
},
|
||||
],
|
||||
},
|
||||
linux: {
|
||||
// name of the unpacked executable inside the AppImage/Flatpak,
|
||||
// defaults to productName if not specified
|
||||
executableName: appName,
|
||||
icon: path.join(path.dirname(iconPath), "icon/"),
|
||||
synopsis: "Tuta Mail Desktop Client",
|
||||
category: "Network",
|
||||
target: [
|
||||
{
|
||||
target: unpacked ? "dir" : "AppImage",
|
||||
arch: architecture,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
build: buildOptions,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue