From 7ab9ca6e528901fd9d8d79fde44bf3c828b3f2ab Mon Sep 17 00:00:00 2001 From: develar Date: Mon, 31 Oct 2016 11:14:03 +0100 Subject: [PATCH] fix: Code Sign with Mac Developer certificates Closes #812 --- package.json | 2 +- src/codeSign.ts | 16 +++++++++++----- src/macPackager.ts | 36 ++++++++++++++++++++++-------------- test/src/nsisUpdaterTest.ts | 1 + yarn.lock | 20 +++++++++++--------- 5 files changed, 46 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index a7b7cb09fd0..52f4ab5f4d8 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,7 @@ "read-installed": "^4.0.3", "sanitize-filename": "^1.6.1", "semver": "^5.3.0", - "source-map-support": "^0.4.5", + "source-map-support": "^0.4.6", "tunnel-agent": "^0.4.3", "update-notifier": "^1.0.2", "uuid-1345": "^0.99.6", diff --git a/src/codeSign.ts b/src/codeSign.ts index 2bca0f89975..d59e71e08b0 100644 --- a/src/codeSign.ts +++ b/src/codeSign.ts @@ -1,4 +1,4 @@ -import { exec, getTempName, isEmptyOrSpaces } from "./util/util" +import { exec, getTempName, isEmptyOrSpaces, isCi } from "./util/util" import { deleteFile, outputFile, copy, rename } from "fs-extra-p" import { download } from "./util/httpRequest" import * as path from "path" @@ -10,7 +10,7 @@ import { TmpDir } from "./util/tmp" const appleCertificatePrefixes = ["Developer ID Application:", "3rd Party Mac Developer Application:", "Developer ID Installer:", "3rd Party Mac Developer Installer:"] -export type CertType = "Developer ID Application" | "3rd Party Mac Developer Application" | "Developer ID Installer" | "3rd Party Mac Developer Installer" +export type CertType = "Developer ID Application" | "3rd Party Mac Developer Application" | "Developer ID Installer" | "3rd Party Mac Developer Installer" | "Mac Developer" export interface CodeSigningInfo { keychainName?: string | null @@ -133,7 +133,7 @@ async function getValidIdentities(keychain?: string | null): Promise { const array = it[0].concat(it[1]) - .filter(it => !it.includes("(Missing required extension)") && !it.includes("valid identities found") && !it.includes("iPhone ") && !it.includes("com.apple.idms.appleid.prd.") && !it.includes("Mac Developer:")) + .filter(it => !it.includes("(Missing required extension)") && !it.includes("valid identities found") && !it.includes("iPhone ") && !it.includes("com.apple.idms.appleid.prd.")) // remove 1) .map(it => it.substring(it.indexOf(")") + 1).trim()) return Array.from(new Set(array)) @@ -168,6 +168,10 @@ async function _findIdentity(namePrefix: CertType, qualifier?: string | null, ke continue } + if (line.includes("Mac Developer:")) { + continue + } + for (let prefix of appleCertificatePrefixes) { if (line.includes(prefix)) { continue l @@ -183,10 +187,12 @@ async function _findIdentity(namePrefix: CertType, qualifier?: string | null, ke export async function findIdentity(certType: CertType, qualifier?: string | null, keychain?: string | null): Promise { let identity = process.env.CSC_NAME || qualifier if (isEmptyOrSpaces(identity)) { - if (keychain == null && process.env.CI == null && process.env.CSC_IDENTITY_AUTO_DISCOVERY === "false") { + if (keychain == null && !isCi() && process.env.CSC_IDENTITY_AUTO_DISCOVERY === "false") { return null } - return await _findIdentity(certType, null, keychain) + else { + return await _findIdentity(certType, null, keychain) + } } else { identity = identity.trim() diff --git a/src/macPackager.ts b/src/macPackager.ts index fbab3e61e25..b10737fad93 100644 --- a/src/macPackager.ts +++ b/src/macPackager.ts @@ -99,19 +99,27 @@ export default class MacPackager extends PlatformPackager { } let keychainName = (await this.codeSigningInfo).keychainName - const masQualifier = masOptions == null ? null : (masOptions.identity || this.platformSpecificBuildOptions.identity) + const isMas = masOptions != null + const masQualifier = isMas ? (masOptions!!.identity || this.platformSpecificBuildOptions.identity) : null - let name = await findIdentity(masOptions == null ? "Developer ID Application" : "3rd Party Mac Developer Application", masOptions == null ? this.platformSpecificBuildOptions.identity : masQualifier, keychainName) + let name = await findIdentity(isMas ? "3rd Party Mac Developer Application" : "Developer ID Application", isMas ? masQualifier : this.platformSpecificBuildOptions.identity, keychainName) if (name == null) { - let message = "App is not signed: CSC_LINK is not specified, and no valid identity in the keychain, see https://github.com/electron-userland/electron-builder/wiki/Code-Signing" - if (masOptions == null) { - message += `\nMust be "Developer ID Application:" or custom non-Apple code signing certificate` - warn(message) - return + if (!isMas) { + name = await findIdentity("Mac Developer", this.platformSpecificBuildOptions.identity, keychainName) + if (name != null) { + warn("Mac Developer is used to sign app — it is only for development and testing, not for production") + } } - else { - message += `\nMust be "3rd Party Mac Developer Application:" and "3rd Party Mac Developer Installer:"` - throw new Error(message) + + if (name == null) { + let message = `App is not signed: cannot find valid ${isMas ? '"3rd Party Mac Developer Application" identity' : `"Developer ID Application" identity or custom non-Apple code signing certificate`}, see https://github.com/electron-userland/electron-builder/wiki/Code-Signing` + if (isMas) { + throw new Error(message) + } + else { + warn(message) + return + } } } @@ -119,13 +127,13 @@ export default class MacPackager extends PlatformPackager { if (masOptions != null) { installerName = await findIdentity("3rd Party Mac Developer Installer", masQualifier, keychainName) if (installerName == null) { - throw new Error("Cannot find valid installer certificate: CSC_LINK is not specified, and no valid identity in the keychain, see https://github.com/electron-userland/electron-builder/wiki/Code-Signing") + throw new Error('Cannot find valid "3rd Party Mac Developer Installer" identity to sign MAS installer, see https://github.com/electron-userland/electron-builder/wiki/Code-Signing') } } const baseSignOptions: BaseSignOptions = { app: path.join(appOutDir, `${this.appInfo.productFilename}.app`), - platform: masOptions == null ? "darwin" : "mas", + platform: isMas ? "mas" : "darwin", keychain: keychainName || undefined, version: this.info.electronVersion } @@ -147,7 +155,7 @@ export default class MacPackager extends PlatformPackager { signOptions.entitlements = customSignOptions.entitlements } else { - const p = `entitlements.${masOptions == null ? "mac" : "mas"}.plist` + const p = `entitlements.${isMas ? "mas" : "mac"}.plist` if (resourceList.includes(p)) { signOptions.entitlements = path.join(this.buildResourcesDir, p) } @@ -157,7 +165,7 @@ export default class MacPackager extends PlatformPackager { signOptions["entitlements-inherit"] = customSignOptions.entitlementsInherit } else { - const p = `entitlements.${masOptions == null ? "mac" : "mas"}.inherit.plist` + const p = `entitlements.${isMas ? "mas" : "mac"}.inherit.plist` if (resourceList.includes(p)) { signOptions["entitlements-inherit"] = path.join(this.buildResourcesDir, p) } diff --git a/test/src/nsisUpdaterTest.ts b/test/src/nsisUpdaterTest.ts index 79bc7b2ae3c..ec5481ac641 100644 --- a/test/src/nsisUpdaterTest.ts +++ b/test/src/nsisUpdaterTest.ts @@ -15,6 +15,7 @@ g.__test_app = { }, on: function () { + // ignored }, } diff --git a/yarn.lock b/yarn.lock index 4b1bbd0e5f4..c8fc68fa175 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1,5 +1,7 @@ # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. # yarn lockfile v1 + + "@develar/semantic-release@^6.3.21": version "6.3.23" resolved "https://registry.yarnpkg.com/@develar/semantic-release/-/semantic-release-6.3.23.tgz#80c8ecd7369cf4a5c442d59d24bd614c051dd004" @@ -1983,8 +1985,8 @@ getpass@^0.1.1: assert-plus "^1.0.0" git-head@^1.14.0: - version "1.14.0" - resolved "https://registry.yarnpkg.com/git-head/-/git-head-1.14.0.tgz#be31c107fb8402098561250ef1e9d88842c391b8" + version "1.15.0" + resolved "https://registry.yarnpkg.com/git-head/-/git-head-1.15.0.tgz#e29cb415f7c9462cd3d69f8e2050544777ab263f" dependencies: git-refs "^1.1.3" @@ -2693,8 +2695,8 @@ lodash@^3.6.0: resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" lodash@^4.0.0, lodash@^4.14.0, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.5.1, lodash@^4.8.0: - version "4.16.4" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.16.4.tgz#01ce306b9bad1319f2a5528674f88297aeb70127" + version "4.16.5" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.16.5.tgz#77d88feac548009b1a5c4ca7b49ac431ce346ae8" longest@^1.0.1: version "1.0.1" @@ -3680,9 +3682,9 @@ sort-keys@^1.1.1: dependencies: is-plain-obj "^1.0.0" -source-map-support@^0.4.2, source-map-support@^0.4.4, source-map-support@^0.4.5: - version "0.4.5" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.5.tgz#4438df4219e1b3c7feb674614b4c67f9722db1e4" +source-map-support@^0.4.2, source-map-support@^0.4.4, source-map-support@^0.4.5, source-map-support@^0.4.6: + version "0.4.6" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.6.tgz#32552aa64b458392a85eab3b0b5ee61527167aeb" dependencies: source-map "^0.5.3" @@ -3993,8 +3995,8 @@ typedarray@~0.0.5: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" typescript@^2.1.0-dev.20161028: - version "2.1.0-dev.20161029" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.1.0-dev.20161029.tgz#889598d3b2a3b5c8d7e2ad6a8ba7f300eff27caa" + version "2.1.0-dev.20161031" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.1.0-dev.20161031.tgz#bcea4c7c0b6c9cf1f7bfa403bd64513c8fc782b0" uc.micro@^1.0.1, uc.micro@^1.0.3: version "1.0.3"