Pythonプログラムが使用する必要のあるパスワードやその他のシークレットを保存するためのオプションがいくつかあります。特に、ユーザーにパスワードの入力を求めることができないバックグラウンドで実行する必要があるプログラムです。
避けるべき問題:
- パスワードをチェックインして、他の開発者や一般の人々が見ることができるソース管理にアクセスします。
- 同じサーバー上の他のユーザーが構成ファイルまたはソースコードからパスワードを読み取っています。
- あなたがそれを編集している間、他の人があなたの肩越しにそれを見ることができるソースファイルにパスワードを持っていること。
オプション1:SSH
これは常にオプションであるとは限りませんが、おそらく最良の方法です。秘密鍵がネットワークを介して送信されることはありません。SSHは数学的な計算を実行して、正しい鍵を持っていることを証明します。
それを機能させるには、次のものが必要です。
- データベースまたはアクセスしているものはすべて、SSHでアクセスできる必要があります。「SSH」に加えて、アクセスしているサービスを検索してみてください。たとえば、「sshpostgresql」です。これがデータベースの機能でない場合は、次のオプションに進みます。
- データベースを呼び出すサービスを実行するためのアカウントを作成し、SSHキーを生成します。
- 呼び出すサービスに公開鍵を追加するか、そのサーバーにローカルアカウントを作成して、そこに公開鍵をインストールします。
オプション2:環境変数
これは最も単純なので、始めるのに良い場所かもしれません。これは、Twelve FactorAppで詳しく説明されています。基本的な考え方は、ソースコードが環境変数からパスワードまたはその他のシークレットを取得し、プログラムを実行する各システムでそれらの環境変数を構成することです。また、ほとんどの開発者に有効なデフォルト値を使用する場合にも便利です。ソフトウェアを「デフォルトで安全」にすることとバランスを取る必要があります。
これは、環境変数からサーバー、ユーザー名、およびパスワードを取得する例です。
import os
server = os.getenv('MY_APP_DB_SERVER', 'localhost')
user = os.getenv('MY_APP_DB_USER', 'myapp')
password = os.getenv('MY_APP_DB_PASSWORD', '')
db_connect(server, user, password)
オペレーティングシステムで環境変数を設定する方法を調べ、独自のアカウントでサービスを実行することを検討してください。そうすれば、自分のアカウントでプログラムを実行するときに、環境変数に機密データが含まれなくなります。これらの環境変数を設定するときは、他のユーザーがそれらを読み取れないように特に注意してください。たとえば、ファイルのアクセス許可を確認してください。もちろん、root権限を持つすべてのユーザーがそれらを読むことができますが、それは仕方がありません。systemdを使用している場合は、サービスユニットを確認し、シークレットのEnvironmentFile
代わりに使用するように注意してEnvironment
ください。Environment
値は、を使用してすべてのユーザーが表示できますsystemctl show
。
オプション3:構成ファイル
これは環境変数と非常に似ていますが、テキストファイルからシークレットを読み取ります。それでも、デプロイメントツールや継続的インテグレーションサーバーなどの環境変数はより柔軟であることがわかります。構成ファイルを使用することにした場合、Pythonは、JSON、INI、netrc、XMLなど、標準ライブラリでいくつかの形式をサポートします。PyYAMLやTOMLなどの外部パッケージもあります。個人的には、JSONとYAMLが最も使いやすく、YAMLではコメントが許可されています。
構成ファイルで考慮すべき3つのこと:
- ファイルはどこにありますか?のようなデフォルトの場所
~/.my_app
と、別の場所を使用するためのコマンドラインオプションがあります。
- 他のユーザーがファイルを読み取れないことを確認してください。
- 明らかに、構成ファイルをソースコードにコミットしないでください。ユーザーがホームディレクトリにコピーできるテンプレートをコミットすることをお勧めします。
オプション4:Pythonモジュール
一部のプロジェクトは、その秘密をPythonモジュールに直接入れています。
db_server = 'dbhost1'
db_user = 'my_app'
db_password = 'correcthorsebatterystaple'
次に、そのモジュールをインポートして値を取得します。
from settings import db_server, db_user, db_password
db_connect(db_server, db_user, db_password)
この手法を使用するプロジェクトの1つがDjangoです。明らかに、ユーザーがコピーおよび変更できるsettings.py
というファイルをコミットしたい場合でも、ソース管理にコミットするべきではありませんsettings_template.py
。
この手法にはいくつか問題があります。
- 開発者は、誤ってファイルをソース管理にコミットする可能性があります。に追加すると
.gitignore
、そのリスクが軽減されます。
- 一部のコードはソース管理下にありません。あなたが訓練されていて、ここに文字列と数字だけを入れれば、それは問題にはなりません。ここでロギングフィルタークラスの作成を開始する場合は、停止してください。
プロジェクトですでにこの手法を使用している場合は、環境変数に簡単に移行できます。すべての設定値を環境変数に移動し、Pythonモジュールを変更してそれらの環境変数から読み取るだけです。