Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

イメージ署名

AWS Signer によるプローバーコンテナイメージの署名と実行前確認を解説します。

STARK 証明は「特定のゲストプログラムが正しく実行された」ことを保証しますが、そもそもそのゲストプログラムを含むコンテナイメージ自体が改ざんされていないことも保証する必要があります。イメージ署名は、信頼されたビルドパイプラインが生成したイメージのみが証明生成に使用されることを担保するセキュリティゲートです。

脅威モデル

イメージ署名が防止する攻撃シナリオを示します。

署名なしの場合

  1. 攻撃者が ECR イメージを改ざんしたものに置換
  2. 改ざんされたプローバーが不正な集計結果を生成
  3. 不正な結果に対して有効な STARK 証明が存在

署名ありの場合

  1. 攻撃者が ECR イメージを改ざんしたものに置換
  2. Step Functions が署名ステータスを確認
  3. 署名なし/未完了を検出 → タスク起動を拒否

STARK 証明は Image ID(ゲストバイナリの暗号的識別子)に紐づきますが、イメージ署名はそれとは別のレイヤで「コンテナイメージ全体の完全性」を保証します。両者は相補的な防御を形成します。

保証の種類メカニズム検出対象
ゲストプログラムの同一性Image ID(RISC Zero)ゲストバイナリの改変
コンテナイメージの完全性AWS Signerイメージ全体の改変(ホスト含む)

署名フロー

ビルドと署名

CodeBuild がプローバーコンテナイメージをビルドして ECR に push し、その後 ECR 上で解決されたイメージ digest を Terraform の ecs_image_uri に反映します。Step Functions は、その digest 固定のイメージ参照に対して署名ステータスを確認します。 ECR マネージド署名が有効な環境では、push 後に AWS Signer プロファイルに基づく署名ステータスが対象 digest に付与されます。

sequenceDiagram
  participant GH as GitHub
  participant CB as CodeBuild
  participant ECR as ECR
  participant SGN as AWS Signer

  GH->>CB: ソースコード取得
  CB->>CB: Docker イメージビルド<br/>(ARM64)
  CB->>ECR: イメージをプッシュ<br/>(タグ付き)
  ECR-->>CB: digest を解決
  ECR->>SGN: (ECR managed signing 有効時)署名処理
  SGN->>ECR: 署名ステータス更新
  Note over ECR: deploy/runtime では<br/>digest 固定で参照

注: このリポジトリでコード化されているのは署名ステータス確認(DescribeImageSigningStatus)です。
署名付与そのもの(ECR managed signing の有効化)は、ECR 側の設定・運用が前提です。

CodeBuild の build/push では運用上のタグを使用できますが、Terraform に渡す ecs_image_uri と Step Functions が署名確認する対象は常にダイジェスト固定(@sha256:<64-hex>)です。これにより、タグの上書きによるイメージのすり替えを防止します。

実行前確認

Step Functions ステートマシンの最初のステートで、check-image-signature Lambda がイメージの署名ステータスを確認します。

stateDiagram-v2
  [*] --> VerifyImageSignature: Step Functions 開始
  VerifyImageSignature --> CheckSignatureResult

  state CheckSignatureResult <<choice>>
  CheckSignatureResult --> RunProver: status = COMPLETE
  CheckSignatureResult --> SignatureFailed: status ≠ COMPLETE

  state SignatureFailed {
    [*] --> CallbackFailed: エラー情報を通知
  }

  state RunProver {
    [*] --> ECSTask: 署名ステータス確認済みイメージで実行
  }

check-image-signature Lambda は以下の処理を行います。

  1. ECR の DescribeImageSigningStatus API を呼び出す
  2. 指定されたリポジトリ名とイメージダイジェストに対する署名ステータスを取得
  3. 取得した statusCOMPLETE / それ以外)を Step Functions に返す

署名ステータスが COMPLETE でない場合、Step Functions の Choice ステートが FinalizeSignatureFailed に遷移し、コールバック Lambda に ImageSignatureVerificationFailed エラーを通知します。ECS タスクは一切起動されません。

ステータス確認と暗号学的検証の違い 本システムの実行前チェックは、ECR の DescribeImageSigningStatus API が返す署名ステータス(COMPLETE / それ以外)を確認するものであり、署名値そのものの暗号学的検証(署名の正当性確認や証明書チェーンの検証)ではありません。 これは、AWS ECR が署名のステータス照会 API は提供する一方、署名を暗号学的に独立検証する API を提供していないことによるものです。ECR managed signing の信頼モデルは、署名の付与・管理を AWS インフラに委任し、利用者はステータスを参照する設計です。 独立した署名検証が必要な場合は、Notation 等の外部ツールの併用が選択肢となります。

ECR リポジトリとイメージ管理

リポジトリ構成

リポジトリ用途ライフサイクル
stark-ballot-simulator/zkvm-prover-{env}プローバーコンテナイメージ最新 10 イメージを保持
stark-ballot-simulator/risc0-toolchainRISC Zero ツールチェーンベースイメージ最新 5 イメージを保持

両リポジトリとも、プッシュ時の脆弱性スキャン(Scan on Push)が有効です。

ダイジェスト固定

Terraform の ecs_image_uri 変数には、ダイジェスト固定の URI のみが許可されます。バリデーションルールにより @sha256:<64-hex> 形式が強制されます。

Step Functions の定義に含まれるイメージダイジェストは、Terraform の変数から以下のように抽出されます。

  • リポジトリ名: URI の @ より前の部分からレジストリホストを除去
  • ダイジェスト: URI の @ より後の部分(sha256:...

この分解により、check-image-signature Lambda は正確なリポジトリとダイジェストの組み合わせで署名ステータスを確認できます。

ビルドパイプライン

CodeBuild プロジェクト

2 つの CodeBuild プロジェクトがイメージのビルドを担当します。

プロジェクトビルド対象タイムアウトインスタンス
stark-ballot-simulator-fargate-prover-{env}プローバーイメージ30 分ARM64 Small
stark-ballot-simulator-risc0-toolchain-builderベースイメージ120 分ARM64 Large

RISC Zero ツールチェーンのビルドは低頻度(ツールチェーンバージョン更新時のみ)ですが、ビルドに時間を要するため Large インスタンスと長いタイムアウトが設定されています。

CodeBuild の IAM 権限

CodeBuild ロールには以下の権限が付与されています。

権限カテゴリ対象 API目的
ECRGetAuthorizationToken, PutImageイメージのプッシュ
AWS SignerSignPayload, GetSigningProfile署名連携用の権限(運用/拡張時)
CloudWatch LogsCreateLogGroup, PutLogEventsビルドログの出力
S3GetObject, PutObjectビルドアーティファクト
CodeStar Connectionscodestar-connections:UseConnection, GetConnectionToken接続方式切り替えに備えた権限(現行 CodeBuild source は GITHUB

Image ID との関係

イメージ署名と Image ID は異なるレイヤのセキュリティメカニズムですが、共に「正しいプログラムが実行されたこと」の信頼チェーンを構成します。

flowchart TD
  subgraph "ビルド時"
    BUILD["コンテナイメージ<br/>ビルド"] --> SIGN["AWS Signer で<br/>イメージ署名"]
    BUILD --> IMGID["Image ID 計算<br/>(ゲストバイナリから導出)"]
    IMGID --> MAP["imageId-mapping.json<br/>に記録"]
  end

  subgraph "実行時"
    VERIFY_SIG["イメージ署名ステータス確認<br/>(Step Functions)"] --> RUN["プローバー実行"]
    RUN --> RECEIPT["レシート生成<br/>(Image ID を含む)"]
  end

  subgraph "検証時"
    RECEIPT --> VERIFY_RECEIPT["レシート検証<br/>(verifier-service)"]
    MAP --> VERIFY_RECEIPT
    VERIFY_RECEIPT --> MATCH{"Image ID<br/>一致?"}
  end

  SIGN --> VERIFY_SIG
検証ポイントタイミング検証主体失敗時の動作
イメージ署名証明生成前Step Functions + LambdaECS タスクの起動拒否
Image ID 照合検証時verifier-service検証失敗の報告