diff --git a/.changeset/tame-radios-pump.md b/.changeset/tame-radios-pump.md new file mode 100644 index 00000000000..8098563cd9b --- /dev/null +++ b/.changeset/tame-radios-pump.md @@ -0,0 +1,5 @@ +--- +"app-builder-lib": patch +--- + +fix(mac): allow ad-hoc identities for codesigning diff --git a/packages/app-builder-lib/scheme.json b/packages/app-builder-lib/scheme.json index 2a05e9f5cea..4ec4fcce1cb 100644 --- a/packages/app-builder-lib/scheme.json +++ b/packages/app-builder-lib/scheme.json @@ -2702,7 +2702,7 @@ ] }, "identity": { - "description": "The name of certificate to use when signing. Consider using environment variables [CSC_LINK or CSC_NAME](./code-signing.md) instead of specifying this option.\nMAS installer identity is specified in the [mas](./mas.md).", + "description": "The name of certificate to use when signing. Consider using environment variables [CSC_LINK or CSC_NAME](./code-signing.md) instead of specifying this option.\nMAS installer identity is specified in the [mas](./mas.md).\n\nSet to `-` to use an ad-hoc identity for signing. Set to `null` to skip signing entirely.", "type": [ "null", "string" @@ -3334,7 +3334,7 @@ ] }, "identity": { - "description": "The name of certificate to use when signing. Consider using environment variables [CSC_LINK or CSC_NAME](./code-signing.md) instead of specifying this option.\nMAS installer identity is specified in the [mas](./mas.md).", + "description": "The name of certificate to use when signing. Consider using environment variables [CSC_LINK or CSC_NAME](./code-signing.md) instead of specifying this option.\nMAS installer identity is specified in the [mas](./mas.md).\n\nSet to `-` to use an ad-hoc identity for signing. Set to `null` to skip signing entirely.", "type": [ "null", "string" diff --git a/packages/app-builder-lib/src/codeSign/macCodeSign.ts b/packages/app-builder-lib/src/codeSign/macCodeSign.ts index eed74b93ca4..81d5c87dd61 100644 --- a/packages/app-builder-lib/src/codeSign/macCodeSign.ts +++ b/packages/app-builder-lib/src/codeSign/macCodeSign.ts @@ -88,10 +88,11 @@ export async function reportError(isMas: boolean, certificateTypes: CertType[], .join("\n") } + const skipMessage = "skipped macOS application code signing" if (isMas || isForceCodeSigning) { - throw new Error(Logger.createMessage("skipped macOS application code signing", logFields, "error", it => it)) + throw new Error(Logger.createMessage(skipMessage, logFields, "error", it => it)) } else { - log.warn(logFields, "skipped macOS application code signing") + log.warn(logFields, skipMessage) } } diff --git a/packages/app-builder-lib/src/macPackager.ts b/packages/app-builder-lib/src/macPackager.ts index 5535e01e13a..73422d676e9 100644 --- a/packages/app-builder-lib/src/macPackager.ts +++ b/packages/app-builder-lib/src/macPackager.ts @@ -1,6 +1,7 @@ import { notarize } from "@electron/notarize" import { NotarizeOptionsNotaryTool, NotaryToolKeychainCredentials } from "@electron/notarize/lib/types" import { PerFileSignOptions, SignOptions } from "@electron/osx-sign/dist/cjs/types" +import { Identity } from "@electron/osx-sign/dist/cjs/util-identities" import { Arch, AsyncTaskManager, copyFile, deepAssign, exec, getArchSuffix, InvalidConfigurationError, log, orIfFileNotExist, statOrNull, unlinkIfExists, use } from "builder-util" import { MemoLazy, Nullish } from "builder-util-runtime" import * as fs from "fs/promises" @@ -8,7 +9,7 @@ import { mkdir, readdir } from "fs/promises" import { Lazy } from "lazy-val" import * as path from "path" import { AppInfo } from "./appInfo" -import { CertType, CodeSigningInfo, createKeychain, CreateKeychainOptions, findIdentity, Identity, isSignAllowed, removeKeychain, reportError, sign } from "./codeSign/macCodeSign" +import { CertType, CodeSigningInfo, createKeychain, CreateKeychainOptions, findIdentity, isSignAllowed, removeKeychain, reportError, sign } from "./codeSign/macCodeSign" import { DIR_TARGET, Platform, Target } from "./core" import { AfterPackContext, ElectronPlatformName } from "./index" import { MacConfiguration, MasConfiguration } from "./options/macOptions" @@ -229,7 +230,7 @@ export class MacPackager extends PlatformPackager { } } - private async sign(appPath: string, outDir: string | null, masOptions: MasConfiguration | null, arch: Arch | null): Promise { + private async sign(appPath: string, outDir: string | null, masOptions: MasConfiguration | null, arch: Arch): Promise { if (!isSignAllowed()) { return false } @@ -237,12 +238,16 @@ export class MacPackager extends PlatformPackager { const isMas = masOptions != null const options = masOptions == null ? this.platformSpecificBuildOptions : masOptions const qualifier = options.identity + const fallBackToAdhoc = (arch === Arch.arm64 || arch === Arch.universal) && !this.forceCodeSigning if (qualifier === null) { if (this.forceCodeSigning) { throw new InvalidConfigurationError("identity explicitly is set to null, but forceCodeSigning is set to true") } log.info({ reason: "identity explicitly is set to null" }, "skipped macOS code signing") + if (fallBackToAdhoc) { + log.warn("arm64 requires signing, but identity is set to null and signing is being skipped") + } return false } @@ -268,7 +273,13 @@ export class MacPackager extends PlatformPackager { } } - if (!options.sign && identity == null) { + const noIdentity = !options.sign && identity == null + if (qualifier === "-") { + identity = new Identity("-", undefined) + } else if (noIdentity && fallBackToAdhoc) { + log.warn(null, "falling back to ad-hoc signature for macOS application code signing") + identity = new Identity("-", undefined) + } else if (noIdentity) { await reportError(isMas, certificateTypes, qualifier, keychainFile, this.forceCodeSigning) return false } @@ -514,7 +525,7 @@ export class MacPackager extends PlatformPackager { await Promise.all( directories.map(async (file: string) => { if (shouldSign(file)) { - await this.sign(path.join(sourceDirectory, file), null, null, null) + await this.sign(path.join(sourceDirectory, file), null, null, packContext.arch) } }) ) diff --git a/packages/app-builder-lib/src/options/macOptions.ts b/packages/app-builder-lib/src/options/macOptions.ts index 9ae69a2b0c6..b03f1460193 100644 --- a/packages/app-builder-lib/src/options/macOptions.ts +++ b/packages/app-builder-lib/src/options/macOptions.ts @@ -21,6 +21,8 @@ export interface MacConfiguration extends PlatformSpecificBuildOptions { /** * The name of certificate to use when signing. Consider using environment variables [CSC_LINK or CSC_NAME](./code-signing.md) instead of specifying this option. * MAS installer identity is specified in the [mas](./mas.md). + * + * Set to `-` to use an ad-hoc identity for signing. Set to `null` to skip signing entirely. */ readonly identity?: string | null diff --git a/pages/code-signing-mac.md b/pages/code-signing-mac.md index 9ce77f65107..a26625e622c 100644 --- a/pages/code-signing-mac.md +++ b/pages/code-signing-mac.md @@ -1,6 +1,6 @@ macOS code signing is supported. If the configuration values are provided correctly in your package.json, then signing should be automatically executed. -On a macOS development machine, a valid and appropriate identity from your keychain will be automatically used. +On a macOS development machine, a valid and appropriate identity from your keychain will be automatically used. If no such identity exists, the default behavior depends on the target architecture. On ARM or universal builds, an ad-hoc signature will be applied by default. On Intel-only builds, the default behavior is to not sign at all. !!! tip See article [Notarizing your Electron application](https://kilianvalkhof.com/2019/electron/notarizing-your-electron-application/). @@ -23,7 +23,7 @@ On a macOS development machine, a valid and appropriate identity from your keych To disable Code Signing when building for macOS leave all the above vars unset except for `CSC_IDENTITY_AUTO_DISCOVERY` which needs to be set to `false`. This can be done by running `export CSC_IDENTITY_AUTO_DISCOVERY=false`. -Another way — set `mac.identity` to `null`. You can pass aditional configuration using CLI as well: `-c.mac.identity=null`. +Another way — set `mac.identity` to `null`. You can pass additional configuration using CLI as well: `-c.mac.identity=null`. If you are building for ARM, you likely actually want to use ad-hoc signing, in which case you should set `mac.identity` to `-`. ## Code Signing and Notarization Tutorial Thank you to a community member for putting this together.