Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】Stop Putting Secrets in Environment Variables: Practical systemd-creds on Linux

2026年09月30日に「Dev.to」が公開したITニュース「Stop Putting Secrets in Environment Variables: Practical systemd-creds on Linux」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

環境変数に秘密情報を置く方法は安全でない。systemd-credsは、サービス起動時に秘密情報を復号し、$CREDENTIALS_DIRECTORYに安全に配置する。これにより、従来の環境変数よりも安全に、暗号化された秘密情報をサービスごとに管理できる。

ITニュース解説

システム運用において、データベースのパスワードやAPIトークンといった「秘密情報(シークレット)」を安全に管理することは、情報セキュリティの観点から極めて重要である。しかし、これまで広く行われてきた秘密情報の管理方法には、セキュリティ上の課題が少なくなかった。例えば、設定ファイルの中に平文でパスワードを直接書き込んだり、サービスを起動する際に環境変数として秘密情報を渡したりする方法は手軽である反面、情報漏洩のリスクを伴う。

環境変数に秘密情報を設定する方法は、サービスを起動する環境に依存するため、そのサービスから派生する子プロセスや、システム上の他のプロセスからD-Busなどの経路を通じて、情報が読み取られてしまう可能性がある。これは、たとえ設定ファイル自体が適切なアクセス権で保護されていても、メモリー上の情報として露出してしまうため、意図せず秘密情報が漏洩するリスクを意味する。また、秘密情報を記載したファイルを/etc以下に置く場合でも、適切な権限設定(例えば、所有者のみ読み取り可能)を怠ると、簡単に他のユーザーやプロセスから読み取られてしまう。さらに、たとえファイルの権限を適切に設定しても、そのファイルを読み取れる特定の権限を持つプロセスがあれば、秘密情報にアクセスできてしまうため、サービス単位での厳密な隔離が難しいという問題があった。Gitリポジトリでの暗号化ツール(SOPSやageなど)はバージョン管理されたコードや設定の保護には優れるが、サービスが実際に実行される際の秘密情報を受け渡す仕組みとしては不十分である。また、ディスク全体の暗号化(LUKSなど)はディスクの盗難対策には有効だが、稼働中のシステム内でのプロセスごとの秘密情報管理には直接寄与しない。

これらの課題を解決するため、Linuxのinitシステムであるsystemdは「クレデンシャル(認証情報)」という新しい機能と、それを管理するsystemd-credsというツールを導入した。クレデンシャルは、サービスが必要とする秘密情報を安全に管理し、サービスに提供するための仕組みである。これは、サービスが起動する際にsystemdによってロードされ、必要に応じて暗号化を解除し、サービス専用の隔離されたディレクトリに配置される。サービスはこのディレクトリ内のファイルとして秘密情報にアクセスできるため、環境変数として情報を直接渡すよりもはるかに安全な方法を提供する。

systemdクレデンシャルの主な利点は、そのライフサイクルとアクセス制御の厳密さにある。クレデンシャルはサービスがアクティブな間のみ有効で、サービス停止時には自動的に解放される。サービスは$CREDENTIALS_DIRECTORYという専用の環境変数を通じて、自分に割り当てられた秘密情報を含むディレクトリにアクセスする。このディレクトリ内のファイルは、当該サービスのユーザーIDとrootユーザーのみが読み取れるように厳密にアクセス権が制限される。さらに、クレデンシャルは保存時にAES-256-GCM暗号化を適用できる。この暗号化には、システムのTPM2チップやホスト固有の秘密鍵を利用でき、より高いセキュリティレベルを実現する。暗号化された秘密情報は、ユニットファイル内や専用のファイルに安全に格納できるため、平文が露出するリスクを大幅に低減できる。また、環境変数では扱いにくいバイナリデータもクレデンシャルとして扱え、1ユニットあたり最大約1MBまでの秘密情報を累積して保持できる。

systemdのユニットファイルには、クレデンシャルをサービスに割り当てるためのいくつかの設定オプションが用意されている。LoadCredential=ID[:PATH]は、ディスク上のファイルなどから暗号化されていないクレデンシャルをロードする。この場合、元となるファイル自体は適切に保護する必要がある。LoadCredentialEncrypted=ID[:PATH]は、暗号化されたクレデンシャルファイルをロードする。サービス起動時に自動的に復号され、安全に利用できる。SetCredential=ID:VALUEは、ユニットファイル内に直接クレデンシャル値を記述するが、これは公開鍵のような秘密ではない情報に使うべきであり、秘密情報には適さない。SetCredentialEncrypted=ID:VALUEは、暗号化されたクレデンシャルデータをユニットファイル内に直接記述する。この場合、ユニットファイル自体は読み取り可能であっても、暗号化されているため秘密情報の安全が保たれる。ImportCredential=GLOBは、コンテナマネージャーやハイパーバイザーなどからシステム全体に提供されたクレデンシャルをサービスにインポートする際に使用する。

クレデンシャルは、/etc/credstore.encrypted/のような特定のディレクトリに暗号化された形式で保存されることが期待される。サービス内部では、$CREDENTIALS_DIRECTORY/IDというパスを通じてアクセスできる。ユニットファイルの設定では、%d/IDという形式も使用できる。これにより、サービスは秘密情報をあたかもファイルとして扱えるため、既存の多くのアプリケーションがファイルパスを指定する形式で秘密情報を受け取れるように容易に対応できる。

systemd-creds encryptコマンドを使うことで、秘密情報を簡単に暗号化できる。暗号化の際には、--with-keyオプションで鍵のモードを指定できる。例えば、hostモードでは、/var/lib/systemd/credential.secretに保存されるホスト固有の秘密鍵を使って暗号化される。tpm2モードでは、システムのTPM2チップに鍵をバインドし、よりセキュアな環境を提供する。これらを組み合わせたhost+tpm2モードも利用可能である。暗号化アルゴリズムはAES-256-GCMが用いられ、生成される暗号文はBase64エンコードされる。この機能はsystemd 250以降で利用でき、特にユーザーサービスの暗号化はsystemd 256以降で可能となる。

実用的な活用例として、コマンドラインから秘密情報を暗号化し、/etc/credstore.encrypted/mysecret.credのようなパスに保存する。その後、サービスユニットファイルにLoadCredentialEncrypted=mysecretと記述することで、サービスはその秘密情報を利用できるようになる。また、systemd-ask-passwordと連携してパスワードを安全に暗号化し、SetCredentialEncrypted=形式でユニットファイルに直接貼り付けることも可能である。これにより、別途秘密情報ファイルを管理する手間を省きつつ安全性を確保できる。既存のアプリケーションが環境変数で秘密情報ファイルのパスを期待する場合でも、Environment=API_TOKEN_FILE=%d/api-tokenのように設定し、ExecStartコマンドラインで$CREDENTIALS_DIRECTORY/api-tokenを参照させることで、安全にクレデンシャルを提供できる。

運用では、systemd-creds encryptで秘密情報を作成し、/etc/credstore.encrypted/のような保護されたディレクトリに保存するか、SetCredentialEncrypted=でユニットファイルに埋め込む。サービスにはLoadCredentialEncrypted=やImportCredential=でクレデンシャルを宣言し、環境変数に平文の秘密情報を置くことは避けるべきである。サービス内では$CREDENTIALS_DIRECTORYや%dパス参照でクレデンシャルを利用する。セキュリティを強化するため、ProtectSystem=strict、PrivateTmp=yes、ProtectHome=yesといったサンドボックス設定を適用し、他のユニットからクレデンシャルマウントが見えないようにすることが推奨される。秘密情報のローテーションは、新しい暗号文を作成し、ユニットを再起動することで行う。ホスト鍵に依存する場合、/var/lib/systemd/credential.secretのバックアップを適切に管理しないと、ホスト鍵を失った場合にクレデンシャルが復号できなくなるため、注意が必要である。また、--not-afterオプションでクレデンシャルに有効期限を設定することもできる。

systemdクレデンシャルは、単一ホスト上のsystemdサービスに対するローカルな秘密情報注入層として非常に優れた解決策である。これは、GitOpsのためのリポジトリ暗号化ツール(SOPS, age)や、ディスク全体の暗号化解除(Clevis, Tang, LUKS)とは異なる役割を持つ。また、企業全体で利用するような複雑なシークレットマネージャーの完全な代替とはならないが、Linuxシステム上で実行される多くのアプリケーションにとって、安全かつ効率的な秘密情報管理の手段を提供する。環境変数に秘密情報を置くという一般的な慣習を改善し、サービスが起動時に必要な秘密情報にだけアクセスできる、より堅牢なシステムを構築するための重要なステップとなるだろう。

関連コンテンツ

関連IT用語

関連ITニュース