♻️

環境変数、認証情報、秘匿情報の大まかな区別と扱い方

2024/03/30に公開

IT業界入り立てのお友だちに口頭説明する際のメモだったが、誰かの役に立つかもしれないので公開する。残念ながら、わかりやすくはならなかった。

事実認識の誤り・記述面での瑕疵等、何らか問題があったらやさしくリポートしてほしい。

環境変数(Environment Variables)

そのまま、環境単位で管理・決定される変数のことを指す。
「同一のソースコードを共有するアプリケーションが、相異なるインフラストラクチャの上で起動する」といった場面において、環境毎の差異を表現するために用いられる値である。Prod環境、Stg環境、Dev環境、Local環境……etcの環境構成の違いに応じてアプリケーションが知っておくべき事項を変数として渡そう、というコンセプト。

基本的に、起動しているOS単位で設定されるものとなる。「言語処理系、あるいはWeb Application Frameworkがプロセス起動時に特定名称のファイルから値を読み込む」といった形でセットされている場合もある。

「基本的には外部から秘匿しておいた方がよろしい」といった黙約があるような気もするし、同意するところではあるが、必ずしも機微ではない。例えばAPP_ENV=productionDEBUG_MODE=falseといった環境変数設定があり得る(実際、Laravelで使われる環境変数名である)ものの、誰かに見られても実害はさほどない。もちろんコンテキスト次第ではある。

また、そもそもなぜ環境変数を利用するかについての詳細は、The Twelve-Factor AppのIII configのページを参照すると良い。

The Twelve-Factor App (日本語訳) | config

認証(資格)情報(Credentials)

任意サーバーにアクセスする際、本人性の確認のために用いられる情報。認証情報であれば即座に機微というわけではないが、多くの場合は機微である。

具体例としては、ssh key pair、ID Password、顔、指紋、などが挙げられる。
なんとなく知識要素の印象が強いようにも思えるが、認証要素全般がCredentialsとして認識できる。

「あるサーバーに、別のリモートサーバーへアクセスするための資格情報を、環境変数として持たせる」といった仕組みを構成することもよくある。こうした運用がポピュラーであるため、環境変数・認証情報といった概念の別を認識していなさそうな人をたまに見かける。が、環境変数は必ずしも認証情報とは限らない。

秘匿情報(Secrets)

隠さなければいけない機微な情報。認証情報のうち機微であるようなものはもちろん秘匿情報に含まれる。何らかのデータストアに保持する場合、限定された人間しかアクセスできないように制御したり、暗号化したりする必要がある(機密性の確保)。

外部に漏出してはならない情報一般を指して良い言葉と思う。が、よく使われるのはAPI Keyなどの機微な認証情報としての秘匿情報を指示する場面である。あとは秘密鍵とか。

扱い方

上記で整理した区別を考慮すると、git pushしてはいけないのは秘匿情報となる。

ではどうやって利用すればいいかと言うと、「秘匿情報を機密性の高いストアに保持し、デプロイなどのタイミングでストアから呼び出し、サーバーに環境変数として渡す」のような手順である。以下に具体例を示す。

  • GitHub RepositoryにSecrets登録を行い、GitHub Actions上でのデプロイ時にデプロイ先のサーバーに何らかの形で渡す(.envファイル化してアプリケーションのディレクトリに配置するなど)
  • AWS SSM Parameter Storeなどに登録し、ECSタスク定義などを経由してコンテナに渡す

ちなみに、IaaS側(AWS, GCP, MS Azure等)に置いておく方が管理面が煩雑になりにくい。同一の環境変数を共有する複数のサーバーを運用している場合、それぞれのサーバーに秘匿情報を楽かつ安全に配布しやすいのはおそらくIaaS側のストアだからである。また、「Repository毎に登録」のような非DRY操作をしないで済み、single source of truthの状態を保ちやすいのも大きい。

機密性の高いストアとは、「暗号化->復号の仕組みを用意してくれている」「ストアする値の論理名毎に権限管理が行える」「アクセス経路が限定的である」などの特徴を備えているものと思っておけばいい気がしている。

これまでの話からの帰結として、機微でない環境変数はcommitするファイルに載せて良いも導けるはずである。実際、アプリケーションのディレクトリにenv.example.localのようなファイルを作り、個別のローカル開発環境毎のビルド時にそのファイルを.envとしてコピーする、といった運用はしばしば見かける。機微でない環境変数は、配布の簡便さを優先しよう、というわけだ。

例えばAPP_NAME=oreno-iketeru-app, HOST_NAME=localhostなどは機微ではなく、わざわざストアからリレーする方が面倒かつ環境の複雑化にも繋がり得るので、こうした扱いをする。

ぐだぐだ書いてきたものの、文脈に応じて伝わるように言えさえすれば呼称は何でもいいと思う。

Discussion