技術(tech)

Electron: production環境でのビルド時にのみコード署名したい

はじめに

  • Electronアプリケーションの配布において、環境ごとに署名の要否を切り替える方法を紹介します
  • 技術スタック:Electron, TypeScript, Node.js

この記事は、以下の記事を続きとなっています。

【Macユーザ】IE非対応でもグローバルサインのサイニング証明書をダウンロードしたいはじめに この記事の主な目的: Macユーザーが誤った証明書ダウンロード方法を選択した場合の対処法を解説 重要な警告: Macユーザー...
【Macユーザ】仮想Windows環境でアプリのコードサイニング署名を実行はじめに この記事の目的: Mac上に仮想Windows環境を構築し、USBトークンを使ったコード署名を実行する方法を解説 前提条件:...
仮想Windows環境でのElectronアプリ署名:環境構築からビルドまで仮想Windows環境でのElectronアプリ署名:環境構築からビルドまで はじめに 記事のポイント: Macユーザーが仮想Wind...

対象とする読者

  • Electronアプリケーションの開発経験がある方
  • アプリケーションの署名処理について興味がある方
  • CI/CD環境で条件付き署名を設定したい方

背景

  • Electronアプリケーションは配布前に署名するのが吉
  • しかし開発環境では毎回署名を行うと時間がかかる
  • 本番ビルド時のみ署名を行い、開発ビルドでは署名をスキップしたい
  • USBトークンが必須となったために、ビルドと署名を同時に実施できる端末は限られてしまった
  • 特にCI/CD環境ではUSBトークンを接続できないため署名プロセスが実行できない
  • 開発環境やテスト用に扱う上では署名は必ずしも必要ないと判断し、prodかそれ以外の場合で処理を分けることにした

解決する課題

  • 環境によって署名プロセスを条件分岐させる
  • 本番環境では確実に署名を行う
  • 開発環境では署名プロセスをスキップして時間を節約する
  • ビルドプロセスをシンプルに保ちつつ条件分岐を実現する
  • CI/CD環境でも署名なしのビルドを実行可能にする

実装方法

  • package.jsonのスクリプト設定で環境別のビルドコマンドを用意
  • electron-builderのコマンドライン引数で署名設定を切り替え
  • 署名処理用のTypeScriptファイルを用意

実装詳細

1. package.jsonでの環境別ビルドスクリプト設定

{
  "scripts": {
    "build:win:prod": "yarn build && electron-builder -w --publish=never --config.win.sign=./sign-with-token.ts",
    "build:win": "yarn build && electron-builder -w --publish=never"
  }
}
  • build:win:prod:本番環境用のビルドコマンド。--config.win.signオプションで署名スクリプトを指定
  • build:win:開発環境用のビルドコマンド。署名オプションを省略

2. 署名スクリプトの実装

実際に使用しているsign-with-token.tsファイルの例です。これはsigntoolコマンドを使用してWindowsアプリケーションに署名するスクリプトです:

// sign-with-token.ts
exports.default = async function(configuration) {
    const { path } = configuration;
    const { execSync } = require('child_process');

    console.log(`署名中: ${path}`);

    try {
      execSync(`signtool sign /tr http://timestamp.globalsign.com/tsa/r6advanced1 /fd sha256 /td sha256 /n "Example Company" "${path}"`, 
        { stdio: 'inherit' });
      return true;
    } catch (error) {
      console.error('署名エラー:', error);
      throw error;
    }
  };

このスクリプトの役割と動作は以下の通りです:

  • configurationオブジェクトから署名対象ファイルのパスを取得
  • Node.jsのchild_processモジュールを使ってsigntoolコマンドを実行
  • タイムスタンプサーバーを指定して署名の有効期限切れを防止
  • SHA256のハッシュアルゴリズムを使用
  • 証明書の発行者名(上記では一般名に置き換え)を指定
  • 署名が成功すればtrueを返し、失敗した場合はエラーをスロー

Windowsの場合、署名にはsigntool.exeが使用されますが、この方法は開発マシンにUSBトークンなどの物理的な証明書が必要になります。

実装結果

  • 開発ビルド時は署名をスキップして高速にビルドできる
  • 本番ビルド時は自動的に署名プロセスが実行される
  • 開発チームはコマンドを使い分けるだけで適切な環境を選択できる
  • CIパイプラインではbuild:win:prodを実行するよう設定するだけでOK
  • ステージング環境(stg)のビルドをCI/CDから実行できるようになった
  • USBトークンが必要な署名処理を本番環境のみに限定できた

おわりに

  • Electronアプリケーションの署名は重要だが、開発効率とのバランスも考慮すべき
  • package.jsonのスクリプト設定を工夫することで、柔軟な環境分岐が実現できる
  • 今回紹介した方法は署名以外の環境別設定にも応用可能
  • USBトークンのような物理的制約がある場合でも、環境別設定によって効率的な開発フローを維持できる

参考文献