|
| 1 | +--- |
| 2 | +title: アイソレーション型(Isolation Pattern) |
| 3 | +i18nReady: true |
| 4 | +--- |
| 5 | + |
| 6 | +アイソレーション(分離・隔絶)型は、フロントエンドから送信された Tauri API メッセージが Tauri コア部に到達する前に、JavaScript を使用して傍受・変更する方法です。アイソレーション型で挿入される安全な JavaScript コードは、アイソレーション型アプリケーションと呼ばれます。 |
| 7 | + |
| 8 | +## アイソレーション型の必要性 |
| 9 | + |
| 10 | +アイソレーション型の目的は、Tauri コア部への望ましくないあるいは悪意のあるフロントエンドからの呼び出しから、アプリケーションを保護するための仕組みを開発者に提供することです。アイソレーション型が必要となったのは、フロントエンドで実行される信頼できないコンテンツから生じる脅威に対応するために生まれました。このような脅威は多くの依存関係を持つアプリケーションによくあるケースです。アプリケーションが遭遇する可能性のある多くの脅威源のリストについては、[セキュリティ:脅威モデル] を参照してください。 |
| 11 | + |
| 12 | +上記の最大の脅威モデルは「開発時の脅威」でしたが、このような脅威は、アイソレーション型を設計する際に念頭に置かれていたものです。多くのフロントエンドのビルド・ツールが、しばしば深くネスト化された数十(もしくは数百)の依存関係で成り立っているだけではなく、複雑なアプリケーション側にも、数多くの(こちらもしばしば深くネスト化された)依存関係があり得るので、最終出力版にバンドルされるのです。 |
| 13 | + |
| 14 | +## アイソレーション型を使用する局面 |
| 15 | + |
| 16 | +Tauri は、アイソレーション型が使用できる場合には常に使用することを強く推奨しています。アイソレーション型のアプリケーションではフロントエンドからの _**すべての**_ メッセージを「捕捉」(インターセプト)するため、アイソレーション型が _常に_ 使用されます。 |
| 17 | + |
| 18 | +さらに Tauri では、外部の Tauri API を使用するときは常に、アプリケーションを「封鎖」(ロックダウン)することを強く推奨しています。アプリの開発者は、安全なアイソレーション型アプリケーションを利用して IPC 入力を検証し、その入力内容が確実に想定されるパラメータの範囲内にあることを確かめます。事例としては、ファイルの読み取りまたは書き込みの呼び出しが、そのアプリケーションの想定外の場所へのパスにアクセスしようとしていないかを確認したり、あるいは、Tauri API の「HTTP フェッチコール」が 「Origin ヘッダー」にそのアプリケーションが想定しているもののみを設定しているかを確認したりすることです。 |
| 19 | + |
| 20 | +とはいえ、フロントエンドからの _**すべての**_ メッセージを捕捉するため、常時動作 API、たとえば [Events] など、でも動作します。一部のイベントでは、アプリ独自の Rust コードにアクションを実行させる可能性があるので、それにも同様の検証手法で対応することができます。 |
| 21 | + |
| 22 | +## アイソレーション型の適用 |
| 23 | + |
| 24 | +アイソレーション型で重要なのは、フロントエンドと Tauri Core(タウリ・コア部)との間に安全なアプリケーションを挿入して、IPC 受信メッセージを捕捉し修正することです。これには、`<iframe>` のサンドボックス機能(隔離機能)を使用して、メインのフロントエンド・アプリケーションと並行して JavaScript を安全に実行することで実現します。Tauri は、ページの読み込み中にアイソレーション型を発動し、Tauri Core に対するすべての IPC 呼び出しを、直接ではなく、サンドボックス化(隔離化)されたアイソレーション型アプリケーション経由で行なうように強制的にルートを切り替えます。Tauri Core に渡されるメッセージの準備が整うと、メッセージはブラウザ実装の [SubtleCrypto] を使用して暗号化され、メインのフロントエンド・アプリケーションに返されます。 |
| 25 | +フロントエンドに戻されるとすぐに、メッセージは直接 Tauri Core に渡され、そこで通常どおりに復号化されて読み取られます。 |
| 26 | + |
| 27 | +誰かがアプリケーションの特定のバージョンのキーを手動で読み取り、暗号化後にそのキーを用いてメッセージの変更を行なえないことを確実にするために、アプリケーションが実行されるたびに新しいキーが生成されます。 |
| 28 | + |
| 29 | +### IPC メッセージのおおよその手順 |
| 30 | + |
| 31 | +動作の流れを判りやすくするために、アイソレーション型の IPC メッセージが Tauri Core に送信されるときに実行されるおおよその手順を、順序付きリストで以下に示します: |
| 32 | + |
| 33 | +1. Tauri の IPC ハンドラーがメッセージを受け取ります |
| 34 | +2. IPC ハンドラー → アイソレーション型アプリケーション |
| 35 | +3. `[sandbox]` アイソレーション型アプリケーションのフックが実行され、メッセージの変更を行なう可能性があります。 |
| 36 | +4. `[sandbox]` メッセージは「実行時に生成されるキー」を使用して AES-GCM で暗号化されます |
| 37 | +5. `[encrypted]` アイソレーション型アプリケーション → IPC ハンドラー |
| 38 | +6. `[encrypted]` IPC ハンドラー → Tauri Core |
| 39 | + |
| 40 | +_注記: 矢印(→)は、メッセージ・パッシング(受け渡し)を示します。_ |
| 41 | + |
| 42 | +### パフォーマンスへの影響 |
| 43 | + |
| 44 | +安全なアイソレーション型アプリケーションは、メッセージの暗号化が行なわれるため、何も行なわない場合ですら [ブラウンフィールド型] と比較して追加のオーバーヘッド・コストが発生します。(適切なパフォーマンスを維持するために、慎重に保守され依存関係も少ないであろう)パフォーマンス重視のアプリケーションを除けば、ほとんどのアプリケーションは比較的小型で AES-GCM 暗号化方式も比較的高速であるため、IPC メッセージの暗号化/復号化の実行時コストを意識する必要はありません。もし AES-GCM について馴染みがないとしても、ここで関連するのは、それが [SubtleCrypto] に含まれる唯一の認証モード・アルゴリズムであり、おそらく「[TLS][transport_layer_security] 暗号化プロトコル」の内部で既に毎日使用しているということだけです。 |
| 45 | + |
| 46 | +Tauri アプリケーションが起動されるたびに一度、暗号化された安全なキーも生成されますが、システムがすでに十分なエントロピー(ランダム性)を備えていて、即座に十分な乱数を返すのであれば、この処理には通常気付きません。これは「デスクトップ環境」では極めて一般的です。「ヘッドレス環境」で [WebDriver との統合テスト] などを実行する場合で、オペレーティング・システムにエントロピー生成サービス《訳注: 「乱数生成」機能》が含まれていない場合には、`haveged` などの何らかのエントロピー生成サービスをインストールすることをお勧めします。<sup>Linux 5.6 (March 2020) 版から、投機的実行によるエントロピー生成が含まれるようになりました。</sup> |
| 47 | + |
| 48 | +### 制限事項 |
| 49 | + |
| 50 | +アイソレーション型には、プラットフォームとの不整合から生じる制限事項がいくつかあります。最も重大な制限は、Windows 上のサンドボックス化された `<iframes>` 内に外部ファイルが正しく読み込まれないことによるものです。このため、アイソレーション型アプリケーションに関連するスクリプトの内容を取得してインラインに挿入する、ビルド時の簡単なスクリプト・インライン化手順を実装しました。つまりこれは、`<script src="index.js"></script>` のようなファイルの典型的なバンドル、あるいは単純な挿入は依然として正常に機能しますが、ES Modules(ECMAScript Modules)などの新しいメカニズムは上手く読み込ま**ない**ということを意味します。 |
| 51 | + |
| 52 | +## 推奨事項 |
| 53 | + |
| 54 | +アイソレーション型アプリケーションの目的は開発時の脅威から保護することであるため、アイソレーション型アプリケーションはできる限り簡素化しておくことを強くお勧めします。依存関係を最小限に抑えるよう努めるだけでなく、必要なビルド手順を最小限に抑えることを検討する必要もあります。これにより、フロントエンド・アプリケーションを覆っているアイソレーション型アプリケーションへのサプライ・チェーン攻撃には心配する必要がなくなります。 |
| 55 | + |
| 56 | +## アイソレーション型アプリケーションの作成 |
| 57 | + |
| 58 | +次の例では、小さな「hello-world」のようなアイソレーション型アプリケーションを作成し、それを仮に既存の Tauri アプリケーションに接続することを想定します。このアプリでは、通過するメッセージの検証は行なわれず、WebView コンソールに内容が出力されるだけです。 |
| 59 | + |
| 60 | +この事例の目的のため、`tauri.conf.json` と同じディレクトリにあると仮定します。既存の Tauri アプリケーションの `distDir` は `../dist` に設定されています。 |
| 61 | + |
| 62 | +`../dist-isolation/index.html`: |
| 63 | + |
| 64 | +```html |
| 65 | +<!doctype html> |
| 66 | +<html lang="en"> |
| 67 | + <head> |
| 68 | + <meta charset="UTF-8" /> |
| 69 | + <title>Isolation Secure Script</title> |
| 70 | + </head> |
| 71 | + <body> |
| 72 | + <script src="index.js"></script> |
| 73 | + </body> |
| 74 | +</html> |
| 75 | +``` |
| 76 | + |
| 77 | +`../dist-isolation/index.js`: |
| 78 | + |
| 79 | +```javascript |
| 80 | +window.__TAURI_ISOLATION_HOOK__ = (payload) => { |
| 81 | + // 何も検証や修正せず、ただ hook から内容を印字するだけです。 |
| 82 | + console.log('hook', payload); |
| 83 | + return payload; |
| 84 | +}; |
| 85 | +``` |
| 86 | + |
| 87 | +あとは、アイソレーション型を使用するように `tauri.conf.json` の[設定](#設定) を変更し、ブート処理経路を [ブラウンフィールド型] からアイソレーション型に切り替えるだけです。 |
| 88 | + |
| 89 | +## 設定 |
| 90 | + |
| 91 | +メインのフロントエンド `distDir` が `../dist` に設定されていると仮定します。また、アイソレーション型アプリケーションを `../dist-isolation` に出力します。 |
| 92 | + |
| 93 | +```json |
| 94 | +{ |
| 95 | + "build": { |
| 96 | + "distDir": "../dist" |
| 97 | + }, |
| 98 | + "app": { |
| 99 | + "security": { |
| 100 | + "pattern": { |
| 101 | + "use": "isolation", |
| 102 | + "options": { |
| 103 | + "dir": "../dist-isolation" |
| 104 | + } |
| 105 | + } |
| 106 | + } |
| 107 | + } |
| 108 | +} |
| 109 | +``` |
| 110 | + |
| 111 | +[transport_layer_security]: https://ja.wikipedia.org/wiki/Transport_Layer_Security |
| 112 | +[セキュリティ:脅威モデル]: /ja/security/lifecycle/ |
| 113 | +[events]: /ja/reference/javascript/api/namespaceevent/ |
| 114 | +[subtlecrypto]: https://developer.mozilla.org/ja-JP/docs/Web/API/SubtleCrypto |
| 115 | +[ブラウンフィールド型]: /ja/concept/inter-process-communication/brownfield/ |
| 116 | +[WebDriver との統合テスト]: /ja/develop/tests/webdriver/ |
| 117 | + |
| 118 | +<div style="text-align:right"> |
| 119 | +[※ この日本語版は、「Feb 22, 2025 英語版」に基づいています]<br /> |
| 120 | +Doc-JP 2.00.00 |
| 121 | +</div> |
0 commit comments