3/1

2026

fastlane matchに学ぶ、開発環境のAPIトークン管理術

#セキュリティ#DevOps#macOS#Keychain#CI/CDfastlane matchに学ぶ、開発環境のAPIトークン管理術

個人開発をしていると、APIトークンの管理に悩むことがある。Netlify、Firebase、App Store Connect...サービスが増えるたびにトークンも増え、「このトークンどこに保存したっけ?」となりがちだ。

今回、iOS開発で使っている fastlane match の設計思想を参考に、APIトークン管理全般に使える仕組みを作ったので紹介する。

課題: 開発環境のAPIトークン管理の悩み

開発者なら一度は経験したことがあるはず:

  • dotfilesにトークンを直書き → うっかりpublicリポにpushして漏洩
  • macOS Keychainに保存 → マシン移行やKeychain再作成で全部消える
  • .envファイルに書く → プロジェクトごとに散らばって管理しきれない
  • ~/.zshrcにexport文 → 平文トークンがシェル設定ファイルに露出

特に困るのが「Keychainが消えたとき」。macOSのKeychainはマシン移行やクリーンインストール時にリセットされることがある。そうなると、各サービスのダッシュボードを回ってトークンを再発行する羽目になる。

発想: fastlane matchから学んだ「暗号化repoパターン」

iOS開発者にはおなじみの fastlane match。これはiOSアプリのコード署名証明書とプロビジョニングプロファイルを管理するツールだ。

matchの設計思想がシンプルで美しい:

  1. 証明書・プロファイルを MATCH_PASSWORD で暗号化
  2. 暗号化ファイルを GitHub private repo に保管
  3. 新しいマシンでは fastlane match を実行するだけで全て復元

「暗号化したファイルをGitリポに入れる」という発想。Gitの履歴管理、アクセス制御、バックアップが自動的に効く。

この設計思想を「APIトークン管理」全般に応用したのが今回の仕組みだ。しかもfastlane matchと同じMATCH_PASSWORDを使い回すので、覚えるパスワードは1つだけ。

アーキテクチャ: 3層構造

全体像はこうなっている:

certificates repo (private)     ← 暗号化されたトークンを保管
    ↕ MATCH_PASSWORD(openssl enc で暗号化/復号)
プロジェクト repo               ← setup_secrets.sh(復号+登録スクリプト)
    ↕ security コマンド
macOS Keychain                  ← ランタイムのトークン格納先
    ↕ security find-generic-password
~/.zshrc                        ← 環境変数として動的取得

ポイント:

  • certificates repo: fastlane matchが既に使っているprivateリポ。ここにsecretsディレクトリを追加してトークンも保管
  • プロジェクト repo: 復元スクリプトのみ。トークンの平文は一切含まない
  • Keychain: macOSの標準的なシークレットストレージ。アプリからもCLIからもアクセス可能
  • ~/.zshrc: Keychainから動的に値を取得する。平文は書かない

実装手順

Step 1: トークンを暗号化してcertificates repoに保管

まず、管理したいトークンをopenssl で暗号化する:

# 暗号化
echo "YOUR_TOKEN_VALUE" | openssl enc -aes-256-cbc -pbkdf2 -salt \
  -pass pass:"YOUR_MATCH_PASSWORD" -out token_name.enc

# 復号(確認用)
openssl enc -aes-256-cbc -pbkdf2 -d \
  -in token_name.enc -pass pass:"YOUR_MATCH_PASSWORD"

暗号化ファイル(.enc)をcertificates repoの secrets/ ディレクトリに配置する:

certificates/
├── certs/          ← fastlane match管理の証明書
├── profiles/       ← fastlane match管理のプロファイル
└── secrets/        ← APIトークン(暗号化済み)
    ├── README.md
    └── netlify_token.enc

Step 2: 復元スクリプトを作る

プロジェクトリポのルートに setup_secrets.sh を置く:

#!/bin/bash
set -euo pipefail

CERT_REPO="git@github.com:yourname/certificates.git"
TMPDIR=$(mktemp -d)
trap "rm -rf $TMPDIR" EXIT

echo "=== Secrets Setup ==="
read -rsp "MATCH_PASSWORD: " MATCH_PASSWORD
echo ""

# certificates repoをclone(shallow)
git clone --depth 1 "$CERT_REPO" "$TMPDIR/certs" 2>/dev/null

# 各トークンを復号→Keychain登録
TOKEN=$(openssl enc -aes-256-cbc -pbkdf2 -d \
  -in "$TMPDIR/certs/secrets/token_name.enc" \
  -pass pass:"$MATCH_PASSWORD") || {
  echo "復号失敗。パスワードを確認してください。"
  exit 1
}
security add-generic-password -a service_name -s TOKEN_NAME -w "$TOKEN" -U
echo "TOKEN_NAME をKeychainに登録しました"

# zshrc用のexport文を案内
echo ""
echo "以下を ~/.zshrc に追加してください:"
echo 'export TOKEN_NAME=$(security find-generic-password -a service_name -s TOKEN_NAME -w 2>/dev/null)'

このスクリプトの流れ:

  1. MATCH_PASSWORDを対話的に入力
  2. certificates repoをtmpディレクトリにshallow clone
  3. 暗号化ファイルを復号
  4. security add-generic-password でKeychainに登録
  5. tmpディレクトリを自動削除(trap EXIT

Step 3: ~/.zshrcでKeychainから動的取得

~/.zshrcには平文トークンを書かない。代わりにKeychainから動的に取得する:

# NG: 平文を直書き
export TOKEN_NAME="actual_token_value_here"

# OK: Keychainから動的取得
export TOKEN_NAME=$(security find-generic-password -a service_name -s TOKEN_NAME -w 2>/dev/null)

2>/dev/null を付けているのは、Keychainにまだ登録されていない場合のエラーメッセージを抑制するため。

CI/CD連携

ローカル開発ではKeychainを使うが、CI/CD環境(GitHub Actions等)ではKeychainが使えない。ここではGitHub Secretsを活用する:

# .github/workflows/deploy.yml
env:
  MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
  NETLIFY_TOKEN: ${{ secrets.NETLIFY_PERSONAL_ACCESS_TOKEN }}

設計上のポイント:

  • MATCH_PASSWORD をGitHub Secretsに登録しておく
  • CI環境ではcertificates repoからの復号は不要(GitHub Secretsから直接取得)
  • ローカルとCIで同じMATCH_PASSWORDを共有することで、一貫性を保つ

既存ツールとの比較

この方式が万能というわけではない。チームの規模や環境に応じて最適なツールは異なる:

ツール特徴向いているケース
この方式依存ゼロ、macOS標準ツールのみ個人開発、macOS限定
1Password CLIGUI連携、チーム管理、マルチOSチーム開発、マルチOS環境
dopplerSaaS、環境変数統合、ダッシュボード大規模、クラウドネイティブ
SOPSクラウドKMS連携、YAML/JSON暗号化AWS/GCP環境
git-cryptリポ全体の透過的暗号化リポ内秘密ファイルが多い

正直、チーム開発なら1Password CLIやdopplerの方が管理しやすい。この方式が活きるのは「個人開発 + macOS + fastlaneを既に使っている」というケース。依存が本当にゼロ(macOS標準のopenssl + security コマンドだけ)なのが最大の利点。

まとめ

メリット:

  • 依存ゼロ: macOS標準ツール(openssl, security)だけで完結
  • fastlane matchとパスワード共有: 覚えるパスワードは1つ
  • Gitで履歴管理: いつ、何のトークンが変更されたか追跡可能
  • シンプル: シェルスクリプト1つで全トークンを復元

デメリット:

  • macOS限定: Linux/Windowsでは別の仕組みが必要
  • GUI管理なし: 全てCLI操作
  • パスワード漏洩リスク: MATCH_PASSWORDが漏れると全トークンが露出
  • スケール限界: トークン数が数十を超えると管理が煩雑に

向いているケース:

  • 個人開発者で、macOSメイン
  • fastlane matchを既に使っている(MATCH_PASSWORDが存在する)
  • 外部サービスへの依存を最小限にしたい
  • 「新しいMacを買ったらスクリプト1つ叩くだけ」を実現したい

iOS開発者ならfastlane matchの恩恵を既に受けているはず。その設計思想をAPIトークン管理にも広げるだけで、「新しいマシンのセットアップが楽になる」という地味だけど確実なメリットが得られる。