138

バージョン管理システムで、開発サーバーと実稼働サーバーのホスト名やポートなどの重要な設定を保持しています。しかし、秘密鍵 (秘密鍵やデータベースのパスワードなど) を VCS リポジトリに保管するのは悪い習慣であることはわかっています。

しかし、パスワードは、他の設定と同様に、バージョン管理する必要があるようです。では、パスワードのバージョン管理を維持する適切な方法何でしょうか?

シークレットを独自の「シークレット設定」ファイルに保持し、そのファイルを暗号化してバージョン管理する必要があると思います。しかし、どのような技術ですか?そして、これを適切に行う方法は?それを完全に行うためのより良い方法はありますか?


私は一般的に質問しますが、私の特定の例では、gitgithubを使用してDjango/Pythonサイトの秘密鍵とパスワードを保存したいと考えています。

また、理想的なソリューションは、git でプッシュ/プルするときに何か魔法のようなことをするでしょう。


編集: わかりやすくするために、プロダクションシークレットをどこに保存するかについて尋ねています。

4

17 に答える 17

101

ファイルをバージョン管理で維持しながら、機密設定ファイルを暗号化したいというのはまさに正しいことです。あなたが言及したように、最良の解決策は、Gitが特定の機密ファイルをプッシュするときに透過的に暗号化し、ローカルで(つまり、証明書を持つ任意のマシンで)設定ファイルを使用できるようにすることですが、GitまたはDropboxまたは誰でもファイルを VC に保存しても、情報を平文で読み取ることはできません。

プッシュ/プル中の透過的な暗号化/復号化に関するチュートリアル

この gist https://gist.github.com/873637は、Git の smudge/clean フィルター ドライバーを openssl で使用して、プッシュされたファイルを透過的に暗号化する方法に関するチュートリアルを示しています。初期設定を行うだけです。

仕組みのまとめ

基本的に、.gitencrypt3 つの bash スクリプトを含むフォルダーを作成します。

clean_filter_openssl 
smudge_filter_openssl 
diff_filter_openssl 

これらは、復号化、暗号化、および Git diff のサポートのために Git によって使用されます。マスター パスフレーズとソルト (修正済み!) はこれらのスクリプト内で定義されており、.gitencrypt が実際にプッシュされないようにする必要があります。clean_filter_opensslスクリプト例:

#!/bin/bash

SALT_FIXED=<your-salt> # 24 or less hex characters
PASS_FIXED=<your-passphrase>

openssl enc -base64 -aes-256-ecb -S $SALT_FIXED -k $PASS_FIXED

smudge_filter_open_sslと についても同様ですdiff_filter_oepnssl。要点を参照してください。

機密情報を含むリポジトリには、ローカル マシンに存在する .gitencrypt ディレクトリ (Git がプロジェクトを透過的に暗号化/復号化するために必要なすべてを含む) を参照する .gitattribute ファイル (暗号化されておらず、リポジトリに含まれる) が必要です。

.gitattributeコンテンツ:

* filter=openssl diff=openssl
[merge]
    renormalize = true

.git/config最後に、次のコンテンツをファイルに追加する必要もあります

[filter "openssl"]
    smudge = ~/.gitencrypt/smudge_filter_openssl
    clean = ~/.gitencrypt/clean_filter_openssl
[diff "openssl"]
    textconv = ~/.gitencrypt/diff_filter_openssl

これで、機密情報を含むリポジトリをリモート リポジトリにプッシュすると、ファイルが透過的に暗号化されます。.gitencrypt ディレクトリ (パスフレーズを含む) を持つローカル マシンからプルすると、ファイルは透過的に復号化されます。

ノート

このチュートリアルでは、機密設定ファイルのみを暗号化する方法については説明していないことに注意してください。これにより、リモート VC ホストにプッシュされるリポジトリ全体が透過的に暗号化され、リポジトリ全体が復号化されるため、完全にローカルで復号化されます。必要な動作を実現するために、1 つまたは複数のプロジェクトの機密ファイルを 1 つのsensitive_settings_repo に配置できます。機密ファイルを同じリポジトリに置く必要がある場合は、この透過的な暗号化技術が Git サブモジュールhttp://git-scm.com/book/en/Git-Tools-Submodulesでどのように機能するかを調べることができます。

攻撃者が多くの暗号化されたリポジトリ/ファイルにアクセスできる場合、固定パスフレーズを使用すると、理論的にはブルート フォース脆弱性につながる可能性があります。IMO、これの可能性は非常に低いです。このチュートリアルの最後にあるメモに記載されているように、固定パスフレーズを使用しないと、異なるマシン上にリポジトリのローカル バージョンが作成され、変更が発生したことが常に「git status」で示されます。

于 2012-07-26T22:31:55.373 に答える
54

Herokuは、設定と秘密鍵に環境変数を使用することを推奨しています。

このような構成変数を処理するための従来のアプローチは、それらをソースの下 (何らかのプロパティ ファイル) に配置することです。これはエラーが発生しやすいプロセスであり、アプリ固有の構成で個別の (およびプライベートな) ブランチを維持する必要があることが多いオープン ソース アプリの場合は特に複雑です。

より良い解決策は、環境変数を使用し、キーをコードから除外することです。従来のホストまたはローカルで作業している場合は、bashrc に環境変数を設定できます。Heroku では、構成変数を使用します。

Foreman と.envファイルにより、Heroku は環境変数をエクスポート、インポート、同期するためのうらやましいツールチェーンを提供します。


個人的には、秘密鍵をコードと一緒に保存するのは間違っていると思います。キーはコードの外部サービス用であるため、ソース管理とは根本的に矛盾しています。1 つのメリットは、開発者が HEAD をクローンして、セットアップなしでアプリケーションを実行できることです。ただし、開発者がコードの履歴リビジョンをチェックアウトするとします。彼らのコピーには昨年のデータベース パスワードが含まれているため、アプリケーションは今日のデータベースに対して失敗します。

上記の Heroku メソッドを使用すると、開発者は昨年のアプリをチェックアウトし、現在のキーで構成して、現在のデータベースに対して正常に実行できます。

于 2012-07-26T10:33:19.997 に答える
17

私の意見では、最もクリーンな方法は環境変数を使用することです。たとえば、 .distファイルを扱う必要はなく、運用環境のプロジェクトの状態はローカル マシンの状態と同じになります。

The Twelve-Factor Appの構成の章を読むことをお勧めします。興味があれば、他の章も読んでください。

于 2012-07-20T09:14:07.543 に答える
10

オプションは、プロジェクトにバインドされた資格情報を暗号化されたコンテナー (TrueCrypt または Keepass) に入れてプッシュすることです。

以下の私のコメントからの回答として更新します。

興味深い質問です。私はちょうどこれを見つけました: github.com/shadowhand/git-encrypt自動暗号化に非常に有望に見えます

于 2012-07-20T08:14:23.957 に答える
10

そのために構成ファイルを使用し、それらをバージョン管理しないことをお勧めします。

ただし、ファイルの例をバージョン管理することはできます。

開発設定の共有に問題はありません。定義上、貴重なデータを含むべきではありません。

于 2012-07-20T08:20:40.547 に答える
7

BlackBoxは StackExchange によって最近リリースされました。私はまだ使用していませんが、問題に正確に対処し、この質問で要求された機能をサポートしているようです。

https://github.com/StackExchange/blackboxの説明から:

シークレットを VCS リポジトリ (つまり、Git または Mercurial) に安全に保存します。これらのコマンドを使用すると、リポジトリ内の特定のファイルを簡単に GPG 暗号化して、リポジトリ内で「保存時に暗号化」することができます。ただし、スクリプトを使用すると、それらを表示または編集する必要があるときに簡単に復号化し、本番環境で使用するために復号化できます。

于 2014-09-03T21:47:39.503 に答える
6

私は一般的に質問をしますが、私の特定の例では、gitとgithubを使用してDjango/Pythonサイトの秘密鍵とパスワードを保存したいと思います。

いいえ、それがあなたのプライベートリポジトリであり、それを共有するつもりがない場合でも、しないでください。

local_settings.pyを作成してVCS無視に配置し、settings.pyで次のようにする必要があります。

from local_settings import DATABASES, SECRET_KEY
DATABASES = DATABASES

SECRET_KEY = SECRET_KEY

あなたの秘密の設定がそのように用途が広いなら、私はあなたが何か間違ったことをしていると言いたいです

于 2012-07-20T10:32:10.873 に答える
4

編集:以前のパスワードのバージョンを追跡したいと思います。たとえば、パスワードの再利用を防ぐスクリプトなどです。

GnuPGは最善の方法だと思います。これは、クラウドサービスに保存されているリポジトリコンテンツを暗号化するために、1つのgit関連プロジェクト(git-annex)ですでに使用されています。GnuPG(gnu pgp)は、非常に強力なキーベースの暗号化を提供します。

  1. ローカルマシンにキーを保持します。
  2. 無視されたファイルに「mypassword」を追加します。
  3. pre-commitフックで、mypasswordファイルをgitによって追跡されるmypassword.gpgファイルに暗号化し、それをcommitに追加します。
  4. マージ後のフックでは、mypassword.gpgをmypasswordに復号化するだけです。

'mypassword'ファイルが変更されていない場合、暗号化すると同じ暗号文になり、インデックスに追加されません(冗長性なし)。mypasswordを少し変更すると、暗号文が根本的に異なり、ステージング領域のmypassword.gpgはリポジトリ内のものと大きく異なるため、コミットに追加されます。攻撃者があなたのgpgキーを入手したとしても、攻撃者はパスワードをブルートフォースする必要があります。攻撃者が暗号文を使用してリモートリポジトリにアクセスした場合、暗号文の束を比較できますが、その数は無視できない利点を与えるのに十分ではありません。

後で、.gitattributesを使用して、パスワードのgitdiffを終了するためのオンザフライ復号化を提供できます。

また、パスワードの種類などに応じて個別のキーを使用することもできます。

于 2012-07-20T09:23:43.497 に答える
3

構成をオーバーライドする方法を提供する

これは、チェックインする構成の一連の正常なデフォルトを管理するための最良の方法です。構成が完全である必要はなく、ホスト名や資格情報などを含める必要もありません。デフォルトの構成をオーバーライドするには、いくつかの方法があります。

環境変数(他の人がすでに述べたように)は、それを行う1つの方法です。

最善の方法は、デフォルトの構成値を上書きする外部構成ファイルを探すことです。これにより、Chef、Puppet、Cfengine などの構成管理システムを介して外部構成を管理できます。構成管理は、コードベースとは別に構成を管理するための標準的な答えであるため、単一のホストまたはホストのグループで構成を更新するためにリリースを行う必要はありません。

参考までに:資格情報を暗号化することは、特にリソースが限られている場所では、常にベスト プラクティスとは限りません。クレデンシャルを暗号化しても、追加のリスク軽減は得られず、不要な複雑さのレイヤーが追加されるだけの場合があります。決定を下す前に、必ず適切な分析を行ってください。

于 2012-07-27T14:32:15.820 に答える
3

通常、パスワードを構成ファイルとして分離します。そしてそれらを分散させます。

/yourapp
    main.py
    default.cfg.dist

そして、実行すると、コピーしたmain.pyパスワードに実際のパスワードを入力します。default.cfg

ps。git または hg を使用する場合。*.cfg作成するファイルを無視する.gitignoreか、.hgignore

于 2012-07-20T08:38:58.477 に答える
2

シークレットに VCS が必要な場合は、少なくとも実際のコードとは別の 2 番目のリポジトリに保管する必要があります。そのため、チーム メンバーにソース コード リポジトリへのアクセス権を与えることができますが、資格情報は表示されません。さらに、このリポジトリを別の場所 (例: github ではなく、暗号化されたファイルシステムを使用する独自のサーバー) にホストし、本番システムにチェックアウトするには、git-submodule のようなものを使用できます。

于 2012-07-30T09:50:23.690 に答える
2

たとえばGPGを使用して、パスワードファイルを暗号化します。ローカル マシンとサーバーにキーを追加します。ファイルを復号化し、リポジトリ フォルダーの外に置きます。

ホームフォルダーにある passwords.conf を使用します。展開するたびに、このファイルが更新されます。

于 2012-07-26T09:41:22.227 に答える
2

いいえ、秘密鍵とパスワードはリビジョン管理の対象外です。本番環境で使用される機密性の高いサービス資格情報を知っていることで、リポジトリへの読み取りアクセス権を持つすべての人に負担をかける理由はありません。

Django 1.4 から、オブジェクトproject.wsgiを定義するモジュールがDjango プロジェクトに同梱されるようになりました。これは、サイト固有の構成を含む設定モジュールの使用を強制するのに最適な場所です。applicationproject.local

この設定モジュールはリビジョン管理からは無視されますが、プロジェクト インスタンスを WSGI アプリケーションとして実行する場合 (通常は運用環境) に存在する必要があります。これは次のようになります。

import os

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.local")

# This application object is used by the development server
# as well as any WSGI server configured to use this file.
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

local.pyこれで、許可された担当者と Django プロセスのみがファイルの内容を読み取ることができるように、所有者とグループを構成できるモジュールを持つことができます。

于 2012-07-29T22:27:26.997 に答える
1

もう 1 つのアプローチは、バージョン管理システムにシークレットを保存することを完全に回避し、代わりにhashicorpの vault のようなツールを使用することです。これは、API と組み込み暗号化を備えたキー ローリングと監査を備えたシークレット ストレージです。

于 2016-10-06T10:14:51.797 に答える
0

システムが提供する場合は、EncFS を使用できます。したがって、暗号化されたデータをリポジトリのサブフォルダーとして保持しながら、脇にマウントされたデータへの復号化されたビューをアプリケーションに提供できます。暗号化は透過的であるため、プルまたはプッシュ時に特別な操作は必要ありません。

ただし、EncFS フォルダーをマウントする必要があります。これは、バージョン管理されたフォルダー以外の場所に保存されているパスワード (環境変数など) に基づいてアプリケーションで実行できます。

于 2012-07-29T22:53:42.903 に答える