【ITニュース解説】One secret in our task definition hid the database change sitting next to it
2026年10月28日に「Dev.to」が公開したITニュース「One secret in our task definition hid the database change sitting next to it」について初心者にもわかりやすく解説しています。
ITニュース概要
Terraform設定でAPIキーを機密情報に指定した結果、同じ設定内のデータベース接続先変更がレビュー時に見えなくなり、誤って適用されサービス障害が発生した。機密情報があると、設定全体が「機密」とマークされるためだ。対策として、機密情報を別途管理し、設定変更が明確に見えるよう改善。DB接続チェックも導入した。
ITニュース解説
あるシステムで、注文サービスが約9分間、注文の書き込み処理に失敗し続けるという障害が発生した。エラーメッセージは「read-only transactionでINSERTを実行できない」というもので、これはデータベースが読み取り専用の状態であり、データを変更する処理が許可されていないことを示している。具体的には、新しくマージされたプルリクエストが原因で、注文サービスが接続するデータベースのURLが、本来の書き込み可能なデータベースではなく、レポート作成用の読み取り専用データベース(レプリカ)を指すように変更されてしまっていたのだ。
このサービスは、Amazon Elastic Container Service (ECS)というクラウドサービス上で動作しており、その設定情報である「タスク定義」はTerraformというツールを使ってコードとして管理されていた。Terraformは、インフラストラクチャをコードで記述し、自動的に構築・変更できるツールで、システムエンジニアがインフラを効率的に管理する上で非常に重要だ。タスク定義には、サービスを構成するコンテナの設定がJSON形式で記述され、その中にはデータベースの接続URLや、外部サービスに接続するためのAPIキーなどの環境変数も含まれる。
問題の核心は、このTerraformの挙動にあった。タスク定義に含まれる環境変数の一つに、外部のアドレス検索プロバイダーのAPIキーがあった。このAPIキーは「機密情報」であるため、Terraformのコードではsensitiveという属性がつけられていた。sensitive属性をつけた変数は、Terraformが扱う際にその値がログや出力に表示されないように保護される。コンテナ定義はJSON形式の文字列として生成されるが、このJSON文字列の中に一つでもsensitiveな値が含まれていると、TerraformはそのJSON文字列全体を「機密情報を含む値」と判断する。
その結果、Terraformが変更内容をレビューのために提示する「プラン」というプレビュー画面に異変が起きた。通常であれば、プランには変更される具体的な内容(例えば、データベースURLがAからBに変更される、など)が詳細に表示されるはずだ。しかし、今回のケースでは、コンテナ定義全体が機密情報として扱われたため、プラン上では「container_definitions = (sensitive value)」と表示され、具体的な中身が隠されてしまったのだ。さらに悪いことに、この「(sensitive value)」という表示は、コンテナイメージを更新する際などにも表示される、サービスではよく見慣れたメッセージだった。そのため、システムエンジニアは具体的な変更内容を確認することなく、普段通りにこのプランを承認してしまった。必要な差分、つまりデータベースURLが変更されているという重要な情報は、機密情報を保護するための機能によって皮肉にも隠蔽されてしまっていたのである。この見落としが、サービスが読み取り専用データベースに接続し、9分間も書き込みに失敗し続ける原因となった。
この問題が発覚した後、まず行われたのは緊急対応として、問題の原因となった変更を元に戻す(コミットをロールバックする)ことだった。そして、このロールバックと再適用の一連の作業に、9分間のサービス停止時間のうちの一部が費やされた。
次に、再発防止のために根本的な対策が講じられた。まず、APIキーのような機密情報をTerraformが直接扱わないように変更された。具体的には、APIキーはAmazon Web Services (AWS) のSecrets Managerというサービスに保存されるようになった。Secrets Managerは、機密情報を安全に保存・管理するためのサービスだ。そして、ECSのタスク定義では、APIキーそのものを環境変数として設定する代わりに、Secrets Managerに保存されたAPIキーの「Amazon Resource Name (ARN)」という識別子を指定するように変更された。ARNは機密情報ではないため、もはやコンテナ定義全体がsensitive valueとして扱われることはなくなった。
この変更により、Terraformのプランは以前のように完全な形でコンテナ定義を表示するようになり、データベースのホスト名が変更された場合は、JSONの差分として具体的な変更行が赤線で明確に示されるようになった。これにより、レビュー担当者は変更内容を正確に把握し、誤った設定を見つけることが可能になったのだ。
さらに、より多層的な防御策が導入された。Terraformのプランで生成されたJSONを対象に、自動的なポリシーチェックが追加された。このポリシーチェックは、本番環境のリソース属性が「sensitive value」として完全にマスクされている場合、パイプライン(変更が本番環境にデプロイされるまでの一連の自動化されたプロセス)を自動的に失敗させるように設定された。これにより、今後同様の問題が発生するリスクが大幅に低減される。
最後に、注文サービス自体も堅牢性を高めるための改善が行われた。サービスが起動する際、自身の接続先データベースがプライマリ(書き込み可能)であることを確認するロジックが追加されたのだ。具体的には、PostgreSQLデータベースの場合、「pg_is_in_recovery」という関数を使って、データベースがレプリカ(読み取り専用)状態ではないことを確認する。もしプライマリではないと判断された場合、サービスは準備完了状態にならず、起動プロセスを停止する。これにより、たとえ誤ったデータベースURLがデプロイされてしまったとしても、サービスが稼働し始める前に問題を検知し、注文が処理できない事態を防ぐことができるようになった。これにより、将来的に同様の誤ったホスト設定がデプロイされそうになっても、9分間も注文処理が停止する代わりに、デプロイが停止されるようになる。
この事例は、システム開発における機密情報の扱いの重要性、そして自動化ツールの挙動を深く理解することの必要性を示している。Terraformのsensitive属性は機密情報を保護する非常に有用な機能だが、その影響範囲や、それが引き起こすプランの表示のされ方を把握していなければ、今回のように重要な変更を見落とす原因にもなり得る。コードレビューの際には、表示される情報だけでなく、その背後にあるツールがどのように動作しているかを常に意識し、多層的なチェック体制を構築することが、安定したサービス運用には不可欠である。