diff --git a/common.js b/common.js index 7c9bdb5c..3a8aab7c 100644 --- a/common.js +++ b/common.js @@ -58,6 +58,30 @@ function parseCLIArgs (argv) { args.osxSign = true } + let noNotarize = false + args.osxNotarize = args['osx-notarize'] + if (Array.isArray(args.osxNotarize) || (args.osxNotarize && typeof args.osxNotarize !== 'object')) { + warning('do not use --osx-notarize, use the sub-properties (see --help)') + noNotarize = true + } else if (args.osxNotarize) { + if (!args.osxNotarize.appleId) { + warning('--osx-notarize.appleId is required when using notarization, notarize will not run (see --help)') + noNotarize = true + } + if (!args.osxNotarize.appleIdPassword) { + warning('--osx-notarize.appleIdPassword is required when using notarization, notarize will not run (see --help)') + noNotarize = true + } + } + if (!args.osxSign) { + warning('notarization was enabled but osx code signing was not, code signing is a requirement for notarization, notarize will not run') + noNotarize = true + } + + if (noNotarize) { + args.osxNotarize = null + } + // tmpdir: `String` or `false` if (args.tmpdir === 'false') { warning('--tmpdir=false is deprecated, use --no-tmpdir instead') diff --git a/docs/api.md b/docs/api.md index 734aa340..3fcf5996 100644 --- a/docs/api.md +++ b/docs/api.md @@ -412,6 +412,14 @@ Entries from `extend-info` override entries in the base plist file supplied by ` The bundle identifier to use in the application helper's plist. +##### `osxNotarize` + +*Object* + +If present, notarizes OS X target apps when the host platform is OS X and XCode is installed. The configuration values listed below can be customized. See [electron-notarize](https://github.com/electron-userland/electron-notarize#method-notarizeopts-promisevoid) for more detailed option descriptions and how to use `appleIdPassword` safely. +- `appleId` (*String*): Your apple ID username / email +- `appleIdPassword` (*String*): The password for your apple ID, can be a keychain reference + ##### `osxSign` *Object* or *`true`* diff --git a/mac.js b/mac.js index e8333a68..15d59d43 100644 --- a/mac.js +++ b/mac.js @@ -6,6 +6,7 @@ const debug = require('debug')('electron-packager') const fs = require('fs-extra') const path = require('path') const plist = require('plist') +const { notarize } = require('electron-notarize') const { signAsync } = require('electron-osx-sign') class MacApp extends App { @@ -52,6 +53,10 @@ class MacApp extends App { return `com.electron.${common.sanitizeAppName(this.appName).toLowerCase()}` } + get bundleName () { + return filterCFBundleIdentifier(this.opts.appBundleId || this.defaultBundleName) + } + get originalResourcesDir () { return path.join(this.contentsPath, 'Resources') } @@ -172,7 +177,7 @@ class MacApp extends App { updatePlistFiles () { let plists - const appBundleIdentifier = filterCFBundleIdentifier(this.opts.appBundleId || this.defaultBundleName) + const appBundleIdentifier = this.bundleName this.helperBundleIdentifier = filterCFBundleIdentifier(this.opts.helperBundleId || `${appBundleIdentifier}.helper`) return this.determinePlistFilesToUpdate() @@ -292,6 +297,12 @@ class MacApp extends App { if (osxSignOpt) { const signOpts = createSignOpts(osxSignOpt, platform, this.renamedAppPath, version, this.opts.quiet) + if (this.opts.osxNotarize && !signOpts.hardenedRuntime) { + common.warning('notarization is enabled but hardenedRuntime was not enabled in ' + + 'signing options. It has been enabled for you but you should ' + + 'enable it in your config.') + signOpts.hardenedRuntime = true + } debug(`Running electron-osx-sign with the options ${JSON.stringify(signOpts)}`) return signAsync(signOpts) // Although not signed successfully, the application is packed. @@ -301,6 +312,20 @@ class MacApp extends App { } } + notarizeAppIfSpecified () { + let osxNotarizeOpt = this.opts.osxNotarize + + if (osxNotarizeOpt) { + const notarizeOpts = createNotarizeOpts( + osxNotarizeOpt, + this.bundleName, + this.renamedAppPath, + this.opts.quiet + ) + return notarize(notarizeOpts) + } + } + create () { return this.initialize() .then(() => this.updatePlistFiles()) @@ -309,6 +334,7 @@ class MacApp extends App { .then(() => this.renameAppAndHelpers()) .then(() => this.copyExtraResources()) .then(() => this.signAppIfSpecified()) + .then(() => this.notarizeAppIfSpecified()) .then(() => this.move()) } } @@ -348,6 +374,18 @@ function createSignOpts (properties, platform, app, version, quiet) { return signOpts } +function createNotarizeOpts (properties, appBundleId, appPath, quiet) { + const notarizeOpts = properties + + // osx-notarize options are handed off to notarize module, but + // with a few additions from the main options + // user may think they can pass bundle ID or appPath but they will be ignored + common.subOptionWarning(notarizeOpts, 'osx-notarize', 'appBundleId', appBundleId, quiet) + common.subOptionWarning(notarizeOpts, 'osx-notarize', 'appPath', appPath, quiet) + + return notarizeOpts +} + module.exports = { App: MacApp, createSignOpts: createSignOpts, diff --git a/package.json b/package.json index 9fe0860b..0a146e74 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,8 @@ "asar": "^0.14.0", "debug": "^4.0.1", "electron-download": "^4.1.1", - "electron-osx-sign": "^0.4.1", + "electron-notarize": "^0.0.5", + "electron-osx-sign": "^0.4.11", "extract-zip": "^1.0.3", "fs-extra": "^7.0.0", "galactus": "^0.2.1", diff --git a/usage.txt b/usage.txt index 58c753c2..7ad3dd28 100644 --- a/usage.txt +++ b/usage.txt @@ -82,6 +82,12 @@ osx-sign (OSX host platform only) Whether to sign the OSX app packages - identity: should contain the identity to be used when running `codesign` - entitlements: the path to entitlements used in signing - entitlements-inherit: the path to the 'child' entitlements +osx-notarize (OSX host platform only) Whether to notarize the OSX app packages. You must + use dot notation to configure a list of sub-properties, e.g. --osx-notarize.appleId="foo@example.com" + For info on supported values see https://github.com/electron-userland/electron-notarize#method-notarizeopts-promisevoid + Properties supported: + - appleId: should contain your apple ID username / email + - appleIdPassword: should contain the password for the provided apple ID protocol URL protocol scheme to register the app as an opener of. For example, `--protocol=myapp` would register the app to open URLs such as `myapp://path`. This argument requires a `--protocol-name`