UNPKG

signing-enclave

Version:

A code signing and notarization tool for macOS and Windows applications. Uses Azure Key Vault for secret and certificate management.

105 lines 4.68 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.downloadMacCertificateFromHSM = downloadMacCertificateFromHSM; exports.macOsSign = macOsSign; const execa_1 = __importDefault(require("execa")); const secretClient_1 = require("./secretClient"); const osx_sign_1 = require("@electron/osx-sign"); async function downloadMacCertificateFromHSM(certName) { return await (0, secretClient_1.downloadCertificateFile)(certName, { postfix: ".p12" }); } /** * Imports the certificate into a temporary Keychain. * @param {string} tempFilePath - Path to the temporary p12/pfx file. * @param {string} keychainName - Name of the temporary Keychain. * @param {string} keychainPassword - Password for the temporary Keychain. */ async function importCertToKeychain(tempFilePath, keychainName, keychainPassword) { await (0, execa_1.default)(`security list-keychains -d user -s login.keychain`, { shell: "/bin/bash", }); // Create the temporary Keychain await (0, execa_1.default)(`security create-keychain -p ${keychainPassword} ${keychainName}`, { shell: "/bin/bash" }); // Append temp keychain to the user domain await (0, execa_1.default)(`security list-keychains -d user -s ${keychainName} $(security list-keychains -d user | sed s/\\"//g)`, { shell: "/bin/bash" }); // Remove relock timeout await (0, execa_1.default)(`security set-keychain-settings ${keychainName}`, { shell: "/bin/bash", }); // Unlock the Keychain await (0, execa_1.default)(`security unlock-keychain -p ${keychainPassword} ${keychainName}`, { shell: "/bin/bash" }); // Import the p12 file into the temporary Keychain await (0, execa_1.default)(`security import "${tempFilePath}" -k "${keychainName}" -P "" -T /usr/bin/codesign`, { shell: "/bin/bash" }); const identity = await findSigningIdentity(keychainName); // Enable codesigning from a non user interactive shell await (0, execa_1.default)(`security set-key-partition-list -S apple-tool:,apple:, -s -k ${keychainPassword} -D "${identity}" -t private ${keychainName}`, { shell: "/bin/bash" }); return identity; } /** * Finds the signing identity in the Keychain. * @param {string} keychainName - Name of the Keychain. * @returns {string} - The signing identity name. */ async function findSigningIdentity(keychainName) { const output = (await (0, execa_1.default)(`security find-identity -p codesigning -v "${keychainName}"`, { shell: "/bin/bash", })).stdout; const match = output.match(/"([^"]+)"/); if (match && match[1]) { return match[1]; } else { throw new Error("No valid signing identity found."); } } /** * Deletes the temporary Keychain. * @param {string} keychainName - Name of the Keychain to delete. */ async function deleteKeychain(keychainName) { console.log(`Deleting keychain: ${keychainName}`); await (0, execa_1.default)(`security delete-keychain "${keychainName}"`, { shell: "/bin/bash", }); } /** * Signs an application using a certificate from Azure KeyVault. * @param pathToSign - The path to the application to sign. * @param certName - The name of the certificate to use on Azure KeyVault. */ async function macOsSign(pathToSign, $certName) { const hrstart = process.hrtime(); const keychain = crypto.randomUUID(); const keychainPassword = crypto.randomUUID(); const tempFile = await downloadMacCertificateFromHSM($certName); try { const identity = await importCertToKeychain(tempFile.secretFilePath, keychain, keychainPassword); try { await tempFile.cleanup(); const initTime = process.hrtime(hrstart); console.debug(`Cert imported in ${initTime[0]}s ${(initTime[1] / 1000000).toFixed(0)}ms: ${$certName}`); const hrsignstart = process.hrtime(); console.log(`Signing: ${pathToSign}`); await (0, osx_sign_1.signAsync)({ app: pathToSign, keychain: keychain, identity: identity, strictVerify: false, }); const signTime = process.hrtime(hrsignstart); console.debug(`Signed in ${signTime[0]}s ${(signTime[1] / 1000000).toFixed(0)}ms: ${$certName}`); } finally { await deleteKeychain(keychain); } } catch (error) { console.error(error); await tempFile.cleanup(); throw error; } } //# sourceMappingURL=macOSSigning.js.map