mirror of
https://github.com/tutao/tutanota.git
synced 2025-10-19 07:53:47 +00:00

Hardening reduces attack surface and also prevents abusing the app as a shell for malware. Close #9622
199 lines
6.6 KiB
JavaScript
199 lines
6.6 KiB
JavaScript
import path from "node:path"
|
|
import { readFileSync } from "node:fs"
|
|
import { getElectronVersion } from "./getInstalledModuleVersion.js"
|
|
|
|
/**
|
|
* This is used for launching electron:
|
|
* 1. copied to app-desktop/build from make.js
|
|
* 2. copied to app-desktop/build from dist.js (DesktopBuilder)
|
|
*
|
|
* @param p {object}
|
|
* @param p.nameSuffix {string}
|
|
* @param p.version {string}
|
|
* @param p.updateUrl {string}
|
|
* @param p.iconPath {string}
|
|
* @param p.sign {boolean}
|
|
* @param [p.notarize] {boolean}
|
|
* @param [p.unpacked] {boolean}
|
|
* @param p.architecture
|
|
*/
|
|
export default async function generateTemplate({ nameSuffix, version, updateUrl, iconPath, sign, notarize, unpacked, architecture }) {
|
|
const appName = "tutanota-desktop" + nameSuffix
|
|
const appId = "de.tutao.tutanota" + nameSuffix
|
|
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",
|
|
version: version,
|
|
author: "Tutao GmbH",
|
|
description: "The desktop client for Tutanota, the secure e-mail service.",
|
|
type: "module",
|
|
scripts: {
|
|
start: "electron .",
|
|
},
|
|
"tutao-config": {
|
|
pubKeys: [
|
|
"-----BEGIN PUBLIC KEY-----\n" +
|
|
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhFrLW999Y/ODqGfGKSzh\n" +
|
|
"7SFm6UgIj5scpb1r+KmEgVr/3zmd973+u2z5gG/wtayUbdVUGlzTgxqTE76BGTBR\n" +
|
|
"szq932uTsPfjRbtbyjIOzfzPvkyAB1Ew91gQk5ubrO1VCbXAZyuFi7RxDibuklLO\n" +
|
|
"lzHyjKyEIVTTdOqOTE+mg/vr41MxDW0X4nZw5MT1mIV/aYGeOSdtNdFsL69aR+d7\n" +
|
|
"KufD43J60FUS9G0tf4KmyQInmGqC8MSXCO0SMwwEJZDxDzkBsSensKfS0HzIjCXS\n" +
|
|
"or/Ahu6RwhEhjm7MyXbhiDyis+kGHSfatsO5KWWuZ4xgCEUO0L6vMQwr5M/qYOj1\n" +
|
|
"7QIDAQAB\n" +
|
|
"-----END PUBLIC KEY-----",
|
|
"-----BEGIN PUBLIC KEY-----\n" +
|
|
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk4NkSbs41KjuNZfFco2l\n" +
|
|
"unXXFOIkrdBfDmIiVfVTYagEk2cN9HkjCkiNsHucLHPuHb0reHsaxrDVE1lWGTPI\n" +
|
|
"0Lh5diLYdxJ+AGy/8j9jsO51hONqTujdD0mJs14YkVfOUXyHQh1z6WJCLc9jrN9+\n" +
|
|
"3dgKOlQRYW2mYise8ggYYcrRs/CY40s3/cQvrFSprFMPS6E+9lmIDp0hPKr9q90t\n" +
|
|
"IXmzihQyc8Q0VmAfCqEwUtx6RY6BGkqKiDoMh4Qs5ZwFxhoSfgrJiwBmv0HcX1yv\n" +
|
|
"QGNSdxrpLuMA/afCPdf49x3iwy+p+paXHKirgM5z6rnikk10Lko7dNXV0735PsZd\n" +
|
|
"dQIDAQAB\n" +
|
|
"-----END PUBLIC KEY-----",
|
|
debugKey,
|
|
],
|
|
pollingInterval: 1000 * 60 * 60 * 3, // 3 hours
|
|
iconName: "logo-solo-red.png",
|
|
fileManagerTimeout: 30000,
|
|
// true if this version checks its updates. use to prevent local builds from checking sigs.
|
|
checkUpdateSignature: sign,
|
|
appUserModelId: appId,
|
|
initialSseConnectTimeoutInSeconds: 60,
|
|
maxSseConnectTimeoutInSeconds: 2400,
|
|
configMigrationFunction: "migrateClient",
|
|
updateUrl,
|
|
defaultDesktopConfig: {
|
|
/**
|
|
* do not change defaultDesktopConfig
|
|
* instead, add migrations to src/desktop/DesktopConfigMigrator.js
|
|
*/
|
|
heartbeatTimeoutInSeconds: 30,
|
|
defaultDownloadPath: null,
|
|
enableAutoUpdate: true,
|
|
runAsTrayApp: true,
|
|
},
|
|
},
|
|
dependencies: {},
|
|
build: buildOptions,
|
|
}
|
|
}
|