LoginSignup
40
22

More than 1 year has passed since last update.

iOSアプリのリポジトリ内の機密情報(API Key/Secrets etc.)のハードコーディングをなくす [Arkana]

Last updated at Posted at 2022-07-26

はじめに

iOSアプリにおいて、サードパーティSDKなどから提供されるAPI KeyやSecretsなど、機密情報をどのようにセキュアに管理するといいでしょうか。
単純に実装するとハードコーディングや、設定ファイルなどに記述し、リポジトリにpushするようになってしまうと思いますが、セキュリティの観点からはアプリと同じリポジトリにpushするのはよろしくありません。

例えばリポジトリに閲覧権限を持っている場合、API Keyを使ってAPIサービスの実行ができてしまったり、CIツールなどでソースコードを外部からアクセスさせている場合、CIツールへ不正アクセスされ漏洩する可能性や、ipaファイルからリバースエンジニアリングツールを使って文字列を抽出される可能性もあります。
そのため、例えGitHubのプライベートリポジトリだったとしても、機密情報の扱い方を考える必要性があります。

注意
この手法は、あくまで難読化やリポジトリから除外することで、漏洩リスクを下げる方法で、完全にセキュアというわけではありません。
完全にセキュアにするためには、そもそもアプリには埋め込まないことです。

cocoapods-keys

これまでiOSアプリでは、cocoapods-keysが使われることが多かったと思います。

cocoapods-keysはCocoapodsのプラグインとしてGemで作られています。

しかしながら、昨今のiOSアプリではSwift Package Managerの登場により、CocoaPodsからなるべく依存を減らそうという流れが強くなっています。

Arkana

そこで、2022/6に新たな代替えライブラリとして「Arkana(アルカナ)」が登場しています。

image.png

Arkanaの特徴

  • Gem
  • Swift Package Manager/CocoaPods対応
  • .envファイルからSwiftコード自動生成
  • 将来的にAndroidも対応予定?(2022/7時点ではまだAndroid未対応)

使い方

インストール

通常のGemインストールになります。READMEにもbundlerを使うことが推奨されていますので、以降もbundlerを使用した前提で記載します。

Gemfile
gem 'arkana', '~> 1.1.1'
$ bundle install

ちなみにRubyは2.7.0以上が対応となっています。

.arkana.yml作成

次に、.arkana.ymlを作成します。template.ymlが用意されていますので、それに従ってルートディレクトリに配置します。

日本語訳を載せておきます。

import_name: 'ArkanaKeys' # オプション。インポートするフレームワークの名前。デフォルトはArkanaKeys。
namespace: 'Keys' # オプション。コードベース内のシークレットにアクセスするために使用する名前空間。デフォルトは ArkanaKeys です。
pod_name: 'ArkanaKeys' # オプション。Podfileで宣言するPodの名前。デフォルトはArkanaKeysです。
result_path: 'dependencies' # オプション。この設定ファイルのパスに関連する、生成されたコードのデスティネーションパス。デフォルトはArkanaKeys。
flavors: # オプション。 Flavorsは、環境変数から読み込む際に、すべてのシークレットに接頭辞として追加されるキーワードです。これは、例えばホワイトレーベルのプロジェクトで便利です。詳しくはREADMEの「使い方」のセクションをご覧ください。
  - FrostedFlakes
  - FrootLoops
swift_declaration_strategy: let # オプション。lazy var, var, letから選ぶ。デフォルトはlet。
should_generate_unit_tests: true # オプション。true, falseから選ぶ。デフォルトはtrue。
package_manager: cocoapods # オプション。spm, cocoapodsから選ぶ. 両方使う場合は、cocoapodsを宣言してください。デフォルトはspmです。
environments: # オプション。環境間で異なるキーがある場合 (例: debug/staging/prod) にsecret keyを生成するために使用される環境のリストです。デフォルトは空です。
  - Debug
  - Release
global_secrets: # オプション。どの環境を構築するかに関係なく同じであるsecretのリスト。デフォルトは空です。
  - MySecretAPIKey
  - AppStoreAppID
  - BackendDomain
environment_secrets: # オプション。このリストの各エントリに対して、envの名前に対応するサフィックスを付加して1つのsecretを作成します。デフォルトは空です。
  - MyServiceAPIKey # MyServiceAPIKeyDebug と MyServiceAPIKeyRelease の環境変数を検索します (フレーバーが宣言されていない場合)。

importの名前なども細かく指定できるのは面白いなと思います。とはいえ特にこだわりがなければ、global_secretsだけ設定でも十分だと思いました。
environmentsenvironment_secretsでうまく分けられればそれはそれでいいと思いますが、サービスによって2種類があるものと、3種類以上の環境で分けているものなどバラバラになる可能性があると思いますので、それにより冗長な設定をするよりはシンプルにglobal_secretsだけを使った方がいいかもしれません。

.env作成

次に、.envファイルを作成します。

.env
MySecretAPIKey=hogehoge
MySecretAPIKey2=hogehogehoge

.envファイルは、key=valueの形式でテキストファイルで作成します。
この.envファイルをアプリのリポジトリとは別に管理する必要があります。もし社内ホスティングのgitサーバーがあれば、そちらに保管すると良いでしょう。

コード生成

コードの生成はarkanaコマンドを使用します。

$ bundle exec arkana -c /path/to/your/.arkana.yml -e /path/to/your/.env

-c.arkana.ymlのpath、-e.envのpathで、省略すると、それぞれルートディレクトリから探されます。

実行すると、Swiftコードが生成されます。

image.png

keyはバイトコードに難読化されたコードで生成され、実行の度に変更されます。

Package追加

package_managerをデフォルトのspmにしていれば、Swift Packageが同ディレクトリに生成されますので、アプリにlocal packageとして追加します。
ArkanaKeysArkanaKeysInterfacesの2つのPackageが生成されますが、アプリからはArkanaKeysだけを参照として追加すればOKです。

Xcode > File > Add Packages...
Pasted_Image_2022_07_25_21_48.png

Swiftコードからのアクセス

Swiftコードでアクセスするには、global_secretsを設定するとGlobal()でstructを生成し、key名でアクセスできます。

import ArkanaKeys

let mySecretAPIKey = ArkanaKeys.Global().mySecretAPIKey

git監視対象から除外

関連ファイルは.gitignoreに記載して、git監視対象から除外しましょう。

.gitignore
.env
ArkanaKeys/*

Makefileでコマンドを登録

チーム開発する場合は、.envファイルとArkanaの実行を自動化すると良いでしょう。
Makefileを作り、以下のようなコマンドを登録しておくと良いと思います。

Makefile
# make env
# - 社内ホスティングサーバーから`.env`ファイルをcloneする
# - `.env`ファイルをルートディレクトリにコピー
# - cloneしたディレクトリを削除
env:
	git clone git@my-internalserver.example.com/my-secrets.git
	cp ./my-secrets/.env ./.env
	rm -rf ./my-secrets

# make secrets
# - arkana実行
secrets:
	bundle exec arkana -c ./.arkana.yml -e ./.env

Bitrise上で.envを生成

次に、CIサービスにBitriseを使用している場合に、.envを生成します。GitHub Actionsでも同様の設定でできると思います。

BitriseのWorkflowにはSecretsが登録できます。
image.png

ここに、base64でエンコードした.envファイルの中身を設定します。

$ base64 .env | pbcopy

pbcopyでクリップボードにコピーできますので、ここではENV_FILEとkey名を設定します。
次に、

$ echo $ENV_FILE | base64 -d > .env

のscriptで環境変数からbase64でデコードして、.envファイルを生成して書き込みます。

bitrise.yml
- script@1:
    title: generate .env file
    inputs:
    - content: |-
      #!/usr/bin/env bash
      # fail if any commands fails
      set -e
      # debug log
      set -x
      
      echo $ENV_FILE | base64 -d > .env

このscriptステップをarkanaコマンド実行前に追加すれば、CI上でもビルドすることができます。

さいごに

今回はiOSアプリにおける機密情報の取り扱いと、新しいライブラリArkanaをご紹介させて頂きました。
お役に立てば幸いです。

40
22
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40
22