axiom-code-signing について
iOS/macOS開発者向けのコード署名スキルです。証明書、プロビジョニングプロファイル、権限、CI/CD署名、配布ビルドの準備を扱い、自動署名と手動署名やチーム管理も説明します。
主な機能
- 01証明書とプロファイルの管理
- 02署名権限の設定
- 03CI/CD署名のセットアップ
- 04配布ビルドの準備
活用シーン
- 01新規プロジェクトの署名設定
- 02証明書やプロファイルのエラー調査
- 03App StoreまたはAd Hoc配布の設定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ charleswiltgen/ axiom --skill axiom-code-signingインストール後、Claude Code で/axiom-code-signingを入力して読み込まれたか確認します。
詳細
コード署名
iOS/macOS アプリ向けの証明書管理、プロビジョニングプロファイル、エンタイトルメントの設定、CI/CD 署名のセットアップ、配布用ビルドの準備。
このスキルを使用する場面
次のような場合に使用します。
- ☑ 新しいプロジェクトや CI/CD パイプラインのコード署名を設定する
- ☑ コード署名エラー(証明書、プロファイル、エンタイトルメント、Keychain)をデバッグする
- ☑ App Store、TestFlight、Ad Hoc 配布向けの署名を設定する
- ☑ チーム全体で証明書とプロファイルを管理する
- ☑ チーム全体の証明書管理に fastlane match を設定する
- ☑ 自動署名と手動署名のトレードオフを理解する
- ☑ エンタイトルメントの変更が必要な新しい機能を追加する
- ☑ CI/CD の署名失敗(errSecInternalComponent、ロックされたキーチェーン)を解決する
プロンプトの例
「アプリのコード署名を設定するにはどうすればよいですか?」 「ビルドで『No signing certificate found』というエラーが発生します」 「チーム向けに fastlane match を設定するにはどうすればよいですか?」 「GitHub Actions で errSecInternalComponent が発生します」 「App Store へのアップロード時に ITMS-90035 が発生します」 「プッシュ通知のエンタイトルメントを追加するにはどうすればよいですか?」 「複数の証明書が一致し、ID が曖昧です」 「ローカルではコード署名が機能しますが、CI では失敗します」 「App Store 配布向けに署名するにはどうすればよいですか?」 「プロビジョニングプロファイルの有効期限が切れました。どうすればよいですか?」
注意すべき兆候
必要以上に問題を複雑にしている兆候です。
- ❌ Slack/メールで証明書を共有する — チャットで .p12 ファイルを共有すると、セキュリティリスクやバージョンの混乱につながります。fastlane match または Xcode の自動署名を使用してください。
- ❌ ビルドを「修正」するためにコード署名を無効にする — デバイス向けビルドや配布用ビルドではコード署名を無効にできません。エラーが再発します。
- ❌ .p12 や .mobileprovision を git にコミットする — これらはシークレットです。CI シークレット管理(GitHub Secrets、環境変数)を使用してください。
- ❌ 「念のため」すべての証明書を再生成する — 既存の証明書が失効し、チームメンバー全員と CI パイプラインに支障が出ます。
- ❌ チームや CI のビルドに個人用証明書を使用する — その人が退職したり証明書の有効期限が切れたりすると、すべてが壊れます。
- ❌ 「プロファイルに署名証明書が含まれていません」という警告を無視する — これは必ずビルド失敗につながります。今すぐ修正してください。
- ❌ エラーを抑制するために
CODE_SIGN_IDENTITY = ""を設定する — 問題をアーカイブ/エクスポート時まで先送りすることになり、デバッグが難しくなります。 - ❌ 自動署名のプロジェクトでプロファイルを手動管理する — どちらか一方の方法を選んでください。併用すると競合が発生します。
必須の最初の手順
コード署名の問題を設定またはデバッグする前に、次の手順を実行してください。
1. 使用可能な署名 ID を一覧表示する
security find-identity -v -p codesigning
インストール済みで、有効かつ署名に使用できる証明書を確認できます。
2. プロビジョニングプロファイルをデコードする
# Find profile embedded in most recent build
find ~/Library/Developer/Xcode/DerivedData -name "embedded.mobileprovision" -newer . 2>/dev/null | head -3
# Decode it
security cms -D -i path/to/embedded.mobileprovision
有効期限、埋め込まれた証明書、エンタイトルメント、デバイスリストを確認します。
3. バイナリからエンタイトルメントを抽出する
codesign -d --entitlements - /path/to/MyApp.app
これらをプロファイルのエンタイトルメントおよび .entitlements ファイルと比較します。3 つすべてが一致している必要があります。
4. プロファイル内の証明書を確認する
# Get SHA-1 from keychain
security find-identity -v -p codesigning | grep "Apple Distribution"
# Output: 1) ABCDEF123... "Apple Distribution: Company (TEAMID)"
# Get SHA-1 from profile
security cms -D -i embedded.mobileprovision | plutil -extract DeveloperCertificates xml1 -o - -
echo "<base64 data>" | base64 -d | openssl x509 -inform DER -noout -fingerprint -sha1
SHA-1 ハッシュが一致している必要があります。一致しない場合、プロファイルはキーチェーン内の証明書とは別の証明書を使って生成されています。
自動署名と手動署名
digraph signing_decision {
"New project or\nsmall team?" [shape=diamond];
"CI/CD pipeline?" [shape=diamond];
"Multiple targets\nwith different profiles?" [shape=diamond];
"Team > 3 developers?" [shape=diamond];
"Automatic Signing" [shape=box, label="Use Automatic Signing\nXcode manages everything"];
"Manual + match" [shape=box, label="Use Manual Signing\n+ fastlane match"];
"Manual Signing" [shape=box, label="Use Manual Signing\nspecify profiles explicitly"];
"Automatic + overrides" [shape=box, label="Use Automatic Signing\nwith xcodebuild overrides\nfor CI"];
"New project or\nsmall team?" -> "CI/CD pipeline?" [label="no, larger team"];
"New project or\nsmall team?" -> "Automatic Signing" [label="yes, solo/2-3 devs"];
"CI/CD pipeline?" -> "Team > 3 developers?" [label="yes, have CI"];
"CI/CD pipeline?" -> "Multiple targets\nwith different profiles?" [label="no CI"];
"Team > 3 developers?" -> "Manual + match" [label="yes"];
"Team > 3 developers?" -> "Automatic + overrides" [label="no, small team + CI"];
"Multiple targets\nwith different profiles?" -> "Manual Signing" [label="yes"];
"Multiple targets\nwith different profiles?" -> "Automatic Signing" [label="no"];
}
自動署名
最適な対象:個人開発者、小規模チーム、CI のないプロジェクト。
Xcode が証明書とプロビジョニングプロファイルを自動的に管理します。チームを選択するだけです。
Xcode → Target → Signing & Capabilities → ✓ Automatically manage signing → Select Team
仕組み:
- 必要に応じて Xcode が証明書を作成またはダウンロードします
- 機能に一致するプロビジョニングプロファイルを生成します
- 機能を追加または削除すると、プロファイルを再生成します
- デバイスを接続すると、そのデバイスを登録します
制限事項:
- 1 台のマシンにつき 1 人の開発者の証明書のみです(チームでは競合する場合があります)
- CI では
xcodebuildのオーバーライドまたは Xcode Cloud が必要です - チームメンバー間でプロファイルを簡単に共有できません
- 複数のプロファイルが使用可能な場合、想定外のプロファイルが選択されることがあります
手動署名
最適な用途:チーム、CI/CD パイプライン、複数のターゲットや拡張機能を含むアプリ。
使用する証明書とプロファイルを明示的に指定します。
Xcode → Target → Signing & Capabilities → ✗ Automatically manage signing
→ Select Provisioning Profile for each configuration (Debug/Release)
仕組み:
- Apple Developer Portal で証明書とプロファイルを作成します
- プロファイルを手動でダウンロードしてインストールします(または match を使用します)
- Xcode または xcodebuild で使用するプロファイルを正確に指定します
- 使用する証明書とプロファイルの組み合わせを完全に制御できます
必要なビルド設定:
CODE_SIGN_STYLE = Manual
CODE_SIGN_IDENTITY = Apple Distribution: Company Name (TEAMID)
PROVISIONING_PROFILE_SPECIFIER = MyApp App Store Profile
DEVELOPMENT_TEAM = YOURTEAMID
証明書の種類とライフサイクル
証明書の種類の選択
| シナリオ | 証明書の種類 | 備考 |
|---|---|---|
| デバイス上でのデバッグビルド | Apple Development | Xcode によって自動作成されます |
| TestFlight/App Store | Apple Distribution | アカウントあたり最大 3 個 |
| Ad Hoc 配布 | Apple Distribution | 同じ証明書を使用しますが、プロファイルの種類が異なります |
| App Store 外での macOS 配布 | Developer ID Application | 有効期間は 5 年です |
証明書の更新手順
証明書の有効期間は 1 年です(Developer ID は 5 年です)。証明書の有効期限が切れた場合:
- 期限切れの証明書を失効させないでください — すでに期限切れです。失効させるとポータルから削除され、その証明書を参照しているプロファイルも無効になります
- Apple Developer Portal で新しい証明書を作成します
- 新しい証明書をダウンロードしてインストールします
- 古い証明書を使用していたすべてのプロビジョニングプロファイルを編集し、新しい証明書を選択して再生成します
- 更新したプロファイルをダウンロードしてインストールします
- 新しい .p12 とプロファイルを使って CI を更新します
- fastlane match を使用している場合:
fastlane match nuke [type]を実行してから、fastlane match [type]を実行します
チーム内の調整:再生成する前にチームへ通知してください。配布用証明書は共有されるため、1 つを再生成すると全員に影響します。
プロビジョニングプロファイルのパターン
開発用プロファイル
登録済みデバイスでのデバッグビルドに使用します。
- 含まれるもの:開発用証明書、登録済みデバイスの UDID、App ID、エンタイトルメント
- 作成方法:Xcode で自動作成(自動署名)するか、ポータルで手動作成します
- デバイス:ポータルに明示的に登録する必要があります(種類ごとに年間 100 台まで)
Ad Hoc プロファイル
TestFlight を使わずに、特定のデバイスでテストする場合に使用します。
- 含まれるもの:配布用証明書、登録済みデバイスの UDID、App ID、エンタイトルメント
- 使用例:QA テスト、クライアント向けデモ、TestFlight を使わないベータテスト
- 制限:開発用プロファイルと同じく、年間 100 台まで
App Store プロファイル
TestFlight と App Store への提出に使用します。
- 含まれるもの:配布用証明書、App ID、エンタイトルメント(デバイスリストは含みません)
- デバイス数の制限はありません。TestFlight では最大 10,000 人のテスターをサポートします
- Xcode Organizer からのアップロード、または
xcodebuild -exportArchiveに必要です
Enterprise プロファイル
社内配布に使用します(Apple Developer Enterprise Program のみ)。
- 含まれるもの:Enterprise 証明書、App ID、エンタイトルメント(デバイスリストは含みません)
- デバイスを登録せずに社内配布できます
- App Store には提出できません
- Apple はコンプライアンス監査を実施します。不正使用(一般公開のための配布)があった場合、プログラムが終了となります
エンタイトルメントの設定
新しい機能の追加
- Apple Developer Portal:App IDs → App ID を選択 → Capabilities → 機能を有効にします
- Xcode:Target → Signing & Capabilities → + Capability → 機能を選択します
- プロファイルの再生成:手動署名を使用している場合は、新しい機能を含めるようプロビジョニングプロファイルを編集し、生成してダウンロードします
自動署名を使用している場合、手順 1 と 3 は Xcode が自動的に処理します。
一般的な機能と権限の対応関係
| 機能 | 権限キー | プロファイルの要件 |
|---|---|---|
| プッシュ通知 | aps-environment | プロファイルに含まれている必要があります |
| App Groups | com.apple.security.application-groups | プロファイルに含まれている必要があります |
| Associated Domains | com.apple.developer.associated-domains | プロファイルに含まれている必要があります |
| Sign in with Apple | com.apple.developer.applesignin | プロファイルに含まれている必要があります |
| HealthKit | com.apple.developer.healthkit | プロファイルに含まれている必要があります |
| iCloud | com.apple.developer.icloud-* | プロファイルに含まれている必要があります |
| アプリ内課金 | 自動 | プロファイルの変更は不要です |
| バックグラウンドモード | UIBackgroundModes (Info.plist) | プロファイルの変更は不要です |
| Keychain Sharing | keychain-access-groups | プロファイルに含まれている必要があります |
複数ターゲットの権限
各ターゲット(アプリ、ウィジェット、拡張機能など)には、それぞれ次のものが必要です。
- Developer Portal の App ID
- プロビジョニングプロファイル
- .entitlements ファイル
すべてのターゲットで同じ Team ID を共有する必要があります。App Groups を使うと、ターゲット間でデータを共有できます。
com.example.app → MyApp.entitlements
com.example.app.widget → Widget/Widget.entitlements
com.example.app.NotificationService → NotificationService/NotificationService.entitlements
CI/CD の署名設定
fastlane を使用しない場合(生のスクリプト)
CI のキーチェーンスクリプトの全手順については、axiom-code-signing-ref を参照してください。重要な手順は次のとおりです。
- 一時キーチェーンを作成する
- 検索リストに追加する(login.keychain-db を含める)— login キーチェーンの認証情報へのアクセスが壊れるため、
default-keychain -sは使用しないでください - キーチェーンのロックを解除する
- .p12 証明書を読み込む
- パーティションリストを設定する(errSecInternalComponent を防止します)
- プロビジョニングプロファイルを
~/Library/MobileDevice/Provisioning Profiles/にインストールする - 明示的な署名設定でビルド/アーカイブする
- クリーンアップする — 一時キーチェーンを削除する(失敗時も必ず実行します)
fastlane match を使用する場合
fastlane match は、パスフレーズで暗号化した証明書とプロファイルを、共有 Git リポジトリ(またはクラウドストレージ)で管理します。
初期設定(チーム管理者が一度だけ実行します):
fastlane match init # Choose storage (git, google_cloud, s3)
fastlane match development # Generate dev certs + profiles
fastlane match appstore # Generate distribution certs + profiles
CI での使用(読み取り専用 — CI で生成しないでください):
# Fastfile
lane :release do
setup_ci # Creates temporary keychain
match(type: "appstore", readonly: true)
build_app(scheme: "MyApp", export_method: "app-store")
end
重要なルール:
- CI では
readonly: trueを使用する必要があります — CI から証明書を生成しないでください MATCH_PASSWORDを CI シークレットとして設定します(証明書リポジトリの暗号化/復号に使用します)setup_ciを使って一時キーチェーンを作成します(キーチェーンの設定をすべて処理します)- 各アプリターゲットには、Matchfile で独自の
app_identifierが必要です
Xcode Cloud
Xcode Cloud は署名を自動的に処理します。
- 証明書の管理は不要です — Apple が署名インフラストラクチャを管理します
- Xcode → Product → Xcode Cloud → Manage Workflows で設定します
- カスタム設定(SPM 認証、カスタムソースからの証明書取得)には
ci_post_clone.shを使用します - 配布用の署名は「Archive」アクション中に処理されます
アンチパターン
アンチパターン 1:チャットで .p12 を共有する
誤り:
Slack: "Hey, here's the distribution cert 📎 cert.p12, password is Company123"
正しい方法:fastlane match(暗号化された Git リポジトリ)または共有チームアカウントでの Xcode 自動署名を使用します。
重要な理由:チャットで共有した .p12 ファイルは、セキュリティリスク(チャット履歴に認証情報が残る)、バージョンの混乱(どの証明書が最新なのか)、単一障害点(送信者の証明書が期限切れまたは失効した場合)を招きます。共有証明書に問題が起きると、チームメンバー 1 人あたり 1~2 時間の時間を要します。
アンチパターン 2:シークレットを Git にコミットする
誤り:
git add certificates/distribution.p12
git add profiles/AppStore.mobileprovision
git commit -m "Add signing files"
正しい方法:CI のシークレット管理を使用します。
# GitHub Actions
echo "$P12_BASE64" | base64 --decode > certificate.p12 # From secrets
echo "$PROFILE_BASE64" | base64 --decode > profile.mobileprovision
重要な理由:証明書とプロファイルはシークレットです。これらがあれば、誰でもあなたのチームとしてアプリに署名できます。プライベートリポジトリであっても、Git の履歴は永久に残ります。一度コミットすると、その認証情報はすべてのクローンに残り続けます。
すでにコミットしてしまった場合:git filter-repo --path path/to/cert.p12 --invert-paths で履歴を削除し、その後、漏えいした証明書をローテーションします(ポータルで失効させ、新しい証明書を作成し、CI シークレットを更新します)。既存のクローンにはすべて古い証明書が残っています — 漏えいしたものとして扱ってください。
アンチパターン 3:「無効化」して署名を「修正」する
誤り:
CODE_SIGN_IDENTITY = ""
CODE_SIGNING_REQUIRED = NO
CODE_SIGNING_ALLOWED = NO
正しい方法:必須の診断手順に従って、実際の署名エラーを診断します。
重要な理由:コード署名を無効にすると、シミュレーターのビルドでは「動作」しますが、デバイスのビルド、アーカイブ、配布では失敗します。問題の解決が先送りされ、デバッグが難しく、期限間際に発覚します。時間コスト:元の問題への対応に加え、エクスポート/アップロードのデバッグに 30 分以上かかります。
アンチパターン 4:チーム/CI に個人用証明書を使う
誤り:
# CI pipeline uses one developer's personal certificate
security import ~/charles-personal.p12 ...
CODE_SIGN_IDENTITY = "Apple Distribution: Charles Personal (ABC123)"
正しい方法:fastlane match または共有の Apple Developer アカウントで管理する、専用のチーム証明書を使用します。
match(type: "appstore", readonly: true)
重要な理由:その開発者が退職したり、マシンを変更したり、証明書の期限が切れたりすると、CI とチーム全体への配布が機能しなくなります。個人用証明書を共有インフラの依存関係にしてはいけません。時間コスト:担当者が不在のときに緊急で証明書をローテーションするのに 2~4 時間かかります。
プレッシャーのかかる状況
シナリオ 1:「今日リリースできるよう、コード署名を無効にしてください」
状況:ビルド期限が迫っており、コード署名エラーでアーカイブがブロックされています。
プレッシャー:「テストに署名は必要ありません。無効にして、リリース後に修正しましょう。」
実情:有効なコード署名がなければ、TestFlight や App Store に提出できません。今無効にすると、提出という最も時間に追われる段階にブロッカーを先送りすることになります。診断手順は 5~10 分で完了し、根本原因を特定できます。
正しい対応:必須の最初の手順のステップ 1~4 を実行します。署名の問題のほとんどは、期限切れまたは不一致のコンポーネントが 1 つあることが原因です。
反論の例:「有効な署名がなければ、TestFlight や App Store に提出できません。診断には 5 分かかり、何が問題かを正確に特定できます。今無効にすると、提出時に同じブロッカーに、さらに時間がない状態で直面することになります。」
シナリオ 2:「チームのビルドに私の個人用証明書を使ってください」
状況:配布証明書の期限切れにより CI が機能していません。チームメンバーが、応急処置として個人用証明書を使うことを提案しています。
プレッシャー:「使える証明書を持っているので、とりあえず私のを使ってください。」
実情:個人用証明書を使うと、単一障害点が生まれます。その人が不在、休暇中、または退職した場合、本人の協力なしには復旧できず、署名ができなくなります。適切な修正(チーム証明書の更新)にかかる時間は同じです。
正しい対応:Apple Developer Portal でチームの配布証明書を更新します。CI のシークレットを更新します。新しい証明書でプロビジョニングプロファイルを再生成します。
反論の例:「あなたの証明書は短期的には使えますが、すべてのビルドにおける単一障害点になってしまいます。チーム証明書の更新にも同じ 10 分がかかり、特定の個人への依存も生じません。」
シナリオ 3:「CI が使えるように、.p12 をリポジトリにコミットしてください」
状況:CI/CD を初めて設定しています。開発者が利便性のため、証明書を git にコミットしようとしています。
プレッシャー:「プライベートリポジトリなので、ほかの人には見られません。」
実情:Git の履歴は永久に残ります。プライベートリポジトリであっても、秘密鍵を含む .p12 は、すべてのクローン、フォーク、バックアップに永遠に残ります。リポジトリが公開されたり、オープンソース化されたり、請負業者がアクセスしたりすれば、署名鍵が漏えいします。CI のシークレット管理は、まさにこのためにあります。
正しい対応:.p12 を Base64 エンコードし、CI のシークレット(GitHub Secrets、GitLab CI Variables など)として保存します。ビルド時にデコードします。
反論の例:「Git の履歴は永久に残ります。一度コミットすると、証明書はすべてのクローンに永遠に残ります。CI のシークレット管理(GitHub Secrets)は同じ手間で設定でき、この用途のために設計されています。適切に設定させてください。」
チェックリスト
配布用にアーカイブする前に:
証明書:
- 配布用証明書が有効である(期限切れまたは失効していない)
-
security find-identity -v -p codesigningで想定される ID が表示される - 証明書がプロビジョニングプロファイルで想定されているものと一致する
プロビジョニングプロファイル:
- プロファイルの有効期限が切れていない
- プロファイルの種類が配布方法(App Store、Ad Hoc、Enterprise)と一致する
- プロファイルに署名に使用する証明書が含まれている
- プロファイルのバンドル ID がターゲットのバンドル識別子と一致する
エンタイトルメント:
- Xcode のすべての機能がプロファイル内の機能と一致する
- .entitlements ファイルにプロファイルにない機能が含まれていない
- アプリ拡張機能に正しいエンタイトルメントを持つ独自のプロファイルがある
- メインアプリと拡張機能で App Groups に一貫性がある
ビルド設定:
-
CODE_SIGN_STYLEが意図(Automatic または Manual)と一致する -
CODE_SIGN_IDENTITYがビルドの種類(Development または Distribution)に対して正しい - 手動署名の場合、
PROVISIONING_PROFILE_SPECIFIERが設定されている -
DEVELOPMENT_TEAMに正しい Team ID が設定されている
CI/CD(該当する場合):
- キーチェーンが作成、ロック解除され、パーティションリストが設定されている
- 証明書が CI キーチェーンにインポートされている
- プロファイルが
~/Library/MobileDevice/Provisioning Profiles/にインストールされている - クリーンアップ処理が成功時と失敗時に実行される(
if: always())
リソース
WWDC:2021-10204、2022-110353
ドキュメント:/security、/bundleresources/entitlements、/xcode/distributing-your-app
スキル:axiom-code-signing-ref、axiom-code-signing-diag