sh1’s diary

プログラミング、読んだ本、資格試験、ゲームとか私を記録するところ

ローカルアプリでも API キーの取り扱いに注意する

f:id:shikaku_sh:20211127154642p:plain:w200

ローカルのサンプルプログラムでも、GitHub にコミットするときなんかに API キーを使用していると困ることがあります。GitHub にサンプルコードをあげるときは、当然 API キーを隠します。で、API を使用する(実際に動作する)実行コードに書き換えるたびに Git の変更要素としてコミットのリストに挙げられてしまうことになります。あまり好ましい状態ではないですね。

書き換えが面倒……ではなくて、そもそも危険なんで止めたいわけです。(Private なリポジトリでも GitHub に管理してもらうことではなさそう)

というわけで、どうするべきなのか調べました。

ローカルのアプリ(サンプルコードを含む)もコードは GitHub に上げる時代になったけど、ネット上のサンプルコードは(特にローカルアプリにおいて)API キーの取り扱いの注意が抜けがちなんで、注意しようという記事です。

基本的な対策方針

Google Cloud - API キーの使用」を確認すると次の説明があります。

  • API キーをコードに直接埋め込まないでください。コードに埋め込まれた API キーは、誤って公開されてしまう可能性があります。たとえば、共有するコードからキーを削除し忘れた場合などです。API キーはアプリケーションに埋め込む代わりに、アプリケーションのソースツリー外部にある環境変数やファイル内に保存します。
  • アプリケーションのソースツリー内のファイルに API キーを保存しないでください。API キーをファイルに保存する場合は、キーがソースコード制御システム内に保存されないよう、ファイルをアプリケーションのソースツリー外部に保持するようにします。これは特に、GitHub のような公共のソースコード管理システムを使用する場合に重要です。
  • 不要な API キーを削除して、攻撃を受けるリスクを最小限に抑えます。
  • 公開する前に、コードを確認します。コードを公開する前に、コードに API キーやその他のプライベート情報が含まれていないことを確認してください。

抜粋しています。

そんなわけで、サンプルコードとは言っても、平文をコードに直接埋め込んでいるとサンプルの本質ではない、とは言え誤って公開されてしまう恐れがあるため、サンプルを作る側も見る側もいいことなさそう。(平文コードを絶対真似るべきじゃない)

パッと見たわかりやすさはいいけど、リスクが大きすぎる。リスクリターンが見合わないというわけです。

もしデベロッパ秘密鍵GitHub上に過って公開したら、悪意のあるハッカーがすぐに飛びついてくるでしょう。彼らはGitHub上のリポジトリに公開されているAWS秘密鍵を発見する仕組みをすでに自動化していて、これらの秘密鍵を使ってEC2インスタンスをスピンアップし、ビットコイン採掘をしてしまいます。

対策1(環境変数

ともかく、「ソースツリー外部に保持するようにします」ということが大切です。

一番シンプルな回答になるのは、環境変数API キーを含めるケースです。

f:id:shikaku_sh:20211127154845p:plain:w400

var key = Environment.GetEnvironmentVariable("RESAS_API", EnvironmentVariableTarget.User);

ローカルアプリだと定番の方法のひとつだと思います。API キーを間違って GitHub なんかにアップロードしづらくなります。

正直サンプルコードを掲載する例なら、これくらい(の冗長コード)なら気にならない気がします。一言、API キーは環境変数に格納しました、でいいので。

対策2(DotNetEnv)

f:id:shikaku_sh:20211127155408p:plain:w400
NuGet からインストール

ファイルに API のキーを入れて管理する場合は Json 形式も候補ですが、DotNetEnv もよいと思います。DotNetEnv は .env 設定ファイルの読み込みをサポートしています。

f:id:shikaku_sh:20211127155441p:plain:w200
出力フォルダーにコピーします

.env ファイルは、ファイル名をあまりつけないです。.env ファイルの書き方はこんな感じ:

RESAS_API = "abcDEF123456 (API キー)"
OTHER_PARAM = 12345

とてもシンプルに記述して、値を読み込むことができる特徴を持ちます。なので、.iniJson 形式とさして変わらないといえば、そのとおりですね。

GitHub にアップロードしないように .env ファイルを除外する設定を忘れたらいけない。.gitignore ファイルに次を追記します:

# Ignore files
.env

値を読み込むコードは次のとおり:

DotNetEnv.Env.Load(".env");
var key = DotNetEnv.Env.GetString("RESAS_API");

.env ファイルは慣例的に除外ファイル扱いをしますので、その点で僅かにですがこの手法がよいのかと思いました。

補足

AWS では git-secrets を利用することで、特定のキー情報と思われる文字列を含むファイルは、アップロードできない、エラーにする対策があります。

git-secrets は、aws の場合に簡単設定することができますが、細かく自分で設定を作れば応用することができると思います。(が、汎用化してチームに転用する例はあまり見たことがないです)

より良い対策なんだと思うのですが、現状はそこまで API キーの流出でとんでもない企業被害が発生したというケースよりも、個人で失敗して 100 万円前後の被害というケースが(見た目には)多いように思いました。なので、対策が個人レベルな感じになるのも否めない気がします。

参考