
cocoapods‑keys を使ってシークレットをソースコードと分離して安全に扱う
はじめに
API キーやシークレットをソースコードにハードコーディングすると、GitHub を公開した際に流出リスクが生じる。
cocoapods‑keys は key の名前だけを Podfile に記述し、値は開発者のローカル Keychain に格納する CocoaPods プラグインだ。プロジェクト内へは難読化された stub だけが生成されるため、比較的安全にバイナリへ埋め込める。
この記事では cocoapods‑keys を導入し、アプリ起動直後に Text
でAPI キーの値を表示するところまでを解説する。
動作環境
- macOS 15.4.1(24E263)
- Xcode 16.2
- Homebrew 4.4.31
- CocoaPods 1.16.2
- cocoapods‑keys
'818f9d2'
- 注意:
'818f9d2'
はバージョンではなくコミット ID 固定
- 注意:
1. CocoaPods と cocoapods‑keys をインストール
bundle init
で Gemfile を生成し、下記を追記してインストールする。
# frozen_string_literal: true
source "https://rubygems.org"
# gem "rails"
gem "cocoapods"
gem "cocoapods-keys", ref: '818f9d2'
bundle install
後に bundle exec pod --version
と bundle exec pod keys --help
が通れば準備は完了だ。
2. Xcode プロジェクトを CocoaPods 対応にする
bundle exec pod init
で Podfile を生成し、次のように編集する。
platform :ios, "18.0"
plugin "cocoapods-keys", {
:project => "SampleCocoaPodsKeys",
:keys => [
"ApiKey",
"ApiBaseUrl"
]
}
target "SampleCocoaPodsKeys" do
use_frameworks!
# Pods for SampleCocoaPodsKeys
end
post_install do |installer|
installer.pods_project.targets.each do |t|
t.build_configurations.each do |c|
c.build_settings["IPHONEOS_DEPLOYMENT_TARGET"] = "18.0"
end
end
end
:keys
に列挙した文字列が環境変数名となる。ハイフン付きキーは避け、API-KEY
ではなく ApiKey
のように記述する。
pod install
でキー値を入力
3. bundle exec pod install
の初回実行時、Podfile へ書いたキーごとに値の入力を求められる。入力した値は、ローカルPCのKeychainに保存される。
値をあとから変更したい場合
bundle exec pod keys set ApiKey "abcd1234"
bundle exec pod keys set ApiBaseUrl "https://api.example.com"
保存済みの値は bundle exec pod keys get ApiKey
で確認できる。
4. 生成物を確認
Pods/
配下に CocoaPodsKeys モジュールが追加される。
生成された SampleCocoaPodsKeysKeys.m
は難読化済みソースだ。シークレットとソースを分離する意味が薄れるため、このファイル群は Git へコミットしないよう .gitignore
に追加する。
# cocoapods‑keys stub
Pods/CocoaPodsKeys/**
5. SwiftUI からキーを読む
Keys
フレームワークを import し、生成クラスからプロパティを取得する。デバッグビルドのみキーを表示する場合は #if DEBUG
を使う。
import SwiftUI
import Keys
struct ContentView: View {
private let keys = SampleCocoaPodsKeysKeys() // 自動生成されたクラス名
var body: some View {
VStack {
#if DEBUG
Text("API KEY: \(keys.apiKey)")
Text("BASE URL: \(keys.apiBaseUrl)")
#endif
}
.padding()
}
}
#Preview {
ContentView()
}
アプリを実行した結果は以下の通り。
トラブルシューティング
rsync の Sandbox エラーが出る
以下のようなエラーが発生した場合は、Build SettingsのUser Script Sandboxing
を No
に変更すると解決する。
Sandbox: rsync(58413) deny(1) file-write-create /Users/ch3cooh/Library/Developer/Xcode/DerivedData/SampleCocoaPodsKeys-cfrvgzlpnlcswcaspcgbzzumdzyd/Build/Products/Debug-iphonesimulator/SampleCocoaPodsKeys.app/Frameworks/Keys.framework/_CodeSignature
CI で Keychain が使えない
ローカルPCではKeychainにシークレットの値を保存した。CIではKeychainを使えない。CI環境では、シークレットの環境変数を設定することで、そちらの値を使ってくれるようになる。
まとめ
- Podfile の cocoapods‑keys へ Key 名だけを列挙する
pod install
時に Keychain へ安全に保存される- Swift からは
ProjectNameKeys().apiKey
の形式で参照できる
これでリポジトリへシークレットをコミットせずに済む。