From 7952ac07ae1fa28cd700ad531d17d3edcfd68cde Mon Sep 17 00:00:00 2001 From: Remo Vetere Date: Thu, 22 Dec 2022 11:07:29 +0100 Subject: [PATCH] Support identity object --- src/flat.ts | 31 +++++++++------ src/isIdentity.ts | 8 ++++ src/sign.ts | 98 +++++++++++++++++++++++++++-------------------- src/types.ts | 23 +++++++---- 4 files changed, 100 insertions(+), 60 deletions(-) create mode 100644 src/isIdentity.ts diff --git a/src/flat.ts b/src/flat.ts index 643ce30..1b4fbd7 100644 --- a/src/flat.ts +++ b/src/flat.ts @@ -4,6 +4,7 @@ import { debugLog, debugWarn, execFileAsync, validateOptsApp, validateOptsPlatfo import { Identity, findIdentities } from './util-identities'; import { FlatOptions, ValidatedFlatOptions } from './types'; +import { isIdentity } from './isIdentity'; const pkgVersion = require('../../package.json').version as string; @@ -13,7 +14,7 @@ const pkgVersion = require('../../package.json').version as string; * @param {Object} opts - Options. * @returns {Promise} Promise. */ -async function validateFlatOpts (opts: FlatOptions): Promise { +async function validateFlatOpts(opts: FlatOptions): Promise { await validateOptsApp(opts); let pkg = opts.pkg; @@ -24,7 +25,7 @@ async function validateFlatOpts (opts: FlatOptions): Promise Scripts:', - validatedOptions.scripts + validatedOptions.scripts, ); await buildApplicationPkg(validatedOptions, identityInUse); diff --git a/src/isIdentity.ts b/src/isIdentity.ts new file mode 100644 index 0000000..df93b0b --- /dev/null +++ b/src/isIdentity.ts @@ -0,0 +1,8 @@ +import { Identity } from './types'; + +export const isIdentity = (element: string | Identity): element is Identity => { + return ( + typeof (element as Identity).name !== 'undefined' && + typeof (element as Identity).hash !== 'undefined' + ); +}; diff --git a/src/sign.ts b/src/sign.ts index 9464715..1a2daea 100644 --- a/src/sign.ts +++ b/src/sign.ts @@ -11,12 +11,18 @@ import { execFileAsync, validateOptsApp, validateOptsPlatform, - walkAsync + walkAsync, } from './util'; import { Identity, findIdentities } from './util-identities'; import { preEmbedProvisioningProfile, getProvisioningProfile } from './util-provisioning-profiles'; import { preAutoEntitlements } from './util-entitlements'; -import { ElectronMacPlatform, PerFileSignOptions, SignOptions, ValidatedSignOptions } from './types'; +import { + ElectronMacPlatform, + PerFileSignOptions, + SignOptions, + ValidatedSignOptions, +} from './types'; +import { isIdentity } from './isIdentity'; const pkgVersion: string = require('../../package.json').version; @@ -25,7 +31,7 @@ const osRelease = os.release(); /** * This function returns a promise validating opts.binaries, the additional binaries to be signed along with the discovered enclosed components. */ -async function validateOptsBinaries (opts: SignOptions) { +async function validateOptsBinaries(opts: SignOptions) { if (opts.binaries) { if (!Array.isArray(opts.binaries)) { throw new Error('Additional binaries should be an Array.'); @@ -34,7 +40,7 @@ async function validateOptsBinaries (opts: SignOptions) { } } -function validateOptsIgnore (ignore: SignOptions['ignore']): ValidatedSignOptions['ignore'] { +function validateOptsIgnore(ignore: SignOptions['ignore']): ValidatedSignOptions['ignore'] { if (ignore && !(ignore instanceof Array)) { return [ignore]; } @@ -43,7 +49,7 @@ function validateOptsIgnore (ignore: SignOptions['ignore']): ValidatedSignOption /** * This function returns a promise validating all options passed in opts. */ -async function validateSignOpts (opts: SignOptions): Promise> { +async function validateSignOpts(opts: SignOptions): Promise> { await validateOptsBinaries(opts); await validateOptsApp(opts); @@ -60,7 +66,7 @@ async function validateSignOpts (opts: SignOptions): Promise + defaults: ReturnType, ) { const mergedPerFileOptions = { ...defaults }; if (opts) { if (opts.entitlements !== undefined) { if (Array.isArray(opts.entitlements)) { - const entitlements = opts.entitlements.reduce>((dict, entitlementKey) => ({ - ...dict, - [entitlementKey]: true - }), {}); + const entitlements = opts.entitlements.reduce>( + (dict, entitlementKey) => ({ + ...dict, + [entitlementKey]: true, + }), + {}, + ); const dir = await fs.mkdtemp(path.resolve(os.tmpdir(), 'tmp-entitlements-')); const entitlementsPath = path.join(dir, 'entitlements.plist'); await fs.writeFile(entitlementsPath, plist.build(entitlements), 'utf8'); @@ -164,8 +173,8 @@ async function mergeOptionsForFile ( /** * This function returns a promise codesigning only. */ -async function signApplication (opts: ValidatedSignOptions, identity: Identity) { - function shouldIgnoreFilePath (filePath: string) { +async function signApplication(opts: ValidatedSignOptions, identity: Identity) { + function shouldIgnoreFilePath(filePath: string) { if (opts.ignore) { return opts.ignore.some(function (ignore) { if (typeof ignore === 'function') { @@ -205,7 +214,7 @@ async function signApplication (opts: ValidatedSignOptions, identity: Identity) const perFileOptions = await mergeOptionsForFile( opts.optionsForFile ? opts.optionsForFile(filePath) : null, - defaultOptionsForFile(filePath, opts.platform) + defaultOptionsForFile(filePath, opts.platform), ); if (opts.preAutoEntitlements === false) { @@ -214,7 +223,7 @@ async function signApplication (opts: ValidatedSignOptions, identity: Identity) debugLog( 'Pre-sign operation enabled for entitlements automation with versions >= `1.1.1`:', '\n', - '* Disable by setting `pre-auto-entitlements` to `false`.' + '* Disable by setting `pre-auto-entitlements` to `false`.', ); if (!opts.version || compareVersion(opts.version, '1.1.1') >= 0) { // Enable Mac App Store sandboxing without using temporary-exception, introduced in Electron v1.1.1. Relates to electron#5601 @@ -222,7 +231,7 @@ async function signApplication (opts: ValidatedSignOptions, identity: Identity) identity, provisioningProfile: opts.provisioningProfile ? await getProvisioningProfile(opts.provisioningProfile, opts.keychain) - : undefined + : undefined, }); // preAutoEntitlements may provide us new entitlements, if so we update our options @@ -266,7 +275,7 @@ async function signApplication (opts: ValidatedSignOptions, identity: Identity) } else { // Remove runtime if passed in with --signature-flags debugLog( - 'Not enabling hardened runtime, current macOS version too low, requires 10.13.6 and higher' + 'Not enabling hardened runtime, current macOS version too low, requires 10.13.6 and higher', ); optionsArguments = optionsArguments.filter((arg) => { return arg !== 'runtime'; @@ -280,7 +289,7 @@ async function signApplication (opts: ValidatedSignOptions, identity: Identity) await execFileAsync( 'codesign', - perFileArgs.concat('--entitlements', perFileOptions.entitlements, filePath) + perFileArgs.concat('--entitlements', perFileOptions.entitlements, filePath), ); } @@ -295,7 +304,7 @@ async function signApplication (opts: ValidatedSignOptions, identity: Identity) '--display', '--entitlements', ':-', // Write to standard output and strip off the blob header - opts.app + opts.app, ]); debugLog('Entitlements:', '\n', result); @@ -304,7 +313,7 @@ async function signApplication (opts: ValidatedSignOptions, identity: Identity) /** * This function returns a promise signing the application. */ -export async function signApp (_opts: SignOptions) { +export async function signApp(_opts: SignOptions) { debugLog('electron-osx-sign@%s', pkgVersion); const validatedOpts = await validateSignOpts(_opts); let identities: Identity[] = []; @@ -314,34 +323,39 @@ export async function signApp (_opts: SignOptions) { if (validatedOpts.identity) { debugLog('`identity` passed in arguments.'); if (validatedOpts.identityValidation === false) { - identityInUse = new Identity(validatedOpts.identity); + identityInUse = new Identity( + isIdentity(validatedOpts.identity) ? validatedOpts.identity.name : validatedOpts.identity, + ); } else { - identities = await findIdentities(validatedOpts.keychain || null, validatedOpts.identity); + identities = await findIdentities( + validatedOpts.keychain || null, + isIdentity(validatedOpts.identity) ? validatedOpts.identity.name : validatedOpts.identity, + ); } } else { debugWarn('No `identity` passed in arguments...'); if (validatedOpts.platform === 'mas') { if (validatedOpts.type === 'distribution') { debugLog( - 'Finding `3rd Party Mac Developer Application` certificate for signing app distribution in the Mac App Store...' + 'Finding `3rd Party Mac Developer Application` certificate for signing app distribution in the Mac App Store...', ); identities = await findIdentities( validatedOpts.keychain || null, - '3rd Party Mac Developer Application:' + '3rd Party Mac Developer Application:', ); } else { debugLog( - 'Finding `Mac Developer` certificate for signing app in development for the Mac App Store signing...' + 'Finding `Mac Developer` certificate for signing app in development for the Mac App Store signing...', ); identities = await findIdentities(validatedOpts.keychain || null, 'Mac Developer:'); } } else { debugLog( - 'Finding `Developer ID Application` certificate for distribution outside the Mac App Store...' + 'Finding `Developer ID Application` certificate for distribution outside the Mac App Store...', ); identities = await findIdentities( validatedOpts.keychain || null, - 'Developer ID Application:' + 'Developer ID Application:', ); } } @@ -366,19 +380,19 @@ export async function signApp (_opts: SignOptions) { debugWarn( 'Pre-sign operation disabled for provisioning profile embedding:', '\n', - '* Enable by setting `pre-embed-provisioning-profile` to `true`.' + '* Enable by setting `pre-embed-provisioning-profile` to `true`.', ); } else { debugLog( 'Pre-sign operation enabled for provisioning profile:', '\n', - '* Disable by setting `pre-embed-provisioning-profile` to `false`.' + '* Disable by setting `pre-embed-provisioning-profile` to `false`.', ); await preEmbedProvisioningProfile( validatedOpts, validatedOpts.provisioningProfile ? await getProvisioningProfile(validatedOpts.provisioningProfile, validatedOpts.keychain) - : null + : null, ); } @@ -395,7 +409,7 @@ export async function signApp (_opts: SignOptions) { validatedOpts.binaries, '\n', '> Identity:', - validatedOpts.identity + validatedOpts.identity, ); await signApplication(validatedOpts, identityInUse); diff --git a/src/types.ts b/src/types.ts index 808ea1f..d403226 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,9 +1,14 @@ export type ElectronMacPlatform = 'darwin' | 'mas'; type SigningDistributionType = 'development' | 'distribution'; +export type Identity = { + name: string; + hash: string; +}; + export type BaseSignOptions = Readonly<{ app: string; - identity?: string; + identity?: string | Identity; platform?: ElectronMacPlatform; keychain?: string; }>; @@ -40,7 +45,7 @@ export type PerFileSignOptions = { * timestamp server. */ timestamp?: string; -} +}; type OnlySignOptions = { binaries?: string[]; @@ -74,10 +79,14 @@ type OnlyValidatedFlatOptions = { type ValidatedForm = Omit & Validated; -export type ValidatedBaseSignOptions = Readonly>; +export type ValidatedBaseSignOptions = Readonly< + ValidatedForm +>; export type SignOptions = Readonly; -export type ValidatedSignOptions = Readonly & - ValidatedBaseSignOptions>; +export type ValidatedSignOptions = Readonly< + ValidatedForm & ValidatedBaseSignOptions +>; export type FlatOptions = Readonly; -export type ValidatedFlatOptions = Readonly & - ValidatedBaseSignOptions>; +export type ValidatedFlatOptions = Readonly< + ValidatedForm & ValidatedBaseSignOptions +>;