axiom-code-signing-diag について
iOS/macOS開発者向けのコード署名診断スキルです。証明書、プロビジョニングプロファイル、権限、Keychain設定を調べ、症状別の手順でビルドやアップロードの失敗原因を探ります。
主な機能
- 01署名IDの確認
- 02プロビジョニングプロファイルのデコード
- 03アプリの権限設定の比較
- 04CIのKeychain問題の調査
- 05症状別の判断ツリー
活用シーン
- 01署名証明書が見つからない問題の診断
- 02CIの署名失敗の調査
- 03権限やプロファイルの不一致の特定
- 04App Storeアップロード拒否への対応
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ charleswiltgen/ axiom --skill axiom-code-signing-diagインストール後、Claude Code で/axiom-code-signing-diagを入力して読み込まれたか確認します。
詳細
コード署名の診断
コード署名の失敗を体系的にトラブルシューティングします。証明書の不足、プロビジョニングプロファイルの不一致、CI でのキーチェーンの問題、エンタイトルメントの競合、App Store へのアップロード拒否を扱います。
概要
基本原則:コード署名が失敗する場合、通常は次のいずれかが原因です。
- 証明書の問題(期限切れ、不足、種類の誤り、失効) — 30%
- プロビジョニングプロファイルの問題(期限切れ、証明書の不足、App ID の誤り、機能の不足) — 25%
- エンタイトルメントの不一致(Xcode には機能があるがプロファイルにはない、またはその逆) — 15%
- キーチェーンの問題(CI でロックされている、errSecInternalComponent、パーティションリスト) — 15%
- アーカイブ/エクスポートの問題(エクスポート方法の誤り、配布用の証明書の種類の誤り) — 10%
- 署名 ID の曖昧さ(一致する証明書が複数あり、Xcode が誤ったものを選択する) — 5%
ビルド設定を書き換えたり、すべてを再生成したりする前に、証明書、プロファイル、エンタイトルメントを必ず確認してください。
注意すべき兆候
コード署名固有の問題を示す症状:
| 症状 | 考えられる原因 |
|---|---|
| "No signing certificate found" | 証明書の期限切れ、失効、またはキーチェーンに存在しない |
| "Provisioning profile doesn't include signing certificate" | キーチェーンにあるものとは別の証明書を使ってプロファイルが生成されている |
| ITMS-90035 Invalid Signature | Distribution ではなく Development 証明書で署名されている |
| ITMS-90161 Invalid Provisioning Profile | プロファイルの期限切れ、またはバイナリとの不一致 |
| CI で errSecInternalComponent が発生する | キーチェーンがロックされている、または set-key-partition-list が呼び出されていない |
| "Ambiguous — matches multiple" | 同じ名前の有効な証明書が複数ある(開発用+期限切れ) |
| "Entitlement not allowed by profile" | Xcode で機能を追加したが、プロファイルを再生成していない |
| "codesign wants to access key" ダイアログ | codesign にキーチェーンへのアクセスが許可されていない |
| ローカルではビルドできるが、CI では失敗する | キーチェーンの設定手順(作成、ロック解除、パーティションリスト)が不足している |
| "Profile doesn't match bundle ID" | Xcode ターゲットとプロファイルのバンドル識別子が一致しない |
| アーカイブ成功後にエクスポートが失敗する | ExportOptions.plist で誤った方法またはプロファイルが指定されている |
| アプリ拡張機能の署名が失敗する | 拡張機能には、チームとプレフィックスが一致する専用のプロファイルが必要 |
非合理化
| 合理化 | うまくいかない理由 | 所要時間 |
|---|---|---|
| 「証明書は昨日まで問題ありませんでした」 | 証明書は期限切れになったり、取り消されたりします。ポータルの変更によってプロファイルが自動的に再生成されることもあります。必ず再確認してください。 | 証明書が一晩で期限切れになった場合、ビルド設定のデバッグに30~60分 |
| 「すべて再生成してみます」 | 証明書を再生成すると古い証明書が取り消され、ほかのチームメンバーや CI に影響します。まず原因を特定してください。 | 2~4時間+チームメンバーへの影響+CI パイプラインの停止 |
| 「キーチェーンをリセットします」 | 保存されているすべての認証情報(SSH キー、保存済みパスワード、ほかの証明書)が消去されます。問題の証明書を特定してください。 | すべての認証情報の復元に1~2時間 |
| 「とりあえずコード署名を無効にします」 | デバイス向けビルドや配布では、コード署名を無効にできません。あとになって、時間がないときに同じ問題に直面します。 | 時間を無駄にしたうえ、元の問題も解決しません |
| 「Xcode のバグなので、再インストールします」 | コード署名の問題は設定に起因するもので、Xcode のバグではありません。再インストールしても証明書やプロファイルは変わりません。 | 設定の問題が解決しないまま、Xcode の再インストールに2~4時間 |
| 「チームのプロビジョニングプロファイルを使います」 | Xcode が自動管理するワイルドカードプロファイルには、特定のエンタイトルメント(プッシュ通知、App Groups)がありません。これらの機能を必要とするアプリでは使えません。 | 必要な機能が不足していると判明するまでに30分以上 |
| 「CI は以前動いていたので、こちら側では何も変えていません」 | Apple がセキュリティ上の理由で証明書を取り消すことがあります。CI ランナーの macOS アップデートによって、キーチェーンの動作が変わることがあります。プロビジョニングプロファイルは1年で期限切れになります。 | 証明書が期限切れなのに「何も変更していない」と何時間も主張することになります |
| 「まずコードを確認します」 | コード署名エラーがコードのバグであることは絶対にありません。原因は100%設定、つまり証明書、プロファイル、エンタイトルメント、キーチェーンにあります。 | プロファイルが期限切れなのに、正常なコードのデバッグに何時間も費やします |
| 「build.keychain をデフォルトに設定します」 | security default-keychain -s build.keychain はログインキーチェーンをデフォルトから置き換えるため、SSH キー、保存済みパスワード、ほかの認証情報にアクセスできなくなります。代わりに list-keychains -s を使ってください。 | デフォルトキーチェーンの復元と、原因不明の SSH/認証情報のエラー対応に30分以上 |
必須の最初の手順
ビルド設定を変更したり、証明書を再生成したりする前に、以下の診断を実行してください。
手順 1: 署名 ID を確認する
security find-identity -v -p codesigning
想定される出力:
- 「Apple Development」または「Apple Distribution」の有効な ID が1つ以上ある
- 各 ID に SHA-1 ハッシュ、名前、Team ID が表示される
問題:
- 有効な ID が0件 → 証明書がインストールされていないか、すべて期限切れです
- 「Apple Development」のみだがアーカイブしようとしている → Distribution 証明書が必要です
- 同じ名前の項目が複数ある → ID が曖昧です(ツリー 5 を参照)
手順 2: プロビジョニングプロファイルをデコードする
# Find the profile being used
find ~/Library/Developer/Xcode/DerivedData -name "embedded.mobileprovision" -newer . 2>/dev/null | head -3
# Decode it
security cms -D -i path/to/embedded.mobileprovision
以下のフィールドを確認してください:
ExpirationDate→ 期限切れではありませんか?DeveloperCertificates→ 現在の証明書が含まれていますか?Entitlements→ アプリで使うすべての機能が含まれていますか?ProvisionedDevices→ テストデバイスの UDID が含まれていますか?(Development/Ad Hoc のみ)Name→ Xcode で使うよう設定されている名前と一致していますか?
手順 3: エンタイトルメントを抽出して比較する
# What entitlements does the built app have?
codesign -d --entitlements - /path/to/MyApp.app
# What entitlements does the profile grant?
security cms -D -i embedded.mobileprovision | plutil -extract Entitlements xml1 -o - -
# What entitlements does Xcode's .entitlements file declare?
cat MyApp/MyApp.entitlements
3つすべてが一致している必要があります。 不一致があると、署名に失敗します。
手順 4: プロファイル内の証明書を確認する
# Get certificate SHA-1 from keychain
security find-identity -v -p codesigning | grep "Apple Distribution"
# Output: 1) ABCDEF123... "Apple Distribution: Company (TEAMID)"
# Check if that certificate is embedded in the profile
security cms -D -i embedded.mobileprovision | plutil -extract DeveloperCertificates xml1 -o - -
# Decode one of the base64 certificates:
echo "<base64 data>" | base64 -d | openssl x509 -inform DER -noout -fingerprint -sha1
プロファイルの SHA-1 は find-identity の SHA-1 と一致している必要があります。
判断ツリー
ツリー 1: 「署名証明書が見つかりません」
digraph tree1 {
"No signing certificate?" [shape=diamond];
"Run find-identity" [shape=box, label="security find-identity -v -p codesigning"];
"0 identities?" [shape=diamond];
"Has identities but wrong type?" [shape=diamond];
"Certificate expired?" [shape=diamond];
"Import certificate" [shape=box, label="Import .p12 into keychain\nsecurity import cert.p12 -k login.keychain-db -P pass -T /usr/bin/codesign"];
"Download from portal" [shape=box, label="Download certificate from\nApple Developer Portal\nor use Xcode > Preferences > Accounts"];
"Use correct cert type" [shape=box, label="Archive needs Apple Distribution\nDebug needs Apple Development\nCheck CODE_SIGN_IDENTITY"];
"Renew certificate" [shape=box, label="Revoke expired cert in portal\nCreate new cert\nUpdate profiles to use new cert"];
"CI keychain issue" [shape=box, label="In CI: create keychain, import cert,\nunlock, set-key-partition-list\n(see code-signing-ref CI section)"];
"No signing certificate?" -> "Run find-identity";
"Run find-identity" -> "0 identities?" [label="check output"];
"0 identities?" -> "Import certificate" [label="yes, no certs at all"];
"0 identities?" -> "Has identities but wrong type?" [label="no, has some"];
"Has identities but wrong type?" -> "Use correct cert type" [label="yes, dev only but need dist"];
"Has identities but wrong type?" -> "Certificate expired?" [label="no, correct type exists"];
"Certificate expired?" -> "Renew certificate" [label="yes"];
"Certificate expired?" -> "CI keychain issue" [label="no, cert valid but CI fails"];
"Import certificate" -> "Download from portal" [label="don't have .p12"];
}
ツリー 2: 「プロビジョニングプロファイルに署名証明書が含まれていません」
digraph tree2 {
"Profile cert mismatch?" [shape=diamond];
"Automatic signing?" [shape=diamond];
"Clean and retry" [shape=box, label="Xcode > Preferences > Accounts\n> Download Manual Profiles\nClean build folder (Cmd+Shift+K)"];
"Regenerate profile" [shape=box, label="Apple Developer Portal:\n1. Edit profile\n2. Select current certificate\n3. Generate\n4. Download and install"];
"Check cert match" [shape=box, label="Step 4: Verify certificate SHA-1\nin keychain matches SHA-1\nembedded in profile"];
"Revoked cert" [shape=box, label="If someone regenerated the cert,\nall existing profiles are invalid.\nRegenerate profiles with new cert."];
"Profile cert mismatch?" -> "Automatic signing?" [label="check Xcode"];
"Automatic signing?" -> "Clean and retry" [label="yes"];
"Automatic signing?" -> "Check cert match" [label="no, manual signing"];
"Check cert match" -> "Regenerate profile" [label="SHA-1 mismatch"];
"Check cert match" -> "Revoked cert" [label="cert not in profile at all"];
}
ツリー 3: ITMS-90035/90161 無効な署名/プロファイル
digraph tree3 {
"Upload rejected?" [shape=diamond];
"ITMS-90035?" [shape=diamond];
"ITMS-90161?" [shape=diamond];
"ITMS-90046?" [shape=diamond];
"Wrong cert" [shape=box, label="Signed with Development cert.\nRe-archive with Apple Distribution.\nCODE_SIGN_IDENTITY = Apple Distribution"];
"Cert expired" [shape=box, label="Certificate expired between\narchive and upload.\nRenew cert, re-archive."];
"Profile expired" [shape=box, label="Provisioning profile expired.\nRegenerate in portal,\nre-archive."];
"Profile mismatch" [shape=box, label="Profile doesn't match binary.\nCheck bundle ID alignment.\nVerify ExportOptions.plist."];
"Check entitlements" [shape=box, label="Entitlement not in profile.\nAdd capability in portal,\nregenerate profile, re-archive."];
"Upload rejected?" -> "ITMS-90035?" [label="check error code"];
"Upload rejected?" -> "ITMS-90046?" [label="ITMS-90046"];
"ITMS-90035?" -> "Wrong cert" [label="'Invalid Signature'"];
"ITMS-90035?" -> "ITMS-90161?" [label="different error"];
"ITMS-90046?" -> "Check entitlements" [label="'Invalid Entitlements'"];
"ITMS-90161?" -> "Profile expired" [label="'Invalid Provisioning Profile'"];
"ITMS-90161?" -> "Profile mismatch" [label="'profile doesn't match'"];
"Wrong cert" -> "Cert expired" [label="cert IS Distribution but still fails"];
}
ツリー 4: CI での errSecInternalComponent/キーチェーンのロック
digraph tree4 {
"errSecInternalComponent?" [shape=diamond];
"Keychain created?" [shape=diamond];
"Keychain unlocked?" [shape=diamond];
"Partition list set?" [shape=diamond];
"Search list correct?" [shape=diamond];
"Create keychain" [shape=box, label="security create-keychain -p pass build.keychain"];
"Unlock keychain" [shape=box, label="security unlock-keychain -p pass build.keychain"];
"Set partition list" [shape=box, label="security set-key-partition-list\n-S apple-tool:,apple: -s\n-k pass build.keychain\n(MOST COMMON FIX)"];
"Add to search list" [shape=box, label="security list-keychains -d user\n-s build.keychain login.keychain-db"];
"Set timeout" [shape=box, label="security set-keychain-settings\n-t 3600 -l build.keychain\n(prevent lock during long builds)"];
"Check runner image" [shape=box, label="Runner image may have changed.\nCheck GitHub Actions runner changelog.\nmacOS updates change keychain defaults."];
"errSecInternalComponent?" -> "Keychain created?" [label="CI environment"];
"Keychain created?" -> "Create keychain" [label="no"];
"Keychain created?" -> "Keychain unlocked?" [label="yes"];
"Keychain unlocked?" -> "Unlock keychain" [label="no"];
"Keychain unlocked?" -> "Partition list set?" [label="yes"];
"Partition list set?" -> "Set partition list" [label="no — this is the #1 fix"];
"Partition list set?" -> "Search list correct?" [label="yes"];
"Search list correct?" -> "Add to search list" [label="no — keychain not in search path"];
"Search list correct?" -> "Set timeout" [label="yes — try extending timeout"];
"Set timeout" -> "Check runner image" [label="still failing"];
}
ツリー 5: ID が曖昧/証明書が複数ある
digraph tree5 {
"Ambiguous identity?" [shape=diamond];
"Same name, different dates?" [shape=diamond];
"Dev and Dist both present?" [shape=diamond];
"List all" [shape=box, label="security find-identity -v -p codesigning\nNote SHA-1 hashes and expiry dates"];
"Delete expired" [shape=box, label="Open Keychain Access\nDelete expired certificate\n(check expiry with openssl x509 -enddate)"];
"Use SHA-1" [shape=box, label="Specify exact identity by SHA-1:\nCODE_SIGN_IDENTITY = 'SHA1HASH'\nor codesign -s 'SHA1HASH'"];
"Specify full name" [shape=box, label="Use full identity name:\nCODE_SIGN_IDENTITY =\n'Apple Distribution: Company (TEAMID)'"];
"Ambiguous identity?" -> "List all" [label="first"];
"List all" -> "Same name, different dates?" [label="inspect"];
"Same name, different dates?" -> "Delete expired" [label="yes, old + new cert"];
"Same name, different dates?" -> "Dev and Dist both present?" [label="no"];
"Dev and Dist both present?" -> "Specify full name" [label="yes, Xcode picks wrong one"];
"Dev and Dist both present?" -> "Use SHA-1" [label="still ambiguous"];
}
ツリー 6: エンタイトルメントの不一致/機能の不足
digraph tree6 {
"Entitlement error?" [shape=diamond];
"In Xcode but not profile?" [shape=diamond];
"In profile but not Xcode?" [shape=diamond];
"Run Step 3" [shape=box, label="Compare entitlements:\n1. codesign -d --entitlements - App\n2. Profile entitlements\n3. .entitlements file"];
"Regenerate profile" [shape=box, label="Apple Developer Portal:\n1. App ID > Capabilities\n2. Enable missing capability\n3. Edit profile\n4. Generate and download"];
"Add capability" [shape=box, label="Xcode > Target >\nSigning & Capabilities >\n+ Capability"];
"Remove stale entitlement" [shape=box, label="Remove capability from\n.entitlements file that\nisn't supported by profile type"];
"Entitlement error?" -> "Run Step 3" [label="diagnose"];
"Run Step 3" -> "In Xcode but not profile?" [label="compare"];
"In Xcode but not profile?" -> "Regenerate profile" [label="yes, capability missing from profile"];
"In Xcode but not profile?" -> "In profile but not Xcode?" [label="no"];
"In profile but not Xcode?" -> "Add capability" [label="yes"];
"In profile but not Xcode?" -> "Remove stale entitlement" [label="entitlement not valid for profile type"];
}
クイックリファレンス表
| 症状 | 確認項目 | 修正方法 |
|---|---|---|
| 署名証明書が見つからない | security find-identity -v -p codesigning | 証明書を読み込むか、ポータルからダウンロードします |
| プロビジョニングプロファイルに証明書が含まれていない | ステップ 4:SHA-1 の比較 | 現在の証明書を使ってプロファイルを再生成します |
| ITMS-90035 署名が無効です | アーカイブ済みアプリに対して codesign -dv | Apple Distribution 証明書を使って再アーカイブします |
| ITMS-90161 プロビジョニングプロファイルが無効です | プロファイルに対して security cms -D -i | 期限切れではないプロファイルを再生成します |
| ITMS-90046 エンタイトルメントが無効です | ステップ 3:3 つの項目の比較 | ポータルでケイパビリティを追加し、プロファイルを再生成します |
| errSecInternalComponent | CI のキーチェーン設定 | set-key-partition-list(最も一般的な修正方法) |
| ID があいまいです | security find-identity -v の件数 | 期限切れの証明書を削除するか、SHA-1 ハッシュを使用します |
| エンタイトルメントが一致しない | 3 つのエンタイトルメントを比較 | Xcode、プロファイル、.entitlements を一致させます |
| プロファイルの期限切れ | security cms -D で ExpirationDate を確認 | ポータルから新しいプロファイルをダウンロードします |
| プロファイルにプッシュ通知がない | プロファイル内で grep aps-environment | ポータルで Push を有効にして、プロファイルを再生成します |
| 拡張機能の署名に失敗する | 拡張機能ターゲットの署名設定 | 各拡張機能には、チームが一致する独自のプロファイルが必要です |
| ローカルでは動作するが、CI では失敗する | CI のキーチェーンスクリプトが完全か確認 | 完全な設定:作成、ロック解除、読み込み、パーティションリスト、検索リスト |
| 「codesign がキーへのアクセスを要求しています」 | キーチェーンのアクセス設定 | security set-key-partition-list または Keychain Access > 情報を見る > アクセス制御 |
| App Groups のエンタイトルメントエラー | 3 つの項目の比較 | ポータルの App ID に App Group を追加し、プロファイルを再生成します |
| ビルドは成功するが、エクスポートに失敗する | ExportOptions.plist | plist 内の method、プロファイル名、チーム ID を確認します |
プレッシャーのかかる状況
シナリオ 1:「とにかくすべて再生成しよう」
状況:コード署名に失敗しています。チームメンバーが、すべてを一新するために証明書をすべて失効させて新しく生成することを提案します。
プレッシャー:「すべて再生成しても、たった 5 分で済みます。」
実情:配布証明書を失効させると、その証明書を使用するすべてのプロビジョニングプロファイルが無効になります。対象はチームメンバー全員とすべての CI システムに及びます。開発者全員が新しい証明書を必要とします。すべての CI パイプラインが動作しなくなります。すべてのプロファイルを再生成する必要があります。「5 分で済む修正」は、チーム全体に 2~4 時間の障害をもたらします。
適切な対応:ステップ 1~4 を使って、問題を特定します。署名の失敗の大半は、システム全体の問題ではなく、期限切れまたは不一致のコンポーネント 1 つが原因です。
反対するときのテンプレート:「証明書を失効させると、チーム全員とすべての CI パイプラインの署名に影響します。まず診断手順を実行させてください。署名の問題の 90%は、期限切れの証明書かプロファイルの不一致が 1 つあるだけで、他の人に影響を与えずに 5 分で修正できます。」
シナリオ 2:「Xcode を更新したら署名に失敗した。ロールバックしよう」
状況:Xcode の更新後、コード署名が動作しなくなりました。誰かが Xcode のロールバックを提案します。
プレッシャー:「更新前はビルドできていたのだから、更新が原因です。」
実情:Xcode の更新によって、管理対象の署名キャッシュが無効になったり、自動署名でプロファイルを選択する方法が変わったりすることがあります。しかし、証明書やプロファイル自体に変更はありません。Xcode をロールバックすると、新しい SDK 機能を利用できなくなり、根本的な設定の問題も解決しません。
適切な対応:ステップ 1~2 を実行し、証明書とプロファイルが引き続き有効か確認します。Xcode の自動署名で別のプロファイルが選択されていないか確認します。次を試してください:Xcode → 環境設定 → アカウント → 手動プロファイルをダウンロード。ビルドフォルダをクリーンアップします。
反対するときのテンプレート:「Xcode の更新によって、証明書やプロファイルが変更されることはありません。まず、Xcode の自動署名で現在どのプロファイルが選択されているか確認させてください。以前とは別のプロファイルが選ばれている可能性が高いです。5 分確認すれば、何が変わったのか正確に分かります。」
シナリオ 3:「アーカイブに失敗したので、もう一度アーカイブしましょう。たぶん破損しています」
背景:アーカイブには成功したものの、エクスポートまたはアップロードに失敗しました。開発者はアーカイブが破損したと思い込み、もう一度アーカイブしようとしています。
圧力:「もう一度やるだけです。今度はうまくいくでしょう。」
実際のところ:アーカイブの「破損」は極めてまれです。エクスポートの失敗は、ほとんどの場合、ExportOptions.plist のメソッドが間違っている、アーカイブ内の証明書の種類が違う、またはプロファイルが一致していないことが原因です。同じ設定で再アーカイブしても、同じ結果になります。
正しい対応:再ビルドする前にアーカイブを調べます。
- .xcarchive 内の .app に対して
codesign -dvを実行し、何で署名されているか確認します。 - ExportOptions.plist のメソッドが目的(app-store、ad-hoc など)に合っていることを確認します。
- ExportOptions で指定されたプロファイルが存在し、有効期限が切れていないことを確認します。
切り返しの例:「同じ設定で再アーカイブしても、同じ結果になります。アーカイブの中身を確認しましょう。codesign -dv を使えば30秒で、エクスポートに失敗した原因が正確にわかります。」
チェックリスト
署名の問題を解決済みと判断する前に、次の項目を確認します。
-
security find-identity -v -p codesigningの結果に、想定した ID が表示される -
security cms -Dでデコードしたプロファイルの有効期限が切れておらず、正しい証明書が含まれている - 3者間でエンタイトルメントを比較し、一致している(バイナリ、プロファイル、.entitlements ファイル)
- 正しい
CODE_SIGN_IDENTITYを指定してビルド/アーカイブに成功する - CI の場合:キーチェーンが作成され、ロック解除され、パーティションリストが設定され、証明書がインポートされている
- CI の場合:クリーンアップのステップが成功時と失敗時の両方で実行される
リソース
WWDC:2021-10204、2022-110353
ドキュメント:/security、/bundleresources/entitlements、/xcode/distributing-your-app
スキル:axiom-code-signing、axiom-code-signing-ref