GitLab公式は、macOSで使うShell executorについてジョブの分離が限定的で、同じホスト上の他プロジェクトのコードへアクセスできる可能性を明記しています。Shell executorの安全境界を前提にすると、GitLab CI 複数プロジェクト共有 Mac Runnerは、信頼済みの通常ビルドだけを共有し、正式署名と非信頼コードを専用Macへ分ける設計が適切です。
今週の推奨アクションは、共有ビルド池と専用リリース池の2層を先に定義し、単一プロジェクトでルーティングと清掃を検証することです。タグ、Protected Runner、ディレクトリ分割はジョブを正しく届ける仕組みであり、ホスト全体を安全なサンドボックスへ変える機能ではありません。
この導入手順を読むべき担当者
複数リポジトリへmacOSビルド資源を提供するプラットフォームエンジニア向けです。証明書、秘密鍵、社内依存サービスへのアクセスを管理するセキュリティ・リリース責任者にも役立ちます。
共有、専用、弾力的なリモートMacのどれを採用するか検討しているIT責任者や調達担当者は、各段階の合格条件を確認してください。
まず共有池と専用池を分ける
最初から1台のMacにすべてのジョブを載せると、通常ビルド、外部からのマージリクエスト、正式署名が同じOSユーザーやKeychainに接近します。まず次の3分類でプロジェクトを判定します。
| 判定 | 入れてよい処理 | 推奨する実行先 |
|---|---|---|
| 共有可能 | 信頼済みリポジトリの通常ビルド、単体テスト、再生成可能な成果物作成 | 管理されたGroup Runner |
| 独立アカウントが必要 | 部署や委託先が異なるプロジェクト、社内依存へのアクセスが異なる処理 | 専用Runnerアカウントを持つMac |
| 専用Macが必要 | 正式署名、配布資格情報、非信頼コード、異なる信頼領域のジョブ | Protected設定の専用Mac |
GitLab Runnerの範囲にはProject、Group、Instanceの考え方があります。公式の範囲管理を確認し、企業の共有池は対象プロジェクトを明示できるGroup Runnerから始めるのが安全です。Instance全体へ広く開放するのは、許可リストと監査方法を説明できる場合に限ってください。
注意:Runnerのタグが正しく一致しても、タグはジョブの宛先を示すだけです。別プロジェクトのファイル、環境変数、バックグラウンドプロセスを読めないことまで保証しません。
初日の設定は範囲、タグ、拒否テストから始める
最初の到達点は、ジョブが「動いた」ことではありません。普通のビルドが共有池へ進み、署名ジョブや許可外プロジェクトが拒否されることを、ログで確認できる状態です。
| 設定項目 | 共有ビルド池 | 専用リリース池 |
|---|---|---|
| Runnerの範囲 | 管理対象Group | 署名対象Project、または限定Group |
| タグ | macos-buildなど用途を限定 |
macos-releaseなど署名専用 |
| Protected設定 | 保護ブランチ・タグの要件を整理 | 必須にする |
| 利用プロジェクト | 許可リストで管理 | リリース担当の対象だけ |
| 主な検証 | 通常ビルドとテスト | 署名、成果物送信、資格情報拒否 |
macOS上の設定は、まずGitLab公式のmacOS Runner手順に沿って実行します。続いてタグとProtected Runnerの設定を適用し、許可したジョブと拒否されたジョブの両方を保存してください。
YAMLは説明用の最小構成にとどめます。
build_macos:
tags:
- macos-build
script:
- whoami
- pwd
- xcodebuild -version
- ./ci/build.sh
ここで確認するのは、管理者のターミナルで成功することではありません。実際のGitLab Runnerサービスアカウントで、whoami、作業場所、Xcodeの呼び出し、成果物生成が同じように成立することです。GitLab CI YAMLの仕様に沿って、署名処理はこの共有ジョブへ混ぜないでください。
最初のパイプラインでアカウントと作業領域を固定する
1. Runnerサービスアカウントを確認する
RunnerがどのmacOSローカルアカウントで実行されているかを記録します。管理者アカウントで作った設定ファイルやKeychainを、そのままCIから読めると判断してはいけません。
確認対象は次のとおりです。
- ホームディレクトリと所有者
- 作業ディレクトリ
- 一時ファイルの保存先
- 依存キャッシュの保存先
- ユーザー単位のXcode設定
- シミュレーターやDerivedDataの保存場所
2. 再生成データと長期資格情報を分離する
ソースコード、ビルド成果物、キャッシュ、証明書秘密鍵を同じ領域へ置かないでください。キャッシュは再生成できる依存物に限定し、秘密鍵や配布用プロファイルを通常のキャッシュ対象から外します。GitLabのキャッシュ仕様でも、キャッシュはジョブ間で再利用されるデータとして扱われます。
キャッシュのキーをプロジェクトや保護状態と結び付けても、同じOSユーザーが別の場所を読める問題は解消しません。ディレクトリ分割は誤操作を減らす対策であり、主ホストのセキュリティ境界ではありません。
3. ジョブ終了後の清掃を検証する
ジョブが終わった後に、ソース、環境変数から生成されたファイル、ログ、DerivedData、バックグラウンドプロセスが残っていないか調べます。清掃処理の記録には、実行前の状態、ジョブ終了時の状態、次のジョブ開始時の状態を含めてください。
経験則:先行プロジェクトが成功した直後に共有範囲を全社へ広げないでください。次のプロジェクトを意図的に接続し、前のジョブの残留物が見えないことを確認してから対象を増やします。
2つ目のプロジェクト接続で交差汚染を試す
2つ目のプロジェクトは、単なる動作確認ではなく、共有設計の限界を探すために使います。タグが正しいにもかかわらず、前のプロジェクトの残留ファイルや環境設定が読めるなら、共有を停止します。
| 検査対象 | 実施する確認 | 不合格時の判断 |
|---|---|---|
| ソースと作業領域 | 前のプロジェクト名や生成物が残っていないか | 清掃手順を修正し、再検証 |
| 環境変数 | 前のジョブ由来の資格情報やパスが残っていないか | 変数の注入方法を変更 |
| バックグラウンド処理 | ジョブ終了後のプロセスが残っていないか | 専用アカウントまたは専用Mac |
| キャッシュ | 他プロジェクトの依存物や成果物を読めないか | キャッシュ設計を分離 |
| DerivedData・シミュレーター | 同じ領域を並列ジョブが共有していないか | パスと同時実行を見直す |
同じ事業部で、コードの信頼度と社内アクセス範囲が近い場合は、管理された共有池を継続できます。部署、委託先、ネットワーク権限、秘密情報の扱いが異なる場合は、RunnerアカウントだけでなくMacノードも分ける方向へ進めます。
本番署名では共有Macから専用Macへ切り替える
iOSの正式署名では、証明書秘密鍵、Provisioning Profile、配布用資格情報、通常の依存サービス用トークンを同じ扱いにしないでください。macOSのKeychainにはアクセス制御がありますが、同じRunnerユーザーで任意スクリプトを実行できる構成なら、Keychain設定だけでShell executorのリスクを消せません。
AppleのKeychain Services資料とアクセス制御リストの説明を確認し、次の境界を決めます。
- 秘密鍵を登録するmacOSローカルアカウント。
- Keychain項目へアクセスできる署名プロセス。
macos-releaseタグを利用できる保護ブランチまたは保護タグ。- 資格情報の登録、使用、失効、再登録の担当者。
- ノード再起動後にアクセス権を再確認する手順。
署名ノードは、Protectedジョブだけを受け付ける専用Runnerにします。未承認プロジェクトから同じタグを指定しても実行されないことを確認し、最小の署名テスト、成果物送信、資格情報のローテーション、再起動後の再認証を記録します。Keychain項目のアクセス制限も、運用手順と一緒に確認してください。
1週目はオンライン表示ではなく閉ループで判定する
共有Mac Runnerが管理画面でオンラインになっているだけでは、導入完了とはいえません。コード取得、Xcodeビルド、成果物保存、正式署名、成果物送信、失敗後の復旧までを一つの流れとして確認します。
条件分岐で構成を決める
- 信頼済みプロジェクトだけで、キャッシュと作業領域の残留がなく、署名を扱わないなら、共有Mac Runnerを継続します。
- プロジェクトごとの権限や社内依存先が異なるなら、まず専用Runnerアカウントへ分けます。それでも同じホスト上の読み取り境界を説明できない場合は、専用Macへ移します。
- 非信頼のマージリクエストが同じMacへ到達するなら、共有池から外します。
- 正式署名、配布資格情報、秘密鍵を扱うなら、Protected設定の専用Macを選びます。
- 通常ビルドは共有できるが、リリース時だけ待ち行列が発生するなら、基準容量を共有池に置き、ピーク時だけVMSPINのリモートMacを試す構成を検証します。
- 物理機器への直接接続や長期の安定した高負荷が必須なら、レンタルだけで置き換えず、購入構成や専用設備と比較します。
Macを追加して検証する場合は、VMSPINの日本語注文案内で必要な利用期間と接続方式を確認し、いきなり全プロジェクトを移行せず、共有ビルド池と専用リリース池を別々に試してください。費用比較では、月額だけでなく、保守、交換、遊休時間、証明書管理、障害時の切り替え作業も含めてください。料金条件を確認する場合は、VMSPINの料金案内と社内の購入見積もりを同じ期間で比較します。
既存の単一Macへ通常ビルド、非信頼ブランチ、正式署名を同居させる方法は、タグを増やすだけでは説明可能な分離になりません。共有池は信頼済みコードの反復ビルドに限定し、署名や異なる信頼領域には専用Macを割り当てるほうが、監査記録と事故時の原因追跡を保ちやすくなります。
よくある確認事項
GitLab Runnerは複数のプロジェクトで同時に利用できますか?
利用できます。企業で複数プロジェクトをまとめる場合は、対象範囲を管理できるGroup Runnerを共有ビルド用に設定し、タグでジョブを振り分けます。ただし、共有できるのはコードと権限の信頼境界が近いプロジェクトです。非信頼のマージリクエストや正式署名処理まで同じMacに集約する設計は避けてください。
macOSのShell executorでプロジェクト間を分離するにはどうしますか?
Runnerのサービスアカウント、作業ディレクトリ、キャッシュ、DerivedData、制作用ファイルを確認し、ジョブ終了後に残留物を削除します。ただしディレクトリを分けても、同じShellユーザーで動くジョブがホスト上の別資産へ到達できる可能性は残ります。Shell executorは信頼済みコード向けとして扱い、完全なサンドボックスとは考えないでください。
Group RunnerとProject Runnerはどちらを選ぶべきですか?
複数の管理対象プロジェクトで通常ビルドを共有するなら、許可対象を管理しやすいGroup Runnerが基本です。特定リポジトリだけが使う署名ノードや、異なる信頼領域の専用MacにはProject Runnerが向いています。Instance Runnerを広く開放する前に、対象プロジェクト、タグ、Protected設定を一覧化してください。
共有Mac RunnerでKeychainやキャッシュの漏えいを防ぐにはどうしますか?
キャッシュは再生成できる依存物に限定し、証明書秘密鍵、Provisioning Profile、配布用資格情報は通常のキャッシュから分離します。Keychainのアクセス制御を設定しても、同一Runnerユーザーで任意スクリプトを実行できるリスクは消えません。正式署名はProtectedジョブだけを受ける専用Macへ移してください。
iOSの正式署名に専用GitLab Runnerは必要ですか?
必ずしも全社で必要とは限りませんが、正式証明書の秘密鍵、配布用プロファイル、リリース権限を扱うなら専用Runnerが妥当です。通常ビルド用の共有Macと同じユーザー、作業領域、プロセスを使うと、タグ設定だけでは境界を説明できません。監査要件や複数部署の信頼関係も含めて判断してください。
単一のMacで共有ビルド、非信頼コード、正式署名を同時に処理しているなら、現状の弱点はタグ設定だけに依存していること、同じShellユーザーの読み取り境界が広いこと、署名資格情報とキャッシュの責任範囲が近いことです。購入台数をすぐ増やすより、まず共有構築ノードと専用署名ノードを分けた小規模な試験を行うほうが、実際のジョブ履歴と監査証跡で判断できます。
短期のリリース集中や一時的なXcode検証で物理Macを増やす必要がある場合は、VMSPINのMacレンタルを試験用ノードとして組み込み、許可プロジェクト、清掃、再起動復旧、署名拒否を個別に検証してください。長期の固定負荷や物理接続が必要なチームには購入や専用設備が適するため、共有池と専用池の役割を分けたうえで、必要な期間だけレンタルを加えるのが現実的です。