diff --git a/package.json b/package.json index 9900f38a..79c7ee68 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "output": "dist", "app": "build" }, - "afterSign": "scripts/notarize.js", + "afterSign": "scripts/after-sign.js", "mac": { "electronUpdaterCompatibility": ">=0.0.1", "category": "public.app-category.productivity", diff --git a/resources/safari.entitlements b/resources/safari.entitlements new file mode 100644 index 00000000..85c03d7b --- /dev/null +++ b/resources/safari.entitlements @@ -0,0 +1,14 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-write + + com.apple.security.network.client + + com.apple.security.network.server + + + diff --git a/scripts/after-sign.js b/scripts/after-sign.js new file mode 100644 index 00000000..ddf49c06 --- /dev/null +++ b/scripts/after-sign.js @@ -0,0 +1,61 @@ +require('dotenv').config(); +const { notarize } = require('electron-notarize'); + +exports.default = run; + +async function run(context) { + console.log(context); + + const appleId = process.env.APPLEID; + const appName = context.packager.appInfo.productFilename; + const appPath = `${context.appOutDir}/${appName}.app`; + const masBuild = context.electronPlatformName === 'mas'; + const macBuild = context.electronPlatformName === 'darwin'; + + if (masBuild || macBuild) { + console.log('### Signing Safari App Extension Libs'); + const resourcesPath = context.packager.MacPackager.info.Packager._buildResourcesDir; + const devId = masBuild ? '3rd Party Mac Developer Application: 8bit Solutions LLC' : + 'Developer ID Application: 8bit Solutions LLC'; + await signSafariAppLibs(appPath, resourcesPath, devId); + } + if (macBuild) { + console.log('### Notarizing ' + appPath); + return await notarize({ + appBundleId: 'com.bitwarden.desktop', + appPath: appPath, + appleId: appleId, + appleIdPassword: `@keychain:AC_PASSWORD`, + }); + } +} + +async function signSafariAppLibs(appPath, resourcesPath, devId) { + const appexPath = appPath + '/Contents/PlugIns/safari.appex'; + const appexFrameworkPath = appexPath + '/Contents/Frameworks/'; + const entitlementsPath = resourcesPath + '/safari.entitlements'; + + const libs = fs.readdirSync(appexFrameworkPath).filter((p) => p.endsWith('.dylib')) + .map((p) => appexFrameworkPath + p); + const promises = []; + libs.forEach((i) => { + const proc = child.spawn('codesign', [ + '--verbose', + '--force', + '-o', + 'runtime', + '--sign', + devId, + '--entitlements', + entitlementsPath, + i]); + stdOutProc(proc); + promises.push(new Promise((resolve) => proc.on('close', resolve))); + }); + await Promise.all(promises); +} + +function stdOutProc(proc) { + proc.stdout.on('data', (data) => console.log(data.toString())); + proc.stderr.on('data', (data) => console.error(data.toString())); +} diff --git a/scripts/notarize.js b/scripts/notarize.js deleted file mode 100644 index db2b3d99..00000000 --- a/scripts/notarize.js +++ /dev/null @@ -1,19 +0,0 @@ -require('dotenv').config(); -const { notarize } = require('electron-notarize'); - -exports.default = async function notarizing(context) { - const { electronPlatformName, appOutDir } = context; - if (electronPlatformName !== 'darwin') { - return; - } - const appleId = process.env.APPLEID; - const appName = context.packager.appInfo.productFilename; - const appPath = `${appOutDir}/${appName}.app`; - console.log('Notarizing ' + appPath); - return await notarize({ - appBundleId: 'com.bitwarden.desktop', - appPath: appPath, - appleId: appleId, - appleIdPassword: `@keychain:AC_PASSWORD`, - }); -};