[macOS] Use macapptool for signing and notarizing macOS binaries

nw-builder has been producing invalid frameworks at least since
2017, at it seems there's no progress in fixing it (see
https://github.com/nwjs/nw.js/issues/6338). To workaround this problem,
we use macapptool to proper seal all the framework resources so it
can be signed and passes the validations required for notarization.
Since we're introducing this dependency, we can also use macapptool
to simplify signing and notarization.

To create a signed macOS build, pass the --codesign flag.
--codesign-identity can be used to use a non-default identity
("Developer ID")

To notarize a signed bundle, use the --notarize flag. There are
also flags provided to specify the username/password for the
notarization service.
pull/935/head
Alberto García Hierro 5 years ago
parent 75ca72104a
commit 5e3fd3ebd4

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-executable-page-protection</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>

@ -161,18 +161,31 @@ function get_task_name(key) {
return 'build-' + key.replace(/([A-Z])/g, function($1){return "-"+$1.toLowerCase();}); return 'build-' + key.replace(/([A-Z])/g, function($1){return "-"+$1.toLowerCase();});
} }
function getArguments() {
return minimist(process.argv.slice(2));
}
function getPlatforms() { function getPlatforms() {
var defaultPlatforms = ['win32', 'win64', 'osx64', 'linux32', 'linux64']; const defaultPlatforms = ['win32', 'win64', 'osx64', 'linux32', 'linux64'];
var argv = minimist(process.argv.slice(2)); const platform = getArguments().platform;
if (argv.platform) { if (platform) {
if (defaultPlatforms.indexOf(argv.platform) < 0) { if (defaultPlatforms.indexOf(platform) < 0) {
throw "Invalid platform '" + argv.platform + "'. Available ones are: " + defaultPlatforms; throw new Error(`Invalid platform "${platform}". Available ones are: ${defaultPlatforms}`)
} }
return [argv.platform]; return [platform];
} }
return defaultPlatforms; return defaultPlatforms;
} }
function execSync() {
const cmd = arguments[0];
const args = Array.prototype.slice.call(arguments, 1);
const result = child_process.spawnSync(cmd, args, {stdio: 'inherit'});
if (result.error) {
throw result.error;
}
}
// Define build tasks dynamically based on the sources // Define build tasks dynamically based on the sources
// and output variables. // and output variables.
var buildCssTasks = []; var buildCssTasks = [];
@ -289,15 +302,28 @@ gulp.task('release-win64', function() {
return archive.finalize(); return archive.finalize();
}); });
gulp.task('release-osx64', function() { gulp.task('release-osx64', function(done) {
var pkg = require('./package.json'); var pkg = require('./package.json');
var src = path.join(appsDir, pkg.name, 'osx64', pkg.name + '.app'); var src = path.join(appsDir, pkg.name, 'osx64', pkg.name + '.app');
// Check if we want to sign the .app bundle // Check if we want to sign the .app bundle
if (process.env.CODESIGN_IDENTITY) { if (getArguments().codesign) {
var sign_cmd = 'codesign --verbose --force --sign "' + process.env.CODESIGN_IDENTITY + '" ' + src; // macapptool can be downloaded from
child_process.execSync(sign_cmd); // https://github.com/fiam/macapptool
//
// Make sure the bundle is well formed
execSync('macapptool', '-v', '1', 'fix', src);
// Sign
const codesignArgs = ['macapptool', '-v', '1', 'sign'];
const codesignIdentity = getArguments()['codesign-identity'];
if (codesignIdentity) {
codesignArgs.push('-i', codesignIdentity);
}
codesignArgs.push('-e', 'entitlements.plist');
codesignArgs.push(src)
execSync.apply(this, codesignArgs);
} }
var output = fs.createWriteStream(path.join(appsDir, get_release_filename('macOS', 'zip'))); const zipFilename = path.join(appsDir, get_release_filename('macOS', 'zip'));
var output = fs.createWriteStream(zipFilename);
var archive = archiver('zip', { var archive = archiver('zip', {
zlib: { level: 9 } zlib: { level: 9 }
}); });
@ -305,7 +331,23 @@ gulp.task('release-osx64', function() {
archive.on('error', function(err) { throw err; }); archive.on('error', function(err) { throw err; });
archive.pipe(output); archive.pipe(output);
archive.directory(src, 'INAV Configurator.app'); archive.directory(src, 'INAV Configurator.app');
return archive.finalize(); output.on('close', function() {
if (getArguments().notarize) {
const notarizeArgs = ['macapptool', '-v', '1', 'notarize'];
const notarizationUsername = getArguments()['notarization-username'];
if (notarizationUsername) {
notarizeArgs.push('-u', notarizationUsername)
}
const notarizationPassword = getArguments()['notarization-password'];
if (notarizationPassword) {
notarizeArgs.push('-p', notarizationPassword)
}
notarizeArgs.push(zipFilename)
execSync.apply(this, notarizeArgs);
}
done();
});
archive.finalize();
}); });
function releaseLinux(bits) { function releaseLinux(bits) {

Loading…
Cancel
Save