Amazon Web Services ブログ

EC2 インスタンス構成証明でセルフマネージド型データベースのゼロオペレーターアクセス (ZOA) を実現

本ブログは 2026 年 9 月 14 日に公開された AWS Blog “Zero operator access for self-managed databases using EC2 instance attestation” を翻訳したものです。

セルフマネージド型データベースには、プライベートキーや認証情報から、個人を特定できる情報 (PII)、金融取引に至るまで、組織にとって最も機密性の高いデータが保存されていることがよくあります。コンプライアンスや規制の要件が課されるセキュリティ重視のアプリケーションでは、ホストへのアクセス権を持つ者がこうしたデータにアクセスするリスクを許容できません。そのため、ホスト上でゼロオペレーターアクセス (ZOA) の実現を目指します。

この記事では、完全に再現可能な ZOA 環境で、ステートフルなデータベースを設計し、実装する方法を説明します。この環境は、Amazon Elastic Compute Cloud (Amazon EC2)、EC2 インスタンス構成証明、Nitro Trusted Platform Module (NitroTPM)、および Attestable AMI によって実現します。これらの機能を利用すると、Linux Unified Key Setup (LUKS) で暗号化された Amazon Elastic Block Store (Amazon EBS) ボリュームの対称キーを、特定の Amazon Machine Image (AMI) の暗号学的な測定値に紐付けることができます。その結果、EC2 インスタンスは、正しい Attestable AMI で起動された場合にのみストレージを復号できるようになります。この Attestable AMI で想定されるブート測定値は、AMI のビルド時にあらかじめ算出されています。

ここでは PostgreSQL をワークロードの例としてこの手法を紹介しますが、同じパターンは、AI モデルの重みや独自のアルゴリズムなど、暗号化されたデータにアクセスできるワークロードを厳格に制限するガードレールが必要なあらゆるユースケースに適用できます。

前提条件とデプロイ

始める前に、以下の内容を理解しておいてください。

  • Nix Flakes: Nix Flakes は、完全に自己完結型のビルドフレームワークです。flake.nix ファイルでシステム全体 (カーネル、パッケージ、サービス、構成) を宣言的に定義し、flake.lock ファイルですべての入力を特定の git コミットハッシュに固定します。これにより、内容がソースコードによって完全に決まる、ビット単位で再現可能な AMI イメージを生成できます。
  • Linux のブートプロセス: Unified Kernel Image (UKI)、dm-verity (読み取り専用ファイルシステムの整合性確保用)、および LUKS (暗号化ボリューム用)。
  • TPM/PCR の概念: Platform Configuration Register (PCR) がブート測定値を蓄積する仕組みと、PCR を偽造できない理由。
  • AWS のサービス: EC2、AWS KMS、EBS、および IMDS。KMS キー、EC2 インスタンス、EBS ボリューム、AWS Identity and Access Management (IAM) ロールを作成する権限を持つ AWS アカウントが必要です。

プロビジョニングスクリプトや NixOS ベースのイメージビルドを含む完全なリファレンス実装は、https://github.com/aws/nitrotpm-attestation-samples リポジトリで公開されています。

適切な AWS コンフィデンシャルコンピューティングソリューションの選択

AWS Nitro Enclaves は、ステートレスなワークロード向けとして広く利用されているコンフィデンシャルコンピューティング機能です。ただし、Nitro Enclaves は厳格に分離された環境で動作し、永続ストレージを持たず、ネットワーク機能も vsock チャネル経由に限られます。EBS ボリュームへの直接アクセス、高いスループット、永続的な状態を必要とするデータベースワークロードをエンクレーブ上に構築しようとすると、これらの制約を回避するために多大なエンジニアリング作業が必要になります。

EC2 インスタンス構成証明は、ハードウェアとネットワークへの完全なアクセスを維持したまま、信頼できるソフトウェアとブートプロセスのみがインスタンス上で実行されていることを暗号学的に証明します。Nix Flakes のような再現可能なビルドシステムと組み合わせることで、データベースに求められるストレージの特性やパフォーマンスを犠牲にすることなく、ゼロオペレーターアクセスを実現できます。

ZOA データベースのユースケースには、EC2 インスタンス構成証明が適しています。必要な機密性を確保しながら、暗号化された EBS ボリュームのマウント、高いスループットでのクエリ処理、標準的なネットワークでの運用をこれまでどおり行うことができます。

再現可能な Attestable AMI の構築

このセクションでは、Nix Flakes を使用して、完全に再現可能で構成証明可能な AMI を構築する方法を詳しく説明します。図 1 は、再現可能で構成証明可能な AMI を構築するために必要な 5 つの大まかなステップを示しています。

Architecture diagram showing the 5 high-level steps to build a reproducible Attestable AMI and generate reference measurements

図 1: Amazon EC2 インスタンス構成証明 (ビルド時のみ)。再現可能な AMI を作成し、その参照測定値を生成します。

1. Nix ビルド: ロックされた flake の入力から決定論的にビルドを行い、AMI の raw イメージを生成します。このイメージは、ESP (UKI)、dm-verity ハッシュツリー、nix store (erofs、読み取り専用) で構成されます。入力が同じであればビット単位で同一の AMI が生成されるため、PCR4 測定値も同じになります。

2. dm-verity によるストアの紐付け: UKI の cmdline には、nix store に対するマークルツリー (Merkle Tree) のルートハッシュが含まれます。ビルド後にストアを変更するとルートハッシュが変わり、その結果 PCR4 も変わります。オプションとして、ビルド後に UKI に署名してセキュアブート署名を追加することもできます。テンプレートでは --secure-boot フラグを使用してこの処理を行っています。

3. nitro-tpm-pcr-compute: このビルド時ユーティリティは、UKI の .efi ファイルのみを読み取り、測定アルゴリズムをオフラインで再現して PCR 値を算出します。PCR 値は 96 文字の SHA-384 ダイジェストで表されます。

4. 参照測定値: このツールは tpm_pcr.json を出力します。

  • PCR4 (Boot Manager Code): UEFI 環境が実行するブートバイナリのハッシュです。Attestable AMI では、このハッシュが構成証明ドキュメントに追加され、AWS KMS キーポリシーに設定された PCR4 値と一致するかどうかを AWS KMS が評価します。これにより、KMS キーを利用できるコードを PCR4 で厳密に固定できます。
  • PCR7 (Secure Boot Policy、セキュアブートが有効な場合のみ): UEFI セキュアブートポリシーのハッシュです。この値は AMI を更新しても変わらないため、特定の AMI の測定値ではなく、セキュアブート証明書を検証する AWS KMS ポリシーを 1 つ記述するだけで済みます。
  • PCR12: カーネルコマンドラインに加えられた変更 (アドオンファイルによる変更など) のハッシュです。PCR4 と組み合わせて、コマンドラインが改ざんされていないことを確認するために使用します。

5. AWS Key Management Service (AWS KMS) キーポリシーへの組み込み: 参照測定値を RecipientAttestation 条件として設定します。これにより AWS KMS は、実際の測定値が一致するインスタンスに対してのみキーを提供するようになります。

それでは、図 1 に示した各ステップの実装の詳細を見ていきましょう。ステップ 1 と 2 に対応する処理として、まず Linux カーネル、カーネルコマンドライン、initramfs、一部のメタデータを含む、強化された Unified Kernel Image (UKI) をビルドします。

ビルドには Nix を使用することをお勧めします。Nix を使用すると、ビルドを宣言的かつ再現可能にできます。ロックされた同じソースからは常にバイト単位で同一の UKI が生成されるため、PCR4 測定値も常に同じになります。図 1 のステップ 3 と 4 のとおり、ビルドでは raw イメージとともに tpm_pcr.json ファイルが出力されます。

{
    "Measurements": {
        "PCR4": "f3a1e2...",
        "PCR7": "a32b31...",
        "PCR12": "000000..."
    }
}

管理下にある Attestable AMI の PCR 測定値を持つ EC2 インスタンスにのみ AWS Key Management Service (AWS KMS) キーでの復号を許可するため、参照測定値を使用して AWS KMS キーポリシーを設定します。

{
    "Sid": "Allow decryption for the Instance role",
    "Effect": "Allow",
    "Principal": {
        "AWS": "${INSTANCE_ROLE}"
    },
    "Action": [
        "kms:Decrypt"
    ],
    "Resource": "*",
    "Condition": {
        "StringEqualsIgnoreCase": {
            ${PCR_VALUES}
        }
    }
}

AWS KMS キーポリシーの JSON オブジェクト内にある ${PCR_VALUES} には、ビルド中に生成された tpm_pcr.json の測定値が入ります。

ここで重要なのは、インスタンス構成証明によって暗号学的に検証された AMI にのみ復号オペレーションを許可する唯一の制御点が、AWS KMS キーポリシーであるという点です。そのため、PCR 値は CI/CD パイプラインで自動更新するのではなく、慎重な手動プロセスで固定し、レビューする必要があります。自動更新を行うと、変更されたイメージや未承認のイメージが気付かないうちに許可され、構成証明による保証がすべて無効になるおそれがあります。

この例では、PostgreSQL データベース用の AMI を作成して、その PCR 測定値を取得します。そして、その測定値を使用して AWS KMS を設定し、正しい測定値で構成証明に成功した場合にのみ、データベースの EBS ボリュームのキーを復号できるようにします。それでは、Nix を使用して記述的かつ再現可能な形で実現できる、具体的なポイントをいくつか見ていきましょう。

ゼロオペレーターアクセス

ゼロオペレーターアクセスを強制して不正アクセスの攻撃対象領域を限定するために、SSH やシリアル接続によるアクセスを含め、マシンへのあらゆる形式のログインを無効にします。

services.sshd.enable = lib.mkForce false;

また、次の設定も行います。

systemd.services."autovt@"       = lib.mkForce {};
systemd.services."getty@"        = lib.mkForce {};
systemd.services.getty-static    = lib.mkForce {};
systemd.services."serial-getty@" = lib.mkForce {};

ファイアウォールとインスタンスメタデータサービス (IMDS) の制御

さらに、インバウンド通信を PostgreSQL に必要なポート 5432 のみに制限し、インスタンスメタデータサービス (IMDS) へのアウトバウンドアクセスを kms-init サービスにのみ許可できます。EC2 インスタンスで実行されるサービスが新しい一時的な AWS 認証情報を取得するには、IMDS へのアクセスが必要です。

networking.firewall = {
    # Allow inbound PostgreSQL connections over mTLS
    allowedTCPPorts = [ 5432 ];

    # IMDS access control - only kms-init user can reach IMDS
    extraCommands = "
        # Allow kms-init service to access IMDS for KMS operations
        ${pkgs.iptables}/bin/iptables -A OUTPUT -d 169.254.169.254 -m owner --uid-owner kms-init -j ACCEPT
        [...]";
};

読み取り専用ファイルシステムの測定

エフェメラルなルートファイルシステム (tmpfs、ディスクや永続ストレージを使用しない) を / に配置します。

"/" = {
    fsType = "tmpfs";
    options = ["mode=0755"];
};

一方、実際のアプリケーションデータ (例えば postgres バイナリ) は /dev/mapper/usr に格納され、/usr に読み取り専用でマウントされます。

"/usr" = {
    device = "/dev/mapper/usr";
    # explicitly mount it read-only otherwise systemd-remount-fs will fail
    options = ["ro"];
    fsType = config.image.repart.partitions.${partitionIds.store}.repartConfig.Format;
};

ここで注意が必要なのは、/dev/mapper/usr は UKI に含まれないという点です。そのため、NitroTPM の測定値 (UKI のビルド時に算出する PCR 値) は、/dev/mapper/usr に保存したデータと直接紐付いていません。

この状態は望ましくありません。権限のないユーザーがこの領域にアクセスできた場合、例えば postgres バイナリを改ざんされたビルドに置き換えることで、データベースの整合性と機密性を損なう可能性があるためです。

マウントされた /dev/mapper/usr (/usr にマウントされ、nix store を含む) の内容が想定どおりで変更されていないことを検証するため、Linux dm-verity を使用してこの領域を PCR 測定値に紐付けます (図 1 のステップ 2 を参照)。Attestable AMI のビルド時に、/dev/mapper/usr 全体のマークルツリーを計算し、そのルートハッシュをカーネルブートパラメータとして渡します。

カーネルコマンドラインはビルド時に UKI に埋め込まれ、バイナリ全体を対象とする PCR4 の測定範囲に含まれます。カーネルコマンドラインには systemd.verity_root_options=panic-on-corruption が含まれているため、dm-verity が /usr パーティションで破損を検出すると、改ざんされたコードを実行する代わりにカーネルパニックが発生し、インスタンスが再起動します。

セキュアブートのバリエーション

ユースケースによっては、Attestable AMI を定期的に再ビルドしたり、異なるアプリケーションの Attestable AMI に同じポリシーを適用したりする必要があります。AMI への変更は PCR4 測定値に反映されるため、AWS KMS キーポリシーを PCR4 値で制御すると、AMI を変更するたびにキーポリシーも更新しなければなりません。これが運用上望ましくない場合は、代わりにセキュアブートを有効にし、その結果得られる PCR7 測定値にポリシーを紐付けることができます。

PCR7 はセキュアブートの状態を表す測定値で、UKI の署名者のアイデンティティが含まれます。つまり、Attestable AMI のビルド時にセキュアブートを有効にし、事前に定義したキーで署名すれば、AWS KMS へのアクセスを PCR7 測定値のみで制御できます (ポリシーから PCR4 と PCR12 を除外)。これにより、Attestable AMI と、それを実行する EC2 インスタンスのフリート全体を 1 つのポリシーでカバーできます。

ブート時の信頼チェーン

次に、ブート時に信頼チェーンがどのように評価されるかを見ていきましょう。図 2 は、EC2 のブート中に NitroTPM、Attestable AMI、AWS KMS の間で信頼チェーンが確立されるまでの 8 つのステップを示しています。

Architecture diagram showing the 8-step boot-time trust chain between NitroTPM, the Attestable AMI, and AWS KMS

図 2: Amazon EC2 インスタンス構成証明のブート時の信頼チェーン。Attestable AMI 内の systemd サービスが、ブート時に暗号化されたキーの取得、復号、EBS ボリュームのロック解除、マウント、データベースの起動を連携して実行します。

0. UEFI による UKI の測定: ブート時に AWS Nitro ファームウェアが ESP から UKI をロードし、NitroTPM の PCR を拡張します。実行される UKI は PCR4 に、cmdline (すべてゼロ) は PCR12 に、セキュアブートキー (オプション) は PCR7 に反映されます。

1. 構成証明のリクエスト: network-online になると、NitroTPM が発行した構成証明ドキュメント (実際の PCR 値を含む) が kms-init に渡されます。

2. ユーザーデータの取得: kms-init がインスタンスメタデータサービス (IMDS) のユーザーデータから暗号化されたキーを読み取ります。

3. AWS KMS での復号: kms-init が、署名された構成証明ドキュメントと暗号文を AWS KMS に送信します。AWS KMS は実際の測定値と参照測定値を比較し、一致した場合は対称キー (tmpfs にのみ保持) を返します。

4. luks-unlock: 対称キーを使用して、Linux の cryptsetup で LUKS EBS ボリュームのロックを解除し、暗号化されたボリュームを読み書きできるようにします。

5. cert-init (並列): 同じキーを使用して、PostgreSQL の Transport Layer Security (TLS) 用のサーバー証明書バンドルを復号します。

6. data.mount: ステップ 4 でロックを解除した ext4 ボリュームを /data にマウントします。これは、tmpfs (エフェメラル) 以外で唯一の書き込み可能なボリュームです。

7. postgresql: cert-init が用意した TLS 証明書を使用して起動します。dm-verity で保護された nix store から実行され、/data/postgresql に対して読み書きを行います。

ブート時に同じキーを TLS サーバーアイデンティティにも活用

次に、AWS KMS で保護された対称キーを使用して、ブート時に機密情報を管理する方法を見ていきましょう。

ブートチェーンで提供される対称キーは汎用的なものです。プロビジョニング時にこのキーで暗号化したアーティファクトであれば、同じ構成証明済みのブートで復号できます。リファレンス実装では、この特性を利用して、AMI の測定値に紐付けられた PostgreSQL 用の TLS サーバーアイデンティティもプロビジョニングしています。認証局 (CA)、サーバー証明書、サーバーのプライベートキーを tarball にまとめ、同じ対称キーで暗号化したうえで、データベースの暗号文とともに EC2 ユーザーデータに埋め込みます。cert-init.service は、Attestable AMI 内でこのバンドルを tmpfs ディレクトリに復号します。PostgreSQL は clientcert=verify-full を強制した状態でポート 5432 で接続を受け付け、同じ CA によって署名された証明書を持つクライアントとの間で相互 TLS を確立します。

リファレンス実装のビルドとデプロイ

リファレンス実装は、そのままエンドツーエンドで実行できます。--secure-boot や --debug など、利用可能なデプロイオプションの詳細については Readme を参照してください。

  1. リポジトリをクローンし、そのディレクトリに移動します。
git clone https://github.com/aws/nitrotpm-attestation-samples && cd nitrotpm-attestation-samples

  1. 十分な IAM 権限があることを確認します。必要な権限は、Readme の「Minimal IAM Privileges」セクションに記載されています。
  2. リポジトリ内で次のコマンドを実行します。AWS リソースがプロビジョニングされ、セキュアブートと secrets-manager を使用して、構成証明済みの LUKS 暗号化ボリューム上で PostgreSQL を実行する EC2 インスタンスが起動します。
cd nix/examples/postgres-kms
./scripts/e2e-test.sh --secure-boot --secrets-manager --authorize-my-ip --create-roles --no-cleanup

クリーンアップ

この例で作成したすべての AWS リソースを削除するには、次のコマンドを実行します。

./scripts/clean.sh

まとめ

この記事では、Amazon EC2 インスタンス構成証明を使用して、ゼロオペレーターアクセスを実現する PostgreSQL 用の Attestable AMI を再現可能な形でビルドするプロセスについて説明しました。また、NitroTPM ベースのブート検証プロセスと、ブートに成功した後に暗号化された EBS ボリュームをマウントする方法についても詳しく解説しました。さらに、PCR 測定値を使用して AMI への変更を検出し、EC2 インスタンスのブートを阻止するとともに、改ざんされたコードが AWS KMS での復号に必要な権限を取得できないようにする方法も紹介しました。

さっそく nitrotpm-attestation-samples リポジトリをクローンし、ニーズに合わせてテンプレートをカスタマイズして、Attestable AMI によるデータ保護を始めましょう!


著者について

David-Paul Dornseifer

David-Paul Dornseifer

David-Paul は AWS の Confidential Compute and Systems Architect です。デジタル資産のカストディ、コンフィデンシャル推論、低レイテンシーの取引インフラストラクチャを専門としています。

Ben Liderman

Ben Liderman

Ben 氏は Fireblocks のシステムアーキテクトです。コンフィデンシャルコンピューティングを活用して高価値なデジタル資産の運用を保護する、セキュアな金融インフラストラクチャの設計に携わっています。

本ブログは Security Solutions Architect の 中島 章博 が翻訳しました。