LoginSignup
0
0

More than 3 years have passed since last update.

macOS向けのElectron で "can't be opened because Apple cannot check it for malicious software." と出るようになった時の対処

Posted at

経緯

以前作ってCI上でビルド・署名・リリースを行うようにしておいたElectron製のアプリケーションで、
いつのまにか
can't be opened because Apple cannot check it for malicious software.
こういうメッセージが出るようになっていた。

「署名の期限が切れた覚えもないし(←あとで確認したら切れてたけど、これは直接の原因ではなかった)なんだろうなぁ」と思い、
理由を調べて直したので、その記録。

原因

MacOS 10.14.5以降、Appleの基準が厳しくなって、notarize(※公証の意味)という処理を通じて、
アプリに対して認める権限の範囲をより詳細に規定しなければいけなくなったらしい。

対処

※ ここから先は electron-builder を使っている場合について書きます
※ 前提として、AppleのDeveloper IDを取得して、ビルド・署名・パッケージングする部分は出来ていることとします

1. entitlements.mac.plistの追加

以下のような感じで用意する。

entitlements.mac.plist
<?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-unsigned-executable-memory</key>
    <true/>
  </dict>
</plist>

2. electron-builder の設定の追加

configの mac 配下に下記を追加

参考:
https://www.electron.build/configuration/mac

3. app-specific passwordの取得

Apple ID Account Page から app-specific passwordを生成します。
これは、自由に再生成・破棄できるAPIキーのようなものです。

秘匿情報なので、gitにコミットなどはしないように気をつけましょう。

参考:
https://support.apple.com/en-us/HT204397

4. notarizeスクリプトの用意

electron-notarizeを使うので、
まず npm install -D electron-notarize します

そして、下記のようなスクリプトでnotarize処理を書きます。

notarize.js
const { notarize } = require('electron-notarize');
const appBundleId = 'electron-builderのconfigでappIdに設定している値と同じもの'

// 下記例は環境変数から読み取っていますが、適宜読み替えてください
const appleId = process.env['APPLEID'] // apple developer IDのemailアドレス
const appleIdPassword = process.env['APPLEID_PASSWORD'] // 3で取得した、app-specific password

exports.default = async function notarizing(context) {
  const { electronPlatformName, appOutDir } = context;
  if(!appleId) throw new Error('appleId is not set in the env')
  if(!appleIdPassword) throw new Error('appleIdPassword is not set in the env')
  if (electronPlatformName !== 'darwin') {
    throw new Error(`Notarization failed. Expected platform is 'darwin' but you are on ${electronPlatformName}`)
  }

  const appName = context.packager.appInfo.productFilename;
  const appPath = `${appOutDir}/${appName}.app`

  console.log(`Notarizing ${appBundleId} found at ${appPath}`);

  return await notarize({
    appBundleId,
    appPath,
    appleId,
    appleIdPassword
  });
};

5. electron-builderのフックにnotarizeを設定

electron-builderではcodesign後に任意のスクリプトを実行できるフックが提供されているので、
4で作成したnotarizeを実行する。

"afterSign": "node /path/to/notarize.js"

対応完了

諸々対応後のelectron-builderの設定:

"build": {
  "appId": "com.なんらかの.ID",
  "productName": "アプリ名",
  "afterSign": "./scripts/notarize.js",
  "mac": {
    "hardenedRuntime": true,
    "gatekeeperAssess": false,
    "entitlements": "build/entitlements.mac.plist",
    "entitlementsInherit": "build/entitlements.mac.plist"
  }
}

この状態で、electron-builder を走らせると、パッケージングなどの処理の一環で無事にnotarize処理が行われ、
配布したアプリを開けるようになります。

ただし、アプリによっては追加の権限が必要になる場合もあるかもしれないので、その場合は、plistに必要な権限を追記してください。

ちなみに、notarize部分単体でも 5分ぐらいかかる ので、トータルのコマンド実行時間は結構長くなります。

特に参考にしたもの

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0