LoginSignup
4
5

[macOS] Electron アプリの公証に成功する方法 2023

Last updated at Posted at 2023-08-26

この記事は、以下の記事のアップデート版 (2023) です。

まずは前提から

macOS 10.14.5 Mojave 以降では、App Store 経由ではないアプリ(いわゆる野良アプリ)であっても、コード署名に加え、Apple 社による「公証 (notary)」を受けていない場合には、以下(↓)のような警告が表示され、原則としてそのままでは実行できません。

📸 コード署名がされていない場合:

📸 公証を受けていない場合:

この制限は Electron 製アプリにとっても変わりありません。これをクリアするために必要な条件が以下の 2 つです。

  1. 有効な「Developer ID Application 証明書」でコード署名する
  2. コード署名と公証に electron-builder を利用する

本稿では electron-builder を利用しますが、他のツールを利用する場合であっても同様の処理を行う必要があります。

以下の記述は、すでに Xcode がインストール済みであることを前提としています。

有効な Developer ID でコード署名する

アプリへコード署名を施すには、有効な「Developer ID Application 証明書」がその Mac へインストールされている必要があります。そして、electron-builder は自動的に「キーチェーンアクセス.app」内のその証明書を利用します。

📸 キーチェーンアクセスに取り込んだ Developer ID 証明書:

そのためには Apple Devloper Program で購入した Apple Developer アカウントが必要で、その ID の証明書をキーチェーンアクセスへ登録しておかなければなりません。

その手順は:

  1. Apple Devloper Program で開発者アカウントを購入する(年間 99 ドル)
  2. そのアカウントの "Certificates, Identifiers & Profiles" ページ → "Certificates" タブで Developer ID Application 証明書を作成
  3. その証明書をダウンロードし、ダブルクリックでキーチェーンアクセスへインストール

という流れになります。

📸 開発者アカウントのページ:

📸 新しい証明書を作成:

📸 Developer ID Application を選択:

📸 作成した証明書のページから Developer ID Application 証明書をダウンロード:

📸 証明書のダブルクリックでキーチェーンアクセスへインストール:

electron-builder でコード署名し、公証を受ける

  • electron-builder のインストール
zsh
npm install --save-dev electron-builder

有効な Developer ID Application 証明書がインストールされている場合、electron-builder (厳密には、これに含まれる @electron/osx-sign パッケージ)は自動でその証明書を使ってアプリにコード署名を行います。

逆に言えば、あえてコード署名したくない場合には、パッケージスクリプト内の mac.identity エントリへ null を明示的に指定する必要があります。

  • パッケージスクリプトの例
builder.js
require("dotenv").config();  // 環境変数の展開(後述)

// パッケージスクリプト本体
require("electron-builder").build({
  config: {
    productName: "Sample",
    artifactName: "${productName}-${version}-${platform}-${arch}.${ext}",
    copyright: "© 2023 sprout2000",
    files: ["dist/**/*"], // 対象アプリの置き場所
    directories: {
      output: "release", // パッケージの出力先
    },
    mac: {
      appId: "jp.sprout2000.Sample",  // アプリID
      category: "public.app-category.developer-tools", // カテゴリ
      target: ["default"], // dmg と zip
      icon: "assets/icon.icns", // アイコンには icns ファイルが必要
      /**
      * 公証の設定(後述)
      */
      notarize: {
        teamId: "369RBS5M6E",
      },
      // identity: null,  // コード署名しない場合はアンコメント
    },
  },
});

パッケージスクリプトの詳細については electron-builder のドキュメントを参照してください。
また、mac.category エントリの値については Apple のドキュメントを参照してください。

アプリへ公証を受ける

アプリはコード署名がなされたあと、dmg と zip へパッケージされる前に公証を受けなければいけません。この間の一連の処理は、electron-builder の mac.notarize エントリ以下の設定が自動で行ってくれます。

    mac: {
      // ...
      notarize: {
        teamId: "369RBS5M6E",
      },
    },
  • teamId の値には Apple ID に割り振られた Team ID が入ります。Team ID は大文字と数字からなる 10 桁の文字列です。

dotenv を導入する

アプリへの公証を受けるためには、electron-builder へ秘匿情報を環境変数として渡す必要があります。しかし、これらはビルドスクリプトへベタ書きできないようになっています。GitHub などへコードをアップロードするとこれらの情報が他者にも晒されてしまうからです。

環境変数を記述した .env ファイルをスクリプト内で展開してくれるツール、dotenv を導入しましょう。

sh
npm install --save-dev dotenv

.env ファイルを作成する

electron-builder へ渡す環境変数は以下の 2 つです。これらの値を .env ファイルへ記述しておきます。

  1. APPLE_ID
  2. APPLE_APP_SPECIFIC_PASSWORD
  • APPLE_ID の値は、その名の通り、Developer program に登録したアカウント名(=メールアドレス)です。
  • APPLE_APP_SPECIFIC_PASSWORD(=アプリ固有のパスワード)は、Apple ID そのものの代わりに、そのアプリに固有のパスワードを与えたものです。これは、Apple Developer ID では 2 要素認証が必須とされているため、スクリプトで認証を受けることができないことに由来します。アプリ固有のパスワードは、appleid.apple.com で作成します(以下の画像を参照)。

📸 アプリ固有のパスワード作成画面:

  • .env ファイルの例
.env
APPLE_ID="sprout2000@example.jp"
APPLE_APP_SPECIFIC_PASSWORD="hhcd-aemv-kkor-hzes"

.env ファイルは必ず .gitignore 内にそのパスを指定してください。
git に管理(= GitHub などへアップロード)させてしまうと秘匿情報が漏えいしてしまいます。

  • ビルドスクリプトの例 (2)
builder.js
  // dotenv で ".env" ファイル内の環境変数を展開
+ require("dotenv").config();
  require("electron-builder").build({ /** */ });

コード署名&公証の実行

パッケージスクリプトを実行し、コード署名と公証のプロセスを開始します。Apple の notary サーバーの状況にもよりますが、全ての処理が完了するまでに 5~10 分の時間を要します。

sh
node ./builder.js
% node ./builder.js
  • electron-builder  version=24.4.0 os=22.4.0
  • writing effective config  file=release/builder-effective-config.yaml
  • executing @electron/rebuild  arch=arm64 version=24.2.0 appDir=/Users/taro/sample
  • packaging       platform=darwin arch=arm64 electron=24.2.0 appOutDir=release/mac-arm64
  • signing         file=release/mac-arm64/Sample.app identityName=Developer ID Application: Taro Nippon
  • building        target=macOS zip arch=arm64 file=release/Sample-0.1.0-darwin-arm64.zip
  • building        target=DMG arch=arm64 file=release/Sample-0.1.0-darwin-arm64.dmg
  • building block map  blockMapFile=release/Sample-0.1.0-darwin-arm64.dmg.blockmap
  • building block map  blockMapFile=release/Sample-0.1.0-darwin-arm64.zip.blockmap

なお、コード署名&公証に成功しているか否かは、spctl コマンドを用いて確認できます。

% spctl -a -vvv -t install release/mac-arm64/Sample.app

release/mac-arm64/Sample.app: accepted
source=Notarized Developer ID
origin=Developer ID Application: Taro Nippon (369RBS5M6E)

また、いったんクラウドストレージへアップロードした dmg または zip をダウンロードし、自分で開いてみる方法も有効です。その場合は、「インターネットからダウンロードされたアプリケーション」である旨の警告のみが表示されます。

おまけ:署名も公証もされていないアプリを開くには?

以下の手順でアプリを開いた結果は自己責任でお願いします。

xattr コマンドを利用してアプリを Apple Gate Keeper の対象外とします。

zsh
% xattr -rc /hoge/foo/Sample.app
4
5
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
4
5