mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
build: fix code-signing for MacOS x64 tests (#50058)
* fix: code-sign binaries for notification tests
* test: remove redundent feedURL test
* test: move squirrel feed tests to api-autoupdater
* fix: fix SQRLShipItRequest.JSONKeyPathsByPropertyKey mappings
* Revert "fix: fix SQRLShipItRequest.JSONKeyPathsByPropertyKey mappings"
This reverts commit 5ad9892a67.
* test: unsign tests requiring no signed app
This commit is contained in:
@@ -196,12 +196,21 @@ jobs:
|
||||
run: |
|
||||
cd src/out/Default
|
||||
unzip -:o dist.zip
|
||||
#- name: Import & Trust Self-Signed Codesigning Cert on MacOS
|
||||
# if: ${{ inputs.target-platform == 'macos' && inputs.target-arch == 'x64' }}
|
||||
# run: |
|
||||
# sudo security authorizationdb write com.apple.trust-settings.admin allow
|
||||
# cd src/electron
|
||||
# ./script/codesign/generate-identity.sh
|
||||
- name: Import & Trust Self-Signed Codesigning Cert on MacOS
|
||||
if: ${{ inputs.target-platform == 'macos' }}
|
||||
run: |
|
||||
cd src/electron
|
||||
./script/codesign/generate-identity.sh
|
||||
# Only sign on x64 — arm64 builds are already ad-hoc signed, and re-signing
|
||||
# with an untrusted cert breaks macOS system integrations (e.g. dock bounce).
|
||||
# Autoupdater tests sign their own fixture copies via signApp().
|
||||
- name: Sign Electron.app for macOS tests
|
||||
if: ${{ inputs.target-platform == 'macos' && inputs.target-arch == 'x64' }}
|
||||
run: |
|
||||
identity=$(src/electron/script/codesign/get-trusted-identity.sh)
|
||||
if [ -n "$identity" ]; then
|
||||
codesign -s "$identity" --deep --force src/out/Default/Electron.app
|
||||
fi
|
||||
|
||||
- name: Run Electron Tests
|
||||
shell: bash
|
||||
|
||||
21
script/codesign/cleanup-identity.sh
Executable file
21
script/codesign/cleanup-identity.sh
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Removes the codesigning keychain created by generate-identity.sh.
|
||||
# Safe to run even if generate-identity.sh was never run (each step
|
||||
# is guarded).
|
||||
|
||||
set -eo pipefail
|
||||
|
||||
KEYCHAIN="electron-codesign.keychain-db"
|
||||
|
||||
# delete-keychain also removes it from the search list
|
||||
if security list-keychains -d user | grep -q "$KEYCHAIN"; then
|
||||
security delete-keychain "$KEYCHAIN"
|
||||
echo "Deleted keychain: $KEYCHAIN"
|
||||
else
|
||||
echo "Keychain not found, nothing to delete"
|
||||
fi
|
||||
|
||||
# Clean up working directory
|
||||
rm -rf "$(dirname $0)"/.working
|
||||
echo "Cleanup complete"
|
||||
@@ -3,6 +3,8 @@
|
||||
set -eo pipefail
|
||||
|
||||
dir="$(dirname $0)"/.working
|
||||
KEYCHAIN="electron-codesign.keychain-db"
|
||||
KEYCHAIN_TEMP="$(openssl rand -hex 12)"
|
||||
|
||||
cleanup() {
|
||||
rm -rf "$dir"
|
||||
@@ -18,30 +20,16 @@ mkdir -p "$dir"
|
||||
|
||||
# Generate Certs
|
||||
openssl req -new -newkey rsa:2048 -x509 -days 7300 -nodes -config "$(dirname $0)"/codesign.cnf -extensions extended -batch -out "$dir"/certificate.cer -keyout "$dir"/certificate.key
|
||||
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain "$dir"/certificate.cer
|
||||
sudo security import "$dir"/certificate.key -A -k /Library/Keychains/System.keychain
|
||||
|
||||
# restart(reload) taskgated daemon
|
||||
sudo pkill -f /usr/libexec/taskgated
|
||||
# macOS 15+ blocks modifications to the system keychain via SIP/TCC,
|
||||
# so we use a custom user-scoped keychain instead.
|
||||
# Refs https://github.com/electron/electron/issues/48182
|
||||
security create-keychain -p "$KEYCHAIN_TEMP" "$KEYCHAIN"
|
||||
security set-keychain-settings -t 3600 -u "$KEYCHAIN"
|
||||
security unlock-keychain -p "$KEYCHAIN_TEMP" "$KEYCHAIN"
|
||||
|
||||
# need once
|
||||
sudo security authorizationdb write system.privilege.taskport allow
|
||||
# need once
|
||||
DevToolsSecurity -enable
|
||||
security list-keychains -d user -s "$KEYCHAIN" $(security list-keychains -d user | tr -d '"')
|
||||
security import "$dir"/certificate.cer -k "$KEYCHAIN" -T /usr/bin/codesign
|
||||
security import "$dir"/certificate.key -k "$KEYCHAIN" -T /usr/bin/codesign -A
|
||||
|
||||
# openssl req -newkey rsa:2048 -nodes -keyout "$dir"/private.pem -x509 -days 1 -out "$dir"/certificate.pem -extensions extended -config "$(dirname $0)"/codesign.cnf
|
||||
# openssl x509 -inform PEM -in "$dir"/certificate.pem -outform DER -out "$dir"/certificate.cer
|
||||
# openssl x509 -pubkey -noout -in "$dir"/certificate.pem > "$dir"/public.key
|
||||
# rm -f "$dir"/certificate.pem
|
||||
|
||||
# Import Certs
|
||||
# security import "$dir"/certificate.cer -k $KEY_CHAIN
|
||||
# security import "$dir"/private.pem -k $KEY_CHAIN
|
||||
# security import "$dir"/public.key -k $KEY_CHAIN
|
||||
|
||||
# Generate Trust Settings
|
||||
# TODO: Remove NPX
|
||||
npm_config_yes=true npx ts-node "$(dirname $0)"/gen-trust.ts "$dir"/certificate.cer "$dir"/trust.xml
|
||||
|
||||
# Import Trust Settings
|
||||
sudo security trust-settings-import -d "$dir/trust.xml"
|
||||
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_TEMP" "$KEYCHAIN"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
set -e
|
||||
|
||||
valid_certs=$(security find-identity -p codesigning -v)
|
||||
valid_certs=$(security find-identity -p codesigning)
|
||||
if [[ $valid_certs == *"1)"* ]]; then
|
||||
first_valid_cert=$(echo $valid_certs | sed 's/ \".*//' | sed 's/.* //')
|
||||
echo $first_valid_cert
|
||||
|
||||
@@ -56,29 +56,6 @@ ifdescribe(!process.mas)('autoUpdater module', function () {
|
||||
).to.throw('Expected options object to contain a \'url\' string property in setFeedUrl call');
|
||||
});
|
||||
});
|
||||
|
||||
ifdescribe(process.platform === 'darwin' && process.arch !== 'arm64')('on Mac', function () {
|
||||
it('emits an error when the application is unsigned', async () => {
|
||||
const errorEvent = once(autoUpdater, 'error') as Promise<[Error]>;
|
||||
autoUpdater.setFeedURL({ url: '' });
|
||||
const [error] = await errorEvent;
|
||||
expect(error.message).equal('Could not get code signature for running application');
|
||||
});
|
||||
|
||||
it('does not throw if default is the serverType', () => {
|
||||
// "Could not get code signature..." means the function got far enough to validate that serverType was OK.
|
||||
expect(() => autoUpdater.setFeedURL({ url: '', serverType: 'default' })).to.throw('Could not get code signature for running application');
|
||||
});
|
||||
|
||||
it('does not throw if json is the serverType', () => {
|
||||
// "Could not get code signature..." means the function got far enough to validate that serverType was OK.
|
||||
expect(() => autoUpdater.setFeedURL({ url: '', serverType: 'json' })).to.throw('Could not get code signature for running application');
|
||||
});
|
||||
|
||||
it('does throw if an unknown string is the serverType', () => {
|
||||
expect(() => autoUpdater.setFeedURL({ url: '', serverType: 'weow' as any })).to.throw('Expected serverType to be \'default\' or \'json\'');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('quitAndInstall', () => {
|
||||
|
||||
@@ -12,7 +12,7 @@ import { AddressInfo } from 'node:net';
|
||||
import * as os from 'node:os';
|
||||
import * as path from 'node:path';
|
||||
|
||||
import { copyMacOSFixtureApp, getCodesignIdentity, shouldRunCodesignTests, signApp, spawn } from './lib/codesign-helpers';
|
||||
import { copyMacOSFixtureApp, getCodesignIdentity, shouldRunCodesignTests, signApp, spawn, unsignApp } from './lib/codesign-helpers';
|
||||
import { withTempDirectory } from './lib/fs-helpers';
|
||||
import { ifdescribe, ifit } from './lib/spec-helpers';
|
||||
|
||||
@@ -146,6 +146,7 @@ ifdescribe(shouldRunCodesignTests)('autoUpdater behavior', function () {
|
||||
ifit(process.arch !== 'arm64')('should fail to set the feed URL when the app is not signed', async () => {
|
||||
await withTempDirectory(async (dir) => {
|
||||
const appPath = await copyMacOSFixtureApp(dir);
|
||||
await unsignApp(appPath);
|
||||
const launchResult = await launchApp(appPath, ['http://myupdate']);
|
||||
console.log(launchResult);
|
||||
expect(launchResult.code).to.equal(1);
|
||||
@@ -153,6 +154,35 @@ ifdescribe(shouldRunCodesignTests)('autoUpdater behavior', function () {
|
||||
});
|
||||
});
|
||||
|
||||
ifit(process.arch !== 'arm64')('should fail with code signature error when serverType is default and app is unsigned', async () => {
|
||||
await withTempDirectory(async (dir) => {
|
||||
const appPath = await copyMacOSFixtureApp(dir);
|
||||
await unsignApp(appPath);
|
||||
const launchResult = await launchApp(appPath, ['', 'default']);
|
||||
expect(launchResult.code).to.equal(1);
|
||||
expect(launchResult.out).to.include('Could not get code signature for running application');
|
||||
});
|
||||
});
|
||||
|
||||
ifit(process.arch !== 'arm64')('should fail with code signature error when serverType is json and app is unsigned', async () => {
|
||||
await withTempDirectory(async (dir) => {
|
||||
const appPath = await copyMacOSFixtureApp(dir);
|
||||
await unsignApp(appPath);
|
||||
const launchResult = await launchApp(appPath, ['', 'json']);
|
||||
expect(launchResult.code).to.equal(1);
|
||||
expect(launchResult.out).to.include('Could not get code signature for running application');
|
||||
});
|
||||
});
|
||||
|
||||
ifit(process.arch !== 'arm64')('should fail with serverType error when an invalid serverType is provided', async () => {
|
||||
await withTempDirectory(async (dir) => {
|
||||
const appPath = await copyMacOSFixtureApp(dir);
|
||||
const launchResult = await launchApp(appPath, ['', 'weow']);
|
||||
expect(launchResult.code).to.equal(1);
|
||||
expect(launchResult.out).to.include("Expected serverType to be 'default' or 'json'");
|
||||
});
|
||||
});
|
||||
|
||||
it('should cleanly set the feed URL when the app is signed', async () => {
|
||||
await withTempDirectory(async (dir) => {
|
||||
const appPath = await copyMacOSFixtureApp(dir);
|
||||
|
||||
11
spec/fixtures/auto-update/initial/index.js
vendored
11
spec/fixtures/auto-update/initial/index.js
vendored
@@ -6,13 +6,18 @@ process.on('uncaughtException', (err) => {
|
||||
const { autoUpdater } = require('electron');
|
||||
|
||||
const feedUrl = process.argv[1];
|
||||
const serverType = process.argv[2];
|
||||
|
||||
console.log('Setting Feed URL');
|
||||
|
||||
autoUpdater.setFeedURL({
|
||||
url: feedUrl
|
||||
});
|
||||
const opts = { url: feedUrl };
|
||||
if (serverType) {
|
||||
opts.serverType = serverType;
|
||||
}
|
||||
|
||||
autoUpdater.setFeedURL(opts);
|
||||
|
||||
console.log('Feed URL Set:', feedUrl);
|
||||
console.log('Server Type Set:', serverType);
|
||||
|
||||
process.exit(0);
|
||||
|
||||
@@ -7,11 +7,8 @@ import * as path from 'node:path';
|
||||
const features = process._linkedBinding('electron_common_features');
|
||||
const fixturesPath = path.resolve(__dirname, '..', 'fixtures');
|
||||
|
||||
// Re-enable codesign tests for macOS x64
|
||||
// Refs https://github.com/electron/electron/issues/48182
|
||||
export const shouldRunCodesignTests =
|
||||
process.platform === 'darwin' &&
|
||||
!(process.env.CI) &&
|
||||
!process.mas &&
|
||||
!features.isComponentBuild();
|
||||
|
||||
@@ -83,3 +80,7 @@ export function spawn (cmd: string, args: string[], opts: any = {}) {
|
||||
export function signApp (appPath: string, identity: string) {
|
||||
return spawn('codesign', ['-s', identity, '--deep', '--force', appPath]);
|
||||
};
|
||||
|
||||
export function unsignApp (appPath: string) {
|
||||
return spawn('codesign', ['--remove-signature', '--deep', appPath]);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user