APIキーなどの秘密情報をソース管理から守るための戦略は?


217

私は、ユーザーがTwitter、GoogleなどのOAuth資格情報を使用してログインできるようにするWebサイトに取り組んでいます。これを行うには、これらのさまざまなプロバイダーに登録し、所有している極秘APIキーを取得する必要がありますさまざまな身体部分からの誓約で保護する。キーがギャンクされると、パーツがヤンクされます。

APIキーは実行時に認証要求を実行するために使用されるため、ソースと共に移動する必要があります。私の場合、キーはアプリケーション内の構成ファイルまたはコード内に存在する必要があります。単一のマシンからビルドして公開する場合、それは問題ではありません。ただし、ソース管理をミックスに組み込むと、事態はさらに複雑になります。

私は安っぽい野郎なので、クラウド内のTFSやGitHubなどの無料のソース管理サービスを使用することを好みます。これにより、若干の難問が残ります。

APIキーがコード内にあり、コードが公開リポジトリで利用可能な場合、どうすれば体を傷つけずに保持できますか?

これを処理する方法はいくつか考えられますが、満足できるものはありません。

  • コードからすべての個人情報を削除し、展開後に編集することができます。これは実装するのが非常に苦痛であり(多くの方法を詳しく説明しません)、オプションではありません。
  • 暗号化できました。しかし、私はそれを解読しなければならないので、ソースを持っている人は誰でもそれを行う方法を見つけ出すことができました。無意味。
  • 私は個人的なソース管理にお金を払うことができました。LOL j / kはお金を使いますか?お願いします。
  • 言語機能を使用して、機密情報をソースの他の部分から分離し、ソース管理から保護することができます。これは私が今やっていることですが、誤ってシークレットファイルをチェックインすると簡単に失敗する可能性があります。

開発、デバッグ、展開を通じてスムーズに動作し、同様に確実に動作するプライベートを世界と共有しないことを保証する方法を本当に探しています(snapchatを除く)。これは完全に非現実的です。 それでは、現実的に何ができますか?

技術的な詳細:VS2012、C#4.5、ソース管理はTFサービスまたはGitHubのいずれかになります。現在、部分クラスを使用して、ソース管理に追加されない別の.csファイルで機密キーを分割します。GitHubには、.gitignoreを使用して部分的なクラスファイルがチェックインされないようにすることができるという利点があると思いますが、以前はそれを台無しにしました。「ああ、よくある問題、これがあなたのやり方です」を望んでいますが、私は「それができる限り吸わない」ために解決する必要があるかもしれません:/


6
APIキーを保持する構成ファイルがソース管理ディレクトリにないことを確認できます。これにより、最初にチェックインできなくなります。
デビッドセルゲイ

22
BitBucket.orgには、無制限のプライベートリポジトリがあります。自由。gitHubリポジトリインポーター(履歴を保持)
ロブファンデ

4
@Dainius開発者を知っているので、開発者を信頼していません。親密に。実際、私は少なくとも自分自身と親密です...いいえ、私はその1つをうそにさせます。しかし、私はそれがどれほど簡単に台無しになるのか、そしてその台無しの履歴をスクラブするのがどれほど難しいのかを知っています。
ウィル

15
@Dainius:はい。チームがコーディングするすべてのキャラクターを確認します。真剣に。私は選択肢がありません。私は目隠しをコーディングできません。少なくとも信頼できません。しかし、私は自分のチームだからです。私はチームの私です。1人の開発者がいて、それは私です。私は彼です。はい。私は彼がそれを正しくしない場合これを台無しにしようとしている人です。私。
ウィル

3
そもそもなぜキーをコードにコンパイルしようとしているのですか?通常、そのようなことを構成ファイルに入れます。
ドナルドフェローズ

回答:


128

コードに秘密情報を入れないでください。起動時にコードによって読み取られる構成ファイルに配置します。構成ファイルは、「工場出荷時のデフォルト」でない限り、バージョン管理の上に置いてはなりません。そして、個人情報を持ちません。

これをうまく行う方法については、バージョン管理と個人設定ファイルの質問も参照してください。


8
@RobertHarveyをバージョン管理に配置せず、必要に応じて無視ルールを追加します。ソフトウェアを使用するユーザーは、独自のAPIキーを使用して独自の構成ファイルを作成する必要があります。
フィリップ

10
ソフトウェアのディストリビューションをビルドして作成する場合、構成ファイルが付属していることをどのように確信していますか?適切なデフォルトのファイルがない限り、通常、ユーザーが構成ファイルを作成するプロセスを経ることを期待するのは合理的ではありません。
トーマスオーエンズ

4
さて、工場出荷時のデフォルトは1つの部分、「インストーラー」または「最初の実行ウィザード」
です-johannes

6
多くのユーザーが独自のインストールを持っている場合、独自のAPIキーを作成して使用するべきではありませんか?同じキーを使用した複数のサイト/インストールは、おそらく悪い考えです。インストールが1回だけの場合は、構成ファイルを使用するのはそれほど面倒ではありません。
マイクウェラー

10
@Will、実装の詳細の非実用性のためにこれを行うことができない場合、展開のための適切なツールを持っていないだけだと思います。コミットされていないシークレット構成ファイルを使用した展開は、完全に簡単です。私はC#ではなくRubyエコシステムに住んでいるので、具体的なアドバイスを提供することはできません。しかし、Rubyの人々は、自動展開にCapistranoを使用する傾向があります。C#には自動展開用のツールもあると確信しており、これによりプロセスが簡単になります。
ベン・リー

29

すべての秘密/保護キーをシステム環境変数として配置できます。設定ファイルは次のようになります。

private.key=#{systemEnvironment['PRIVATE_KEY']}

これがこれらのケースを処理する方法であり、コードには何も入りません。さまざまなプロパティファイルおよびプロファイルと組み合わせて非常にうまく機能します。環境ごとに異なるプロパティファイルを使用します。ローカル開発環境では、プロパティファイルに開発キーを配置して、ローカルセットアップを簡素化します。

private.key=A_DEVELOPMENT_LONG_KEY

ホスティングオプションで動作させることができれば、これは合理的なソリューションになります。環境変数が、公開後拭かれませんおそらく、いくつかのキー/値の設定のペア...されることはありません
ウィル

ライブ環境に出荷する前に、これらの環境変数をビルドサーバーに配置してはどうでしょうか。そうすれば、実稼働リソース/構成ファイルの準備が整います。
イオアニスツィカス

ビルドサーバーが開発マシンであるため、この情報が誤ってソース管理にチェックインされる可能性があることを心配しています。
ウィル

これに伴う問題は、サーバー上の誰でも環境が読み取り可能であることです。
JasonG 14

ユーザーのenvvarは、ユーザーまたはルートのみが読み取り可能です。(しかし、古代のLinuxとAIXはこれをしませんでした)
ニールマクギガン14年

27

Pure Gitの方法

  • .gitignore プライベートデータを含むファイル
  • ここであなたが置き換え、ローカルブランチを使用しTEMPLATEDATA
  • 汚れ/クリーンフィルターを使用します。(ローカル)フィルターのスクリプトは双方向の置換を実行しますTEMPLATE<->DATA

マーキュリアルウェイ

  • ダミーコードの上にあるMQ-patch(es)は、次のものに置き換えTEMPLATEられますDATA(変更セットはパブリック、パッチはプライベート)
  • 特別に設計されたキーワードによるキーワード拡張(作業ディレクトリでのみ拡張されます

SCMに依存しない方法

  • ビルド/デプロイプロセスの一部としてキーワードを置換する

うーん... gitのアドバイスは良いです、そしてあなたの不可知論的なアドバイスは私に良いアイデアを与えてくれます...ビルドイベントを使用してファイルを公開プロセスに導入し、その後削除して、そうしないことを保証するのに役立ちますソース管理に偶然を追加することが...
ウィル

7
いいえ、いいえ、もう一度-いいえ!ファイルを無視することは、ビルドプロセスなどに非常に具体的なカスタマイズを追加するのに適していますが、セキュリティで保護されたデータの格納には決して使用しないでください。たとえあなたがそれを無視しているとしても、リポジトリに安全なデータを保存しないでください。
shabunc

11
@shabunc-RTFM!リポジトリに保存されていない無視れたファイル
レイジーバジャー

9
@LazyBadger-私はそれが無視されることをよく知っています。また、レポにいることで、誰かが間違ってレポに追加する可能性が常にあることも知っています。いくつかの外部設定パスがはるかに優れています。
-shabunc

4
@shabunc-構成をSCMパスから除外することの良い点。これが、たとえば、Postgresでパスワードをファイルに入れることでパスワードチェックをバイパスできる理由です。ただし、パスワードファイルは〜/ .pgpassに配置する必要があります。これは、おそらくソース管理にチェックインするのに非常に便利な場所ではありません。彼らは、自動化のために、彼らはあなたに銃を与えるために持っているが、彼らはそれを足で自分自身を撮影からあなたを保つために努力し、知っている...
スティーブ・ミジリー

14

暗号化されたファイルに秘密を入れ、それをコミットします。パスフレーズは、システムの起動時に提供されるか、コミットしない小さなファイルに保存されます。Emacsがこれらの暗号化されたファイルを元気に管理してくれるのは素晴らしいことです。たとえば、emacs initファイルには次が含まれます:(load "secrets.el.gpg")、これは機能します-エディターを起動すると、これらのまれな場所でパスワードの入力を求められます。誰かが暗号化を破る心配はありません。


3
これは素晴らしい解決策です-あなたがこれ以上の賛成票を持っていないことに驚いています。私は、米国で連邦政府によって規制されている学生データを扱う会社で働いているので、彼らは資格情報と秘密に特に注意する必要があります。彼らは大企業でもあるため、資格情報にSCMを使用する必要があります。これにより、ITがengrを作成した後にそれらを検索/管理できます。あなたのソリューションはまさに彼らがすることです。これらには、dev / staging / prod / etcの復号化キーを保持する復号化キーファイルがあります(それぞれに1つのファイル)。次に、すべての秘密が暗号化され、ファイルにチェックインされます。復号化ファイルは、各環境で取得するために使用されます。
スティーブミッドリー

7
まあ、ある意味で、シークレット(この場合はAPIキー)を暗号化しても、問題はシークレットデータコミットないことから、パスフレーズ(現在はシークレットデータになるをコミットないことに変わります。しかし、もちろん、システムの起動時にそれを要求するのは良い選択肢です。
siegi

私はこの解決策が好きです。コミットする暗号化されたファイルの種類は、KeePassファイルである可能性があります。notes.envファイルの内容を格納するフィールドを使用して、各環境のエントリがあります。数か月前、私はkeepassファイルを読み取りnotes、エントリのフィールドを使用して.envファイルを作成できるツールを作成しました。require('switchenv').env()Node.jsプログラムの先頭でNODE_ENVなどに一致するエントリに基づいてprocess.env変数を作成できるように、機能を追加することを考えています。-> github.com/christiaanwesterbeek/switchenv
Christiaan Westerbeek

14

これは非常にAndroid / Gradle固有ですが、にあるグローバルgradle.propertiesファイルでキーを定義できますuser home/.gradle/。buildTypeまたはフレーバーに応じて異なるプロパティ(開発用APIとリリース用API)を使用できるため、これも便利です。

gradle.properties

MY_PRIVATE_API_KEY=12356abcefg

build.gradle

buildTypes {
        debug{
            buildConfigField("String", "GOOGLE_VERIFICATION_API_KEY", "\"" + MY_PRIVATE_API_KEY +"\"")
            minifyEnabled false
            applicationIdSuffix ".debug"
            }
        }

このように参照するコード

String myAPI = BuildConfig.GOOGLE_VERIFICATION_API_KEY;

BuildConfigは、あなたのAPKにとてもシンプルなリバースエンジニアリングは、あなたがBuildConfigに入れ、すべてのこれらのキーと秘密明らかになり、対応するソースファイルに変換
ドミトリLivotov

1
確かに、有効なポイント。しかし、質問はバイナリではなくソースコードからAPIキーを排除する方法についてでした。
スコッティヤブ

11

そのキーをアプリケーションと一緒に配布したり、ソースコードリポジトリに保存したりすることは想定していません。この質問はその方法を尋ねているものであり、それは通常行われていることではありません。

モバイルWebアプリケーション

Android / iPhoneの場合、デバイスはアプリが最初に実行されるときに独自のWebサービスからKEYを要求する必要があります。その後、キーは安全な場所に保存されます。発行者によってキーが変更または取り消された場合。Webサービスは新しいキーを公開できます。

ホストされたWebアプリケーション

ソフトウェアのライセンスを使用しているお客様は、ソフトウェアを最初に構成するときにキーを手動で入力する必要があります。全員に同じキー、異なるキーを与えることも、独自のキーを取得することもできます。

公開されたソースコード

ソースコードはパブリックリポジトリに保存しますが、KEYには保存しません。ファイルの設定で、行を追加します* ここにキーを配置します *。開発者がソースコードを使用する場合、sample.cfgファイルのコピーを作成し、独自のキーを追加します。

config.cfg開発または本番用のファイルをリポジトリに保持しません。


4
この質問は、それを行う方法を尋ねています。いいえ、絶対に行いません。実際には、これらのキーはコードで使用する必要があるため、コードでアクセスする必要があり、通常はコードまたは構成ファイルを介してアクセスすることを意味します。ソースに一緒にいない場合、少なくとも近くにあり、誤ってソース。残念ながら、ホストされているWebアプリは無意味です。(仮想)Facebookアカウントを介してStackOverflowにログインするために、APIキーを申請する必要はありませんでした。 ここでの場所のキーは Qに記載されているようDEV->パブの環境では動作しません大規模な単純化である
ウィル

他の多くの人がそうであるように、私は質問に正しく答えました。それらのいずれかを受け入れていないという事実は、これらのキーの使用方法を理解していないことを意味します。
Reactgular

7
次に、キー発行Webサービスをどのように保護しますか?別のキーを使用していますか?
ジャンゲチャン

同上は@JianggeZhangが言った-これは危険なアドバイスです
デヴィッド・K.ヘス

5

サーバーごとに変化する秘密事項に環境変数を使用します。

http://en.wikipedia.org/wiki/Environment_variable

それらの使用方法は言語に依存します。


3
あいまいさによるセキュリティは、多くの人にとって推奨されるアプローチではありません。あなたの答えをより明確にするために詳しく説明してくれませんか?

2
これは不明瞭ではありません。環境変数は追加したユーザーのみが利用できるため、すべての資格情報はアプリが実行しているユーザーコンテキストと同じ保護を持ちます。環境変数の概念を含むように回答を更新しました。それはより明確ですか?
フィリペジュスティ

4

これは、ある時点で誰もが問題を抱えている問題だと思います。

私が使用したワークフローは次のとおりです。ひねりを加えた.gitignoreを使用します。

  1. すべての構成ファイルは特別なフォルダーに配置されます(w /サンプル構成ファイル-オプション)
  2. すべての構成ファイルは.gitignoreに含まれているため、公開されません
  3. プライベートボックスにgitoliteサーバー(またはお気に入りのgitサーバー)をセットアップする
  4. プライベートサーバー内のすべての構成ファイルを含むリポジトリを追加します
  5. メインリポジトリの特別なフォルダーに構成ファイルをコピーするスクリプトを追加します(オプション)

これで、構成リポジトリを任意の開発および展開システムに複製できます。スクリプトを実行して、ファイルを正しいフォルダーにコピーするだけで完了です。

まだすべてのGitHubキャンディを入手し、コードを世界と共有しています。機密データはメインリポジトリに存在しないため、公開されません。これらは、まだ展開システムからのプルとコピーにすぎません。

私はプライベートgitサーバーに15ドル/年のボックスを使用していますが、安いスケートの要件ごとに自宅で1つセットアップすることもできます;-)

PS:gitサブモジュール(http://git-scm.com/docs/git-submodule)を使用することもできますが、私はいつもコマンドを忘れてしまいますので、ルールは早くて汚いです!


2

暗号化を使用しますが、起動時にマスターキーを、コンソールでパスワードとして、プロセスのユーザーのみが読み取れるファイルに、またはMac OSキーチェーンやWindowsキーストアなどのシステム提供のキーストアから提供します。

継続的に配信するには、さまざまなキーをどこかに記録する必要があります。構成はコードと区別する必要がありますが、リビジョン管理下に置くことは非常に理にかなっています。


1

3つの戦略、まだ言及されていない(?)

チェックイン時またはVCS事前チェックインフック内

  • エントロピーの高い文字列の検索、例-秘密の検出
  • よく知られているAPIキーパターンの正規表現検索。AWSのAKIA *キーは一例であり、git-secretsはそれに基づいたツールの1つです。また、定数が割り当てられた「パスワード」などの変数名。
  • 既知の秘密を検索する-あなたはあなたの秘密を知っている、それらのテキストを検索します。または、ツールを使用して、この概念実証を作成しました

すでに述べた戦略

  • ソースツリーの外部のファイルに保存する
  • ソースツリーにあるが、VCSに無視するように指示する
  • 環境変数は、ソースツリーの外部にデータを保存するバリエーションです
  • 開発者に貴重な秘密を明かさないでください

0

個人情報をソース管理から遠ざけます。配布用にロードされていないデフォルトを作成し、VCSに実際のデフォルトを無視させます。インストールプロセス(手動、構成/ビルド、またはウィザード)で、新しいファイルの作成と入力を処理する必要があります。必要に応じて、ファイルのアクセス許可を変更し、必要なユーザー(Webサーバー?)のみがファイルを読み取れるようにします。

利点:

  • 開発エンティティ==生産エンティティを想定していません
  • すべての共同編集者/コードレビュアーが信頼できるとは限りません
  • バージョン管理の対象から外すことで、簡単なミスを防ぎます
  • QA /ビルドのカスタム構成でインストールを簡単に自動化

すでにこれを行っており、誤ってチェックインしている場合は、プロジェクトのに追加してください.gitignore。これにより、再度行うことができなくなります。

プライベートリポジトリを提供する無料のGitホストたくさんあります。資格情報のバージョン管理は絶対にしないでくださいが、安価でプライベートリポジトリも使用できます。^ _ ^


-2

OAuthキーを生データとしてどこかに保存する代わりに、何らかの暗号化アルゴリズムで文字列を実行し、ソルトハッシュとして保存しませんか?次に、構成ファイルを使用して実行時に復元します。そうすれば、キーは開発ボックスに保存されているかサーバー自体に保存されているかにかかわらず、どこにも保存されません。

サーバーがリクエストごとにソルトおよびハッシュされた新しいAPIキーを自動的に生成するようにAPIを作成することもできます。この方法では、チームでさえOAuthソースを見ることができません。

編集:おそらくスタンフォードJavascript Crypto Libraryを試してみてください。かなり安全な対称暗号化/復号化が可能です。


1
ハッシュは通常、一方向のスクランブルです。あなたが提案するように行う対称暗号化アルゴリズムがあります。

3
ハッシュを(簡単に)暗号化解除することはできません。これがハッシュのポイントです。これは、MEが他の誰かのAPIを使用して、MEに秘密鍵を割り当てるためのものです。私のハッシングにより、(貧弱なアルゴリズムを選択して毎回クラックしない限り)APIを使用できなくなります。
ウィル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.