Skip to content

Commit

Permalink
updating docs and moving electron fuses directly before signing step
Browse files Browse the repository at this point in the history
  • Loading branch information
mmaietta committed Oct 11, 2024
1 parent 12d8d4d commit 5e296d6
Show file tree
Hide file tree
Showing 20 changed files with 276 additions and 42 deletions.
10 changes: 10 additions & 0 deletions packages/app-builder-lib/scheme.json
Original file line number Diff line number Diff line change
Expand Up @@ -1286,32 +1286,42 @@
},
"FuseOptionsV1": {
"additionalProperties": false,
"description": "All options come from [@electron/fuses](https://github.com/electron/fuses)",
"properties": {
"enableCookieEncryption": {
"description": "Enables cookie encryption",
"type": "boolean"
},
"enableEmbeddedAsarIntegrityValidation": {
"description": "Enables validation of the app.asar archive on macOS",
"type": "boolean"
},
"enableNodeCliInspectArguments": {
"description": "Disables the --inspect and --inspect-brk family of CLI options",
"type": "boolean"
},
"enableNodeOptionsEnvironmentVariable": {
"description": "Disables the NODE_OPTIONS environment variable",
"type": "boolean"
},
"grantFileProtocolExtraPrivileges": {
"description": "Grants the file protocol extra privileges",
"type": "boolean"
},
"loadBrowserProcessSpecificV8Snapshot": {
"description": "Loads V8 Snapshot from `browser_v8_context_snapshot.bin` for the browser process",
"type": "boolean"
},
"onlyLoadAppFromAsar": {
"description": "Enforces that Electron will only load your app from \"app.asar\" instead of its normal search paths",
"type": "boolean"
},
"resetAdHocDarwinSignature": {
"description": "Resets the app signature, specifically used for macOS.\nNote: This should be unneeded since electron-builder signs the app directly after flipping the fuses.\nRef: https://github.com/electron/fuses?tab=readme-ov-file#apple-silicon",
"type": "boolean"
},
"runAsNode": {
"description": "Disables ELECTRON_RUN_AS_NODE",
"type": "boolean"
}
},
Expand Down
32 changes: 32 additions & 0 deletions packages/app-builder-lib/src/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -382,14 +382,46 @@ export interface MetadataDirectories {
readonly app?: string | null
}

/**
* All options come from [@electron/fuses](https://github.com/electron/fuses)
*/
export interface FuseOptionsV1 {
/**
* Disables ELECTRON_RUN_AS_NODE
*/
runAsNode?: boolean
/**
* Enables cookie encryption
*/
enableCookieEncryption?: boolean
/**
* Disables the NODE_OPTIONS environment variable
*/
enableNodeOptionsEnvironmentVariable?: boolean
/**
* Disables the --inspect and --inspect-brk family of CLI options
*/
enableNodeCliInspectArguments?: boolean
/**
* Enables validation of the app.asar archive on macOS
*/
enableEmbeddedAsarIntegrityValidation?: boolean
/**
* Enforces that Electron will only load your app from "app.asar" instead of its normal search paths
*/
onlyLoadAppFromAsar?: boolean
/**
* Loads V8 Snapshot from `browser_v8_context_snapshot.bin` for the browser process
*/
loadBrowserProcessSpecificV8Snapshot?: boolean
/**
* Grants the file protocol extra privileges
*/
grantFileProtocolExtraPrivileges?: boolean
/**
* Resets the app signature, specifically used for macOS.
* Note: This should be unneeded since electron-builder signs the app directly after flipping the fuses.
* Ref: https://github.com/electron/fuses?tab=readme-ov-file#apple-silicon
*/
resetAdHocDarwinSignature?: boolean
}
68 changes: 32 additions & 36 deletions packages/app-builder-lib/src/platformPackager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
Configuration,
ElectronPlatformName,
FileAssociation,
LinuxPackager,
Packager,
PackagerOptions,
Platform,
Expand Down Expand Up @@ -323,10 +324,6 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>

await this.info.afterPack(packContext)

if (this.config.electronFuses != null) {
await this.addElectronFuses(packContext, this.config.electronFuses)
}

if (framework.afterPack != null) {
await framework.afterPack(packContext)
}
Expand All @@ -338,31 +335,52 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
}
}

private async addElectronFuses(context: AfterPackContext, fuses: ConfigurationFusesV1Options) {
const {
protected async doSignAfterPack(outDir: string, appOutDir: string, platformName: ElectronPlatformName, arch: Arch, platformSpecificBuildOptions: DC, targets: Array<Target>) {
const asarOptions = await this.computeAsarOptions(platformSpecificBuildOptions)
const isAsar = asarOptions != null
const packContext = {
appOutDir,
packager: { appInfo },
electronPlatformName,
outDir,
arch,
} = context
targets,
packager: this,
electronPlatformName: platformName,
}
// the fuses MUST be flipped right before signing
if (this.config.electronFuses != null) {
await this.addElectronFuses(packContext, this.config.electronFuses)
}
const didSign = await this.signApp(packContext, isAsar)
const afterSign = await resolveFunction(this.appInfo.type, this.config.afterSign, "afterSign")
if (afterSign != null) {
if (didSign) {
await Promise.resolve(afterSign(packContext))
} else {
log.warn(null, `skipping "afterSign" hook as no signing occurred, perhaps you intended "afterPack"?`)
}
}
}

public async addElectronFuses(context: AfterPackContext, fuses: ConfigurationFusesV1Options) {
const { appOutDir, electronPlatformName, packager } = context

const ext = {
darwin: ".app",
win32: ".exe",
linux: [""],
linux: "",
}[electronPlatformName]

const executableName = electronPlatformName === "linux" ? appInfo.sanitizedName.toLowerCase() : appInfo.productFilename
const executableName = packager instanceof LinuxPackager ? packager.executableName : packager.appInfo.productFilename
const electronBinaryPath = path.join(appOutDir, `${executableName}${ext}`)

log.info({ electronPath: log.filePath(electronBinaryPath) }, "executing @electron/fuses")
return flipFuses(electronBinaryPath, this.generateFuseConfig(electronPlatformName, arch, fuses))
return flipFuses(electronBinaryPath, this.generateFuseConfig(fuses))
}

private generateFuseConfig(electronPlatformName: string, arch: Arch, fuses: ConfigurationFusesV1Options): FuseV1Config {
private generateFuseConfig(fuses: ConfigurationFusesV1Options): FuseV1Config {
const config: FuseV1Config = {
version: FuseVersion.V1,
resetAdHocDarwinSignature: fuses.resetAdHocDarwinSignature ?? (electronPlatformName === "darwin" && arch === Arch.universal),
resetAdHocDarwinSignature: fuses.resetAdHocDarwinSignature,
}
// this is annoying, but we must filter out undefined entries because some older electron versions will receive `the fuse wire in this version of Electron is not long enough` even if entry is set undefined
if (fuses.runAsNode != null) {
Expand Down Expand Up @@ -392,28 +410,6 @@ export abstract class PlatformPackager<DC extends PlatformSpecificBuildOptions>
return config
}

protected async doSignAfterPack(outDir: string, appOutDir: string, platformName: ElectronPlatformName, arch: Arch, platformSpecificBuildOptions: DC, targets: Array<Target>) {
const asarOptions = await this.computeAsarOptions(platformSpecificBuildOptions)
const isAsar = asarOptions != null
const packContext = {
appOutDir,
outDir,
arch,
targets,
packager: this,
electronPlatformName: platformName,
}
const didSign = await this.signApp(packContext, isAsar)
const afterSign = await resolveFunction(this.appInfo.type, this.config.afterSign, "afterSign")
if (afterSign != null) {
if (didSign) {
await Promise.resolve(afterSign(packContext))
} else {
log.warn(null, `skipping "afterSign" hook as no signing occurred, perhaps you intended "afterPack"?`)
}
}
}

// eslint-disable-next-line
protected createTransformerForExtraFiles(packContext: AfterPackContext): FileTransformer | null {
return null
Expand Down
10 changes: 10 additions & 0 deletions test/src/linux/debTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ test.ifNotWindows(
deb: {
depends: ["foo"],
},
electronFuses: {
runAsNode: true,
enableCookieEncryption: true,
enableNodeOptionsEnvironmentVariable: true,
enableNodeCliInspectArguments: true,
enableEmbeddedAsarIntegrityValidation: true,
onlyLoadAppFromAsar: true,
loadBrowserProcessSpecificV8Snapshot: true,
grantFileProtocolExtraPrivileges: undefined, // unsupported on current electron version in our tests
},
},
})
)
Expand Down
12 changes: 12 additions & 0 deletions test/src/linux/flatpakTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@ test.ifAll.ifDevOrLinuxCi(
"flatpak",
app({
targets: Platform.LINUX.createTarget("flatpak"),
config: {
electronFuses: {
runAsNode: true,
enableCookieEncryption: true,
enableNodeOptionsEnvironmentVariable: true,
enableNodeCliInspectArguments: true,
enableEmbeddedAsarIntegrityValidation: true,
onlyLoadAppFromAsar: true,
loadBrowserProcessSpecificV8Snapshot: true,
grantFileProtocolExtraPrivileges: undefined, // unsupported on current electron version in our tests
},
},
})
)

Expand Down
38 changes: 36 additions & 2 deletions test/src/linux/fpmTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,42 @@ if (process.platform === "win32") {
}

// "apk" is very slow, don't test for now
test.ifAll.ifDevOrLinuxCi("targets", app({ targets: Platform.LINUX.createTarget(["sh", "freebsd", "pacman", "zip", "7z"]) }))
test.ifAll.ifDevOrLinuxCi(
"targets",
app({
targets: Platform.LINUX.createTarget(["sh", "freebsd", "pacman", "zip", "7z"]),
config: {
electronFuses: {
runAsNode: true,
enableCookieEncryption: true,
enableNodeOptionsEnvironmentVariable: true,
enableNodeCliInspectArguments: true,
enableEmbeddedAsarIntegrityValidation: true,
onlyLoadAppFromAsar: true,
loadBrowserProcessSpecificV8Snapshot: true,
grantFileProtocolExtraPrivileges: undefined, // unsupported on current electron version in our tests
},
},
})
)

// https://github.com/electron-userland/electron-builder/issues/460
// for some reasons in parallel to fmp we cannot use tar
test.ifAll.ifDevOrLinuxCi("rpm and tar.gz", app({ targets: Platform.LINUX.createTarget(["rpm", "tar.gz"]) }))
test.ifAll.ifDevOrLinuxCi(
"rpm and tar.gz",
app({
targets: Platform.LINUX.createTarget(["rpm", "tar.gz"]),
config: {
electronFuses: {
runAsNode: true,
enableCookieEncryption: true,
enableNodeOptionsEnvironmentVariable: true,
enableNodeCliInspectArguments: true,
enableEmbeddedAsarIntegrityValidation: true,
onlyLoadAppFromAsar: true,
loadBrowserProcessSpecificV8Snapshot: true,
grantFileProtocolExtraPrivileges: undefined, // unsupported on current electron version in our tests
},
},
})
)
19 changes: 18 additions & 1 deletion test/src/linux/linuxArchiveTest.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
import { Platform } from "electron-builder"
import { app } from "../helpers/packTester"

test.ifAll.ifNotWindows.ifDevOrLinuxCi("tar", app({ targets: Platform.LINUX.createTarget(["tar.xz", "tar.lz", "tar.bz2"]) }))
test.ifAll.ifNotWindows.ifDevOrLinuxCi(
"tar",
app({
targets: Platform.LINUX.createTarget(["tar.xz", "tar.lz", "tar.bz2"]),
config: {
electronFuses: {
runAsNode: true,
enableCookieEncryption: true,
enableNodeOptionsEnvironmentVariable: true,
enableNodeCliInspectArguments: true,
enableEmbeddedAsarIntegrityValidation: true,
onlyLoadAppFromAsar: true,
loadBrowserProcessSpecificV8Snapshot: true,
grantFileProtocolExtraPrivileges: undefined, // unsupported on current electron version in our tests
},
},
})
)
12 changes: 11 additions & 1 deletion test/src/linux/linuxPackagerTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ test.ifNotWindows(
onlyLoadAppFromAsar: true,
loadBrowserProcessSpecificV8Snapshot: true,
grantFileProtocolExtraPrivileges: undefined, // unsupported on current electron version in our tests
}
},
},
})
)
Expand Down Expand Up @@ -147,6 +147,16 @@ test.ifNotWindows.ifNotCiMac(
// tslint:disable-next-line:no-invalid-template-strings
artifactName: "boo-${productName}",
},
electronFuses: {
runAsNode: true,
enableCookieEncryption: true,
enableNodeOptionsEnvironmentVariable: true,
enableNodeCliInspectArguments: true,
enableEmbeddedAsarIntegrityValidation: true,
onlyLoadAppFromAsar: true,
loadBrowserProcessSpecificV8Snapshot: true,
grantFileProtocolExtraPrivileges: undefined, // unsupported on current electron version in our tests
},
},
effectiveOptionComputed: async it => {
const content: string = it.desktop
Expand Down
10 changes: 10 additions & 0 deletions test/src/linux/snapHeavyTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ test.ifAll(
snap: {
useTemplateApp: false,
},
electronFuses: {
runAsNode: true,
enableCookieEncryption: true,
enableNodeOptionsEnvironmentVariable: true,
enableNodeCliInspectArguments: true,
enableEmbeddedAsarIntegrityValidation: true,
onlyLoadAppFromAsar: true,
loadBrowserProcessSpecificV8Snapshot: true,
grantFileProtocolExtraPrivileges: undefined, // unsupported on current electron version in our tests
},
},
})
)
Expand Down
10 changes: 10 additions & 0 deletions test/src/linux/snapTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ test.ifAll.ifDevOrLinuxCi(
name: "sep",
},
productName: "Sep",
electronFuses: {
runAsNode: true,
enableCookieEncryption: true,
enableNodeOptionsEnvironmentVariable: true,
enableNodeCliInspectArguments: true,
enableEmbeddedAsarIntegrityValidation: true,
onlyLoadAppFromAsar: true,
loadBrowserProcessSpecificV8Snapshot: true,
grantFileProtocolExtraPrivileges: undefined, // unsupported on current electron version in our tests
},
},
})
)
Expand Down
2 changes: 1 addition & 1 deletion test/src/mac/macPackagerTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ test.ifMac.ifAll("two-package", () =>
onlyLoadAppFromAsar: true,
loadBrowserProcessSpecificV8Snapshot: true,
grantFileProtocolExtraPrivileges: undefined, // unsupported on current electron version in our tests
}
},
},
},
{
Expand Down
12 changes: 12 additions & 0 deletions test/src/windows/appxTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@ it.ifDevOrWinCi(
app(
{
targets: Platform.WINDOWS.createTarget(["appx"], Arch.x64),
config: {
electronFuses: {
runAsNode: true,
enableCookieEncryption: true,
enableNodeOptionsEnvironmentVariable: true,
enableNodeCliInspectArguments: true,
enableEmbeddedAsarIntegrityValidation: true,
onlyLoadAppFromAsar: true,
loadBrowserProcessSpecificV8Snapshot: true,
grantFileProtocolExtraPrivileges: undefined, // unsupported on current electron version in our tests
},
},
},
{
projectDirCreated: async projectDir => {
Expand Down
Loading

0 comments on commit 5e296d6

Please sign in to comment.