1. ソフトウェアサプライチェーンセキュリティの課題とAWS Signerの全体像

ビルドしたコードやコンテナイメージが、改ざんされずに本番環境へ届いている保証はあるでしょうか。ビルドパイプラインの侵害・レジストリへの不正イメージ混入・依存パッケージの汚染といったソフトウェアサプライチェーン攻撃に対し、コード/アーティファクトの署名と検証で完全性を保証するのがAWS Signerです。
本セクションでは、サプライチェーンセキュリティの本番課題を整理したうえで、AWS Signerの全体像・署名検証の意義・本記事全体の構成を説明します。
- AWS Signer基礎 — 署名プロファイル/署名ジョブ/署名プラットフォーム/鍵・PKI管理(§2)
- Lambdaコード署名 — Code Signing Configuration/署名検証/デプロイ強制(§3)
- コンテナ/OCIアーティファクト署名 — Notation/CNCF Notary統合/ECR署名(§4)
- 失効・信頼・検証 — 署名失効/Trust Store/検証ワークフロー(§5)
- CI/CD統合・運用・コストとSLSA準拠の全体設計(§6・§7)
- KMS/CloudHSM — 暗号鍵の保護・管理(鍵そのもの)
- IAM Roles Anywhere — ワークロードのアイデンティティ(誰がアクセスするか)
- AWS Signer — コード/アーティファクトの署名・検証(何がデプロイされるか)
- 本記事はサプライチェーン完全性に集中。鍵保護・ID基盤は既存記事を参照
1-1. サプライチェーン攻撃の脅威とコード署名の意義
2020年に発覚したSolarWindsサプライチェーン攻撃では、ビルドサーバーに侵入したマルウェアが正規のOrion製品のビルドプロセスに組み込まれ、デジタル署名済みのアップデートパッケージとして18,000社以上の顧客へ配布されました。このケースでは、「署名済みであること」ではなく「正規のビルドプロセスで生成されたか」「ビルド後に改ざんされていないか」の検証が重要だと改めて示されました。
2021年末に公開されたLog4Shell(CVE-2021-44228)は、Javaで広く利用されるOSSライブラリLog4jの脆弱性が、それを利用する無数のアプリケーションに波及した事例です。RCE脆弱性が直接の問題ですが、組織が利用するすべての依存パッケージを把握・管理できていなかった点で、サプライチェーン可視性の課題を浮き彫りにしました。
こうした教訓から、デプロイされる成果物の完全性を継続的に保証する仕組みが不可欠になっています。ビルド後からデプロイまでの「最後の1マイル」を守ることが、現代のDevSecOpsの重要テーマとなっています。
ソフトウェアサプライチェーンセキュリティの現状
Cloud Security Alliance(CSA)の調査では、組織の62%がサプライチェーン攻撃を「最大の脅威」と認識しているにもかかわらず、コード署名を体系的に導入している組織は30%未満にとどまるという報告があります。多くの組織でCI/CDパイプラインの整備が進む一方、「ビルドが通れば安全」という前提の下、デプロイ前の成果物検証が後回しにされているのが実情です。
AWS環境でのサプライチェーンリスクの特徴として、マネージドサービスへの依存度の高さが挙げられます。LambdaのデプロイやECSタスク更新は非常に手軽で実行しやすいため、未検証の成果物が本番環境へ混入しやすい構造になっています。コード署名をパイプラインに組み込むことで、この手軽さを維持しながらも、成果物の改ざん検知ゲートを自動的に設けられます。
ソフトウェアサプライチェーン攻撃の主な経路
第1の経路はビルドパイプラインの侵害です。CIサーバーやビルド環境そのものが攻撃対象になります。ビルドスクリプトの改ざん、ビルド環境へのマルウェア注入、依存パッケージのバージョン固定の回避などが知られた手口です。ビルド環境の隔離・最小権限設計・ビルド成果物への署名を組み合わせて対策します。
第2の経路はコンテナレジストリへの不正イメージ混入です。ECRやDockerHubなどのコンテナレジストリへの不正なイメージのアップロードや、正規イメージへの悪意あるレイヤーの追加が該当します。コンテナイメージへの署名と、デプロイ時の署名検証でリスクを低減できます。
第3の経路は依存パッケージの汚染(タイポスクワッティング)です。npm・PyPI・Maven Centralなどのパッケージレジストリに、正規パッケージとよく似た名前の悪意あるパッケージを公開する攻撃です。依存関係のロックファイル管理とSBOM(ソフトウェア部品表)の整備が有効な対策になります。
コード署名と検証で実現できること
コード署名は成果物に対して2点を保証します。発元の保証として「誰が署名したか」を証明し、完全性の保証として「署名後に改ざんされていないか」を検証します。デプロイ時に署名を検証することで、ビルド完了からデプロイまでの間の改ざんを確実に検知できます。署名鍵が適切に保護されていれば、たとえビルドサーバーが侵害されても、攻撃者は正規の署名を偽造できません。
暗号化と署名の目的の違いも重要です。暗号化はデータの機密性(許可された者しか読めない)を守るのに対し、署名はデータの完全性と発元(誰が署名したか・署名後に改ざんされていないか)を保証します。AWS Signerはコード/アーティファクトの署名と検証に特化したマネージドサービスです。
SLSAフレームワークとの関係
SLSA(Supply chain Levels for Software Artifacts)は、Googleが主導するサプライチェーンセキュリティのフレームワークで、4段階のレベルを定義しています。
SLSA Level 1では、自動化されたビルドプロセスと来歴ドキュメントの生成が求められます。SLSA Level 2では、認証されたビルドサービスと改ざん不可能な来歴の保証が基準となります。SLSA Level 3では、信頼されたビルドプラットフォームと来歴の完全な透明性が必要です。SLSA Level 4は2者検証と再現可能ビルドを基準とする最高レベルで、現時点では理想的な目標基準とされています。
AWS Signerは、SLSA L2〜L3のコード署名要件を満たすためのコアコンポーネントとして機能します。AWS CodeBuildの署名済み来歴(Signed Provenance)とAWS Signerの署名を組み合わせることで、「このビルドアーティファクトは、この日時に、このコミットから、認証されたビルドサービスで生成された」という証跡を保証できます。
本記事の構成案内
Vol1では、AWS Signerの基礎から実践的な署名・検証・CI/CD統合・SLSA準拠設計まで一気通貫で解説します。署名プロファイル・署名ジョブの基礎(§2)から始まり、Lambdaのコード署名強制(§3)、コンテナ/OCIアーティファクト署名(§4)、失効と信頼管理(§5)、CI/CD統合と運用・コスト(§6)、SLSA準拠の全体設計(§7)、詰まりポイントとまとめ(§8)で構成しています。
AWS Signerを使うメリット
AWSマネージドサービスとして提供されるAWS Signerは、秘密鍵の保管・ローテーション・証明書発行をAWSが担います。自前でPKIを構築・運用するコストを省きながら、コード署名のベストプラクティスを実装できます。また、IAMポリシーによる署名権限の制御、CloudTrailによる署名操作の監査ログ、そして既存のCI/CDサービス(CodePipeline・CodeBuild・GitHub Actions)との容易な統合が、エンタープライズレベルの運用を支えます。
署名はAWS SignerサービスのエンドポイントへのAPI呼び出しで実行され、署名された成果物はS3またはECRに保管されます。Lambda Code Signing ConfigurationやNotationの信頼ポリシーと連携することで、署名検証はデプロイの自然なゲートとして機能し、開発フローへの摩擦を最小限に抑えながらサプライチェーン保護を実現できます。
東京リージョン(ap-northeast-1)を含む複数のAWSリージョンでAWS Signerは利用可能です。リージョンをまたいだデプロイ構成では、デプロイ先リージョンのSignerエンドポイントを使用することを推奨します。
1-2. 読者像
本記事の対象読者は、AWSでLambdaやコンテナワークロードを本番運用し、デプロイされる成果物の改ざん検知とサプライチェーン完全性の担保を求めるプラットフォームエンジニアおよびセキュリティエンジニアです。
次のような課題感を持つ読者を想定しています。ビルドパイプラインに署名ゲートを組み込み、未署名や改ざんされた成果物が本番環境へデプロイされるリスクを排除したいエンジニアが主な対象です。SOC2・ISO27001・FedRAMPなど、ソフトウェアサプライチェーンのセキュリティ管理を求めるコンプライアンス要件への対応が必要な組織にとっても役立つ内容です。また、SLSAフレームワークへの準拠を段階的に進め、ソフトウェア来歴の追跡可能性とビルドの完全性を高めたいチームにも有用です。
前提知識として、LambdaのデプロイメントパッケージやDockerコンテナイメージの基礎、AWS IAMの権限管理の基礎を理解していることを想定しています。暗号署名の詳細な数学的知識は不要ですが、公開鍵・秘密鍵の概念を理解しているとより深く読めます。鍵保護の設計はCloudHSM記事を、CI/CDランナーのアイデンティティ管理はIAM Roles Anywhere記事をそれぞれ参照してください。
本記事が特に役立つ場面として、次のようなシナリオが挙げられます。本番Lambdaのデプロイ権限を複数のエンジニアが保持している組織で、署名済み関数のみをデプロイ可能にする仕組みを検討している場合、§2〜§3が直接参考になります。EKSやECSでコンテナイメージの来歴を検証するAdmission Controllerを導入したい場合、§4が詳細な実装ガイドになります。コンプライアンス監査のためにデプロイ時の署名証跡をCloudTrailに記録したい場合は、§6-2の監査ログ設計が参考になります。
セキュリティエンジニアとして既存のCI/CDパイプラインにサプライチェーン保護を後付けで組み込みたい場合も本記事が対象です。AWS Signerはマネージドサービスのため既存のインフラを大きく変更せずに導入でき、署名プロファイルとCodeBuild/GitHub Actionsの統合だけで運用を始めることが可能です。段階的な導入(WarnモードからEnforceモードへ)もサポートされているため、既存のデプロイフローを壊さずに保護レベルを段階的に引き上げられます。
1-3. AWS Signerと既存セキュリティの使い分け
AWSのセキュリティサービスはそれぞれ異なる「何を守るか」に特化しています。AWS Signerの役割を明確化するため、関連サービスとの使い分けを整理します。
サービスの役割比較
| サービス | 守るもの / 保証するもの | 主なユースケース |
|---|---|---|
| AWS KMS | 暗号鍵の保護・管理 | データ暗号化・復号・鍵ローテーション |
| AWS CloudHSM | 専有HSMによる鍵の完全管理 | FIPS 140-3 L3準拠・顧客専有鍵 |
| IAM Roles Anywhere | ワークロードのアイデンティティ | オンプレ/ハイブリッドの長期キー廃止 |
| AWS Signer | コード/アーティファクトの完全性 | Lambda/コンテナ署名・SLSA準拠 |
KMSとCloudHSMは「鍵そのもの」を守るサービスです。AWS Signerはマネージドな鍵ペアを提供し、鍵管理をAWSが担うため、利用者はPKI運用を意識せずに署名と検証に集中できます。
IAM Roles AnywhereはビルダーやCI/CDランナーの「誰がアクセスするか」というアイデンティティを管理します。ビルドサーバーがRoles Anywhereで認証し、AWS SignerのAPIを呼び出して成果物に署名するという組み合わせが、典型的なセキュリティ連環のパターンです。
本記事はAWS Signerの署名・検証機能に集中して解説します。鍵保護の詳細設計はCloudHSM記事を、CI/CDランナーのアイデンティティ管理はIAM Roles Anywhere記事をそれぞれ参照してください。§7でこれらの連携パターンをSLSA準拠の全体設計として統合します。
AWS Signerを選択するタイミング
次のいずれかに該当する場合、AWS Signerの導入を優先して検討することを推奨します。
- Lambda関数を複数チームが並行開発しており、誰が署名した関数だけを本番デプロイ可能にしたい
- ECRのコンテナイメージに署名を付与し、Kubernetesクラスターや ECSデプロイ前に改ざん検知ゲートを設けたい
- SOC2・ISO27001・FedRAMPなどの監査対応として、デプロイ成果物の完全性証跡が必要
- SLSA L2〜L3準拠を段階的に達成し、ソフトウェア来歴の追跡可能性を高めたい
逆に、単純なIAMロール管理の強化やネットワーク通信の暗号化が主な課題であれば、それぞれ専用サービスの活用を先に検討してください。AWS Signerはあくまでもコード/アーティファクトの完全性保証に特化したサービスです。
AWS Signerが対応する成果物と統合先
AWS Signerが署名する成果物と統合先を整理します。
| 成果物の種類 | 署名プラットフォームID | 主な統合先 |
|---|---|---|
| Lambda デプロイパッケージ(Zip) | AWSLambda-SHA384-ECDSA | Code Signing Configuration(Lambda) |
| コンテナ/OCIアーティファクト | Notation-OCI-SHA384-ECDSA | ECR・Kubernetes Admission Controller・ECS |
署名プロファイルは複数作成でき、環境(開発・本番)やチーム(バックエンド・フロントエンド)ごとに分離して管理できます。クロスアカウント署名もサポートしており、中央の署名アカウントから各本番アカウントへのデプロイに署名ゲートを設けるマルチアカウント設計も可能です。§2以降でこれらの具体的な設定方法を解説します。
2. AWS Signer基礎 — 署名プロファイル × 署名ジョブ × 署名プラットフォーム
![fig02: AWS Signerの署名プロファイルと署名ジョブのフロー(署名プロファイルで署名プラットフォーム[Lambda Zip用AWSLambda-SHA384-ECDSAやコンテナ用Notation-OCI-SHA384-ECDSA]と鍵を定義し、署名ジョブが成果物に署名する。AWSが署名証明書と秘密鍵を管理する構成)](https://www.watchittrend.com/wp-content/themes/the-thor/img/dummy.gif)
AWS Signerは、署名プロファイル・署名ジョブ・署名プラットフォームの3要素で構成されます。本セクションでは、各要素の役割と署名鍵の管理方針を解説します。
2-1. 署名プロファイル(Signing Profile)
署名プロファイルは、AWS Signerにおける署名設定の中核リソースです。「どの署名プラットフォームを使い、どの期間有効な証明書で署名するか」を定義します。署名ジョブを実行するときは必ず署名プロファイルを指定します。これにより、個々のジョブが同一の設定・鍵コンテキストで動作することを保証します。
プロファイルの主要設定項目
| 設定項目 | 説明 |
|---|---|
| 署名プラットフォームID | Lambda署名用・OCI署名用などの対象を指定 |
| 署名有効期間 | 最大135ヶ月。証明書の有効期限に相当 |
| プロファイルバージョン | 署名のたびに自動でバージョン付きARNが生成 |
| ステータス | Active / Revoked / Expired の3状態 |
署名プロファイルは、作成時点で固有のARN(arn:aws:signer:<region>:<account>:/signing-profiles/<profileName>)が割り当てられます。このARNをCode Signing Configuration(Lambda)やNotation信頼ポリシー(コンテナ)に紐付けることで、「どの署名者が生成した署名のみを信頼するか」を明示的にコントロールできます。
プロファイルのライフサイクルとバージョン管理
署名プロファイルには、署名実行ごとにバージョンが付与されます。バージョン付きARNは arn:aws:signer:<region>:<account>:/signing-profiles/<profileName>/revisions/<versionId> の形式です。コンソールやCLIでプロファイルのバージョン一覧を確認でき、どのバージョンで署名されたかを追跡できます。
# 署名プロファイルの作成
aws signer put-signing-profile \
--profile-name MyLambdaSigningProfile \
--platform-id AWSLambda-SHA384-ECDSA \
--signature-validity-period "value=12,type=MONTHS"
# 署名プロファイルの一覧
aws signer list-signing-profiles
# 特定プロファイルの詳細取得
aws signer get-signing-profile \
--profile-name MyLambdaSigningProfile
クロスアカウント署名
組織内で署名専用アカウントを設け、開発アカウントからクロスアカウントで署名プロファイルを利用する構成は、ベストプラクティスの一つです。署名プロファイルのリソースベースポリシーに signer:StartSigningJob の許可を別アカウントのロールへ付与することで、署名鍵の管理権限と実行権限を分離できます。
# クロスアカウント署名プロファイルポリシーの設定
aws signer add-profile-permission \
--profile-name MyLambdaSigningProfile \
--action "signer:StartSigningJob" \
--principal "arn:aws:iam::111122223333:root" \
--revision-id <version-id> \
--statement-id AllowDevAccount
開発アカウント側では、このプロファイルARNを直接指定して署名ジョブを開始します。署名証明書と秘密鍵は署名専用アカウント(Signer管理)に閉じており、開発者は鍵を意識せずに署名できます。
プロファイルの失効(Revoke)
署名プロファイルを失効させると、そのプロファイルで新たな署名ジョブは実行できなくなります。ただし、失効前に生成した署名の有効性は「失効有効日時(revocationEffectiveOn)」以前の署名については保持されます。失効後は同名で再作成せず、別名プロファイルを新規作成して切り替えることを推奨します。同名再作成は失効前後の署名検証を混乱させるため避けてください。
2-2. 署名プラットフォームと署名ジョブ
署名プラットフォームは、「何に署名するか」「どのアルゴリズムを使うか」を定義したマネージド設定です。AWS Signerはいくつかのプラットフォームを用意しており、対象成果物に応じて選択します。
主要な署名プラットフォームID
| Platform ID | 対象 | 署名アルゴリズム |
|---|---|---|
AWSLambda-SHA384-ECDSA | Lambda .zip デプロイバンドル | ECDSA P-384 + SHA-384 |
Notation-OCI-SHA384-ECDSA | コンテナ/OCIアーティファクト | ECDSA P-384 + SHA-384 |
AmazonFreeRTOS-TI-CC3220SF | FreeRTOS(TI CC3220SF) | ECDSA P-384 + SHA-256 |
AmazonFreeRTOS-Default | FreeRTOS(汎用) | ECDSA P-256 + SHA-256 |
Lambdaの.zipファイル署名には AWSLambda-SHA384-ECDSA を、コンテナイメージやOCIアーティファクトへのNotation署名には Notation-OCI-SHA384-ECDSA を使用します。いずれもECDSA P-384 + SHA-384の組み合わせで、FIPS 140に対応した強度を持ちます。
署名ジョブの実行フロー
署名ジョブは StartSigningJob API(または aws signer start-signing-job CLI)で実行します。Lambdaの場合、署名対象の.zipをS3に配置し、署名済み成果物の出力先S3バケットを指定します。
# Lambda .zip の署名ジョブを実行
aws signer start-signing-job \
--source "s3={bucketName=my-source-bucket,key=function.zip,version=abc123}" \
--destination "s3={bucketName=my-signed-bucket,prefix=signed/}" \
--profile-name MyLambdaSigningProfile
# 署名ジョブのステータス確認
aws signer describe-signing-job \
--job-id <job-id>
署名ジョブのステータスは InProgress → Succeeded / Failed / TimedOut に遷移します。Succeededになった成果物は指定した出力先S3バケットに配置されます。
Notation によるコンテナイメージ署名
コンテナイメージへの署名は、Notation CLIとAWS Signerプラグイン(notation-plugin-aws-signer)を使います。ECRにプッシュしたイメージに対して以下のように実行します。
# AWS SignerプロファイルでコンテナイメージへNotation署名
notation sign \
<account>.dkr.ecr.<region>.amazonaws.com/my-repo@sha256:<digest> \
--plugin com.amazonaws.signer.notation.plugin \
--id arn:aws:signer:<region>:<account>:/signing-profiles/MyContainerProfile
署名はイメージダイジェスト(sha256:<digest>)に付与されるため、タグ変更で署名が無効になることはありません。OCIアーティファクトとしてECRに保存されるため、EKS/ECSのデプロイ時にNotation検証ポリシーで検証できます。
署名ジョブの監査
すべての署名ジョブはCloudTrailに StartSigningJob イベントとして記録されます。ジョブID・プロファイル名・実行者・タイムスタンプが証跡に残るため、「いつ・誰が・どの成果物を署名したか」を追跡できます。
2-3. 署名鍵とPKI管理
AWS Signerの特徴は、AWSが署名証明書と秘密鍵を完全に管理することです。開発者は秘密鍵に直接アクセスできません。これにより、鍵の漏洩リスクと属人的な鍵管理を排除します。
鍵アルゴリズムと証明書の構造
AWS Signerが発行する署名証明書はECDSA P-384 + SHA-384を採用しています。AWSがX.509証明書を発行し、AWSの中間CA(Certificate Authority)が署名します。証明書には署名プロファイル名・プロファイルARN・アカウントIDが含まれており、検証時にアイデンティティをトレースできます。
鍵ローテーション
署名プロファイルは「鍵を更新」するのではなく、「新しいプロファイルを作成して切り替える」設計です。有効期間が近づいたら新しいプロファイルを作成し、Code Signing ConfigurationやNotation信頼ポリシーの参照先を更新します。古いプロファイルで生成した署名は失効させるまでは有効であるため、ローテーション期間中は両プロファイルを許可リストに含めておけば無停止に切り替えられます。
IAM権限の最小化
| IAM アクション | 用途 |
|---|---|
signer:StartSigningJob | 署名ジョブの実行 |
signer:DescribeSigningJob | ジョブステータスの確認 |
signer:GetSigningProfile | プロファイル情報の取得 |
signer:PutSigningProfile | プロファイルの作成・更新 |
signer:RevokeSignature | 署名の失効 |
signer:RevokeSigningProfile | プロファイルの失効 |
CI/CDパイプラインには signer:StartSigningJob と signer:DescribeSigningJob のみを付与します。プロファイルの作成・失効は署名管理者ロールに限定することで、権限を最小化できます。
外部PKIとCloudHSMの位置づけ
自社PKI基盤の証明書でコンテナイメージに署名したい場合は、Notationの外部鍵管理(外部CA証明書)を使うことでAWS Signerを経由せずに署名できます。ただし、鍵管理・ローテーション・CRL(失効リスト)の運用が自社負担になります。専有HSMでの署名鍵保護を要する規制要件がある場合は、CloudHSMとの統合も検討してください(詳細は関連記事「AWS CloudHSM 専有HSM/鍵管理 本番運用 Vol1」を参照)。
署名証明書のメタデータとCloudTrail監査
AWS Signerが発行した署名証明書には、署名プロファイル名・プロファイルARN・AWSアカウントID・リージョンが含まれています。検証時にこれらのメタデータを確認することで、「どの組織のどのチームが署名したか」を正確にトレースできます。
CloudTrailには以下のイベントが記録されます。
| イベント名 | トリガー |
|---|---|
StartSigningJob | 署名ジョブの開始 |
GetSigningJob | ジョブ状態の参照 |
PutSigningProfile | 署名プロファイルの作成・更新 |
RevokeSignature | 署名の失効 |
RevokeSigningProfile | プロファイルの失効 |
これらのイベントをAmazon Athenaやセキュリティ情報イベント管理(SIEM)に集約することで、署名操作の網羅的な監査証跡を構築できます。監査証跡は、コンプライアンス要件(SOC 2・ISO 27001・PCI DSS)を満たすための重要な証拠になります。
3. Lambdaコード署名 — Code Signing Configuration × デプロイ強制
![fig03: Lambdaコード署名のフロー(AWS Signerで署名したLambdaデプロイバンドルを、Lambda関数に紐づけたCode Signing Configuration[許可署名プロファイルと検証ポリシーWarn/Enforceを定義]が検証し、未署名や検証失敗のデプロイを拒否して管理者と開発者の職務分離を実現する構成)](https://www.watchittrend.com/wp-content/themes/the-thor/img/dummy.gif)
Lambdaはコード署名を組み込みでサポートし、署名されたコードのみのデプロイを強制できます。本セクションでは、Code Signing Configurationとデプロイ強制を解説します。
3-1. Code Signing Configuration(CSC)
Code Signing Configuration(CSC)は、Lambda関数に紐付けるリソースで、「どの署名プロファイルで署名されたコードを受け入れるか」と「検証失敗時の振る舞い」の2つを定義します。
CSCの核心は許可署名プロファイル(Allowed Signing Profiles)です。1つのCSCに複数の署名プロファイルARNを登録でき、そのいずれかで署名されたコードのみがデプロイ可能になります。登録されていない署名プロファイルで署名されたコードや、署名のないコードはデプロイを拒否または警告できます。
Platform ID: AWSLambda-SHA384-ECDSA
Lambda向けの署名プラットフォームIDはAWSLambda-SHA384-ECDSAです。このプラットフォームはLambda ZIPデプロイメントパッケージの署名に特化しており、SHA-384ハッシュとECDSA署名アルゴリズムを使用します。コンテナイメージには別のプラットフォーム(Notation-OCI-SHA384-ECDSA)を使用します。
# AWSLambda-SHA384-ECDSAプラットフォームの詳細を確認
aws signer get-signing-platform \
--platform-id AWSLambda-SHA384-ECDSA
# このプラットフォームで署名プロファイルを作成
aws signer put-signing-profile \
--profile-name ProdLambdaSigningProfile \
--platform-id AWSLambda-SHA384-ECDSA \
--signature-validity-period '{"value": 135, "type": "DAYS"}'
職務分離(Separation of Duties)の実装
CSCは管理者と開発者の職務分離を実現するための中心的リソースです。一般的な分離パターンは次のとおりです。
| 役割 | 許可するIAMアクション | 禁止するアクション |
|---|---|---|
| セキュリティ/プラットフォームチーム | signer:PutSigningProfile・lambda:CreateCodeSigningConfig・lambda:PutFunctionCodeSigningConfig | 開発コードへの直接アクセス |
| 開発チーム | signer:StartSigningJob(指定プロファイルのみ) | lambda:PutFunctionCodeSigningConfig(CSC変更不可) |
| CI/CDシステム | signer:StartSigningJob・lambda:UpdateFunctionCode | signer:PutSigningProfile(プロファイル変更不可) |
この分離により、開発者が誤って未署名コードをデプロイしても、CSCのEnforceモードが拒否します。また、CI/CDシステムが侵害されても、署名プロファイル自体の変更には管理者権限が必要なため、悪意ある署名プロファイルへの差し替えを防げます。
CSCの作成手順
コンソールまたはCLIでCSCを作成します。
# 署名プロファイルのバージョンARNを取得
PROFILE_VERSION_ARN=$(aws signer get-signing-profile \
--profile-name ProdLambdaSigningProfile \
--query 'arn' --output text)
# Code Signing Configurationを作成
aws lambda create-code-signing-config \
--description "Lambda prod code signing config" \
--allowed-publishers "{\"SigningProfileVersionArns\": [\"$PROFILE_VERSION_ARN\"]}" \
--code-signing-policies '{"UntrustedArtifactOnDeployment": "Enforce"}'
UntrustedArtifactOnDeploymentにはWarnまたはEnforceを指定します(詳細は次項)。
Lambda関数への紐付け
CSCをLambda関数に紐付けるにはPutFunctionCodeSigningConfig APIを使います。
# CSC ARNを取得
CSC_ARN=$(aws lambda list-code-signing-configs \
--query 'CodeSigningConfigs[0].CodeSigningConfigArn' \
--output text)
# Lambda関数にCSCを紐付け
aws lambda put-function-code-signing-config \
--function-name my-lambda-function \
--code-signing-config-arn "$CSC_ARN"
# 紐付け確認
aws lambda get-function-code-signing-config \
--function-name my-lambda-function
紐付け後は、その関数へのすべてのUpdateFunctionCode呼び出しで署名検証が実行されます。
デプロイ時の署名検証フロー
CSCを紐付けたLambda関数へのデプロイ時、次の順序で署名検証が行われます。
UpdateFunctionCodeAPIが呼び出される- LambdaサービスがデプロイZIPの署名を取得する
- 署名プロファイルがCSCの許可リストに含まれているか確認する
- 署名のタイムスタンプが有効期間内か確認する
- 署名とコードのダイジェストが一致するか確認する
- すべてのチェックが通れば関数コードを更新し、失敗すれば(Enforceの場合)
CodeSigningConfigMismatchExceptionを返す
この一連のチェックはLambdaサービス内で自動実行されるため、デプロイパイプライン側に追加の実装は不要です。
Layerへの署名適用
Lambda Layerにも同じCSCの署名検証を適用できます。共有ライブラリ(共通依存パッケージ等)をLayerとして配布する際に、Layerの完全性も保証できます。
# 署名ジョブを実行してLayerに署名
aws signer start-signing-job \
--source 's3={bucketName=my-signing-bucket,key=input/layer.zip,version=latest}' \
--destination 's3={bucketName=my-signing-bucket,prefix=output/}' \
--profile-name ProdLambdaSigningProfile
# 署名済みLayerを発行
aws lambda publish-layer-version \
--layer-name my-signed-layer \
--content 's3Bucket=my-signing-bucket,s3Key=output/layer.zip' \
--compatible-runtimes python3.11 python3.12
署名プロファイルの鍵ローテーション対応
署名プロファイルを更新(鍵ローテーション)すると新バージョンが作成されます。CSCには古いバージョンのARNが登録されているため、新バージョンのARNを追加してCSCを更新する必要があります。移行期間中は新旧両バージョンをCSCの許可リストに並存させ、旧バージョンでのデプロイが停止したことを確認してから旧バージョンを削除します。
# CSCを新旧両バージョンで更新(移行期間用)
aws lambda update-code-signing-config \
--code-signing-config-arn "$CSC_ARN" \
--allowed-publishers \
"{\"SigningProfileVersionArns\": [\"$OLD_VERSION_ARN\", \"$NEW_VERSION_ARN\"]}"
3-2. 署名検証ポリシー(Warn / Enforce)
CSCのUntrustedArtifactOnDeploymentに設定する値によって、署名検証に失敗した場合の振る舞いが大きく異なります。
Warnモード(Warn)
Warnモードでは、未署名または検証失敗のコードでもデプロイが完了します。ただし、CloudWatchにwarningが記録され、EventBridgeからアラームを設定できます。
Warnモードの活用シーン:
– CSCを初めて導入し、既存関数を段階的に移行する際
– 開発環境でCSCの振る舞いを確認しながら試験的に適用する際
– 署名パイプラインを構築中で、一時的に強制を緩める際
Warnモードでも、CSCは署名を検証してCloudTrailへ詳細を記録します。検証結果を後から監査できるため、未署名デプロイを把握したうえでEnforceへ移行するタイミングを判断できます。本番環境ではEnforceへの移行が強く推奨されます。
CloudWatchアラームの設定例:
# Lambda Code Signing失敗をアラームで通知
aws cloudwatch put-metric-alarm \
--alarm-name "LambdaCodeSigningValidationFailure" \
--metric-name "CodeSigningValidationFailure" \
--namespace AWS/Lambda \
--statistic Sum \
--period 300 \
--threshold 1 \
--comparison-operator GreaterThanOrEqualToThreshold \
--evaluation-periods 1 \
--alarm-actions "arn:aws:sns:ap-northeast-1:123456789012:security-alerts"
Enforceモード(Enforce)
Enforceモードでは、未署名または検証失敗のコードをデプロイしようとすると、CodeSigningConfigMismatchExceptionが返り、関数コードの更新が拒否されます。本番環境では原則Enforceモードを使用します。
検証失敗のケース:
– 署名がない(未署名コードのデプロイ試行)
– 署名プロファイルがCSCの許可リストに含まれていない
– 署名が改ざんされている(コードと署名のダイジェストが一致しない)
– 署名プロファイルが失効している
– 署名の有効期限が切れている
# Enforceモードで未署名コードをデプロイしようとした場合のエラー例
aws lambda update-function-code \
--function-name my-lambda-function \
--zip-file fileb://unsigned-code.zip
# エラー: An error occurred (CodeSigningConfigMismatchException)
# Lambda cannot deploy the function. The function or layer might be unsigned,
# or the signing profile might be revoked.
段階導入の推奨パターン
既存のLambda関数にCSCを導入する際は、段階的なアプローチを推奨します。
- 評価フェーズ(Warnモード): すべての対象Lambda関数にCSCをWarnモードで紐付けます。CloudWatchで未署名デプロイの頻度を1〜2週間計測し、移行対象の規模を把握します。
- パイプライン整備フェーズ: CI/CDパイプラインにSigner署名ジョブを組み込み、すべての関数で署名付きデプロイが成功することを確認します。
- Enforceへ移行: 署名パイプラインが安定したら
UntrustedArtifactOnDeploymentをEnforceに更新します。
# WarnからEnforceへ切り替え
aws lambda update-code-signing-config \
--code-signing-config-arn "$CSC_ARN" \
--code-signing-policies '{"UntrustedArtifactOnDeployment": "Enforce"}'
Warnモード中は未署名デプロイが発生するたびにCloudTrailへ記録されます(デプロイは成功)。このログを使って「移行が完了したかどうか」をデータに基づいて判断できるため、Enforceへの切り替えタイミングを確信を持って実行できます。
3-3. バージョン管理とデプロイ強制
Lambda バージョン × 署名の整合性
Lambda関数はPublishVersionで不変バージョンを作成します。署名検証はUpdateFunctionCode時点で実行されます。これにより、バージョンごとに「いつ、誰の署名で、どのコードがデプロイされたか」の完全な証跡が残ります。
# 署名済みコードをデプロイしてバージョンを発行
aws lambda update-function-code \
--function-name my-lambda-function \
--s3-bucket my-signing-bucket \
--s3-key output/signed-function.zip
aws lambda publish-version \
--function-name my-lambda-function \
--description "Signed release v1.2.3"
CloudTrailによる署名検証ログ
UpdateFunctionCodeのCloudTrailイベントには、CSCの情報が含まれます。セキュリティ監査ではAthenaを使ったCloudTrailログ検索が有効です。
-- Athenaで署名検証ログを確認
SELECT eventTime, userIdentity.arn, requestParameters.functionName,
responseElements.codeSigningConfigArn
FROM cloudtrail_logs
WHERE eventName LIKE 'UpdateFunctionCode%'
AND responseElements.codeSigningConfigArn IS NOT NULL
ORDER BY eventTime DESC
LIMIT 100;
署名有効期限の管理
署名プロファイルには有効期限(Signature Validity Period)を設定できます。有効期限を過ぎた署名でのデプロイはEnforceモードで拒否されます。長期運用するLambdaでは、署名プロファイルの有効期限とCI/CDの再署名スケジュールを整合させてください。
推奨設定:
– 本番プロファイル: 有効期間135日(ローテーション頻度: 120日ごと)
– 開発プロファイル: 有効期間30日(短期テスト用)
期限切れ間近の署名プロファイルをEventBridgeで検知するには、signer:SigningProfileStatusChangeイベントを使用します。
# 署名プロファイルの有効期限を確認
aws signer get-signing-profile \
--profile-name ProdLambdaSigningProfile \
--query '{ValidityPeriod: signatureValidityPeriod, Status: status}'
緊急時の署名プロファイル失効
署名鍵の漏洩や不正署名が疑われる場合、署名プロファイルを即座に失効させることで、そのプロファイルで署名されたコードのデプロイを止められます。失効はEnforceモードでのみ即座に効力を発揮します。
# 署名プロファイルを失効(緊急対応)
aws signer revoke-signing-profile \
--profile-name CompromisedSigningProfile \
--profile-version abcdef1234 \
--reason "Signing key compromise detected" \
--effective-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
失効後は新しい署名プロファイルを作成してCSCを更新し、既存のLambda関数を再デプロイする必要があります。CSCの許可リストから失効したプロファイルを削除し、新プロファイルを追加する更新手順を事前にインシデント対応手順書へ記載しておくことを推奨します。
IaC(Terraform/CloudFormation)でのCSC管理
CSCとLambda関数の紐付けをIaCで管理することで、環境間の一貫性を担保できます。
# Terraform: Code Signing ConfigurationとLambda関数の紐付け
resource "aws_lambda_code_signing_config" "prod" {
allowed_publishers {
signing_profile_version_arns = [
aws_signer_signing_profile.prod.arn
]
}
policies {
untrusted_artifact_on_deployment = "Enforce"
}
description = "Lambda prod code signing config"
}
resource "aws_lambda_function_code_signing_config" "my_function" {
code_signing_config_arn = aws_lambda_code_signing_config.prod.arn
function_name = aws_lambda_function.my_function.function_name
}
IaCによる管理では、CSCの設定変更がコードレビューのプロセスを経るため、意図しない署名ポリシーの緩和を防げます。
4. コンテナ/OCIアーティファクト署名 — Notation × CNCF Notary

コンテナイメージの署名は、AWS SignerとNotation(CNCF Notary Project)の統合で実現します。本セクションでは、Notation連携とECR署名を解説します。
4-1. Notation / CNCF Notary Project統合
Notationは、CNCF(Cloud Native Computing Foundation)が推進するNotary Projectの成果として生まれたオープンスタンダードのコンテナ署名CLIです。OCI(Open Container Initiative)仕様に準拠し、コンテナイメージや任意のOCIアーティファクトにデジタル署名を付与できます。AWS Signerとの統合では、Notationをクライアント側インターフェースとして活用しながら、PKI管理・秘密鍵の保護・署名証明書の発行をすべてAWS Signerに委譲できます。
AWS Signerプラグインの導入
Notationは署名・検証のオーケストレーションを担い、鍵管理はプラグイン経由で外部サービスへ委譲する設計です。AWS提供の公式プラグインnotation-aws-signerをインストールすると、Notation CLIがAWS Signerと連携してECRイメージの署名・検証ができます。
# Notation本体のインストール(macOS例)
brew install notation
# AWS Signerプラグインのダウンロードとインストール
notation plugin install \
--url https://d2hvyiie56hcat.cloudfront.net/darwin/amd64/plugin/latest/notation-aws-signer.tar.gz
# インストール済みプラグインの確認
notation plugin ls
# 出力例:
# NAMEDESCRIPTIONVERSIONCAPABILITIES ERROR
# com.amazonaws.signer.notation.pluginAWS Signer Plugin for Notation 1.0.298[SIGNATURE_GENERATOR.ENVELOPE]<nil>
プラグインの動作原理は次のとおりです。
- Notation CLIがECRイメージのダイジェスト(sha256:…)を計算します。
- プラグイン経由でAWS Signerの
StartSigningJobAPIを呼び出します。 - Signerが署名プロファイルで指定された鍵ペアを使用してペイロードに署名し、署名ブロックを返します。
- NotationがOCIアーティファクトとして署名をECRへプッシュします。
署名プラットフォームID
AWS SignerがNotationと連携するときのプラットフォームIDはNotation-OCI-SHA384-ECDSAです。このプラットフォームIDは署名プロファイル作成時に指定します。SHA-384ハッシュとECDSA(P-384曲線)を組み合わせた署名方式で、コンテナサプライチェーン保護に求められる強度を提供します。
# Notation-OCI向け署名プロファイルを確認
aws signer list-signing-profiles \
--platform-id Notation-OCI-SHA384-ECDSA \
--query 'profiles[*].{name:profileName,status:status}' \
--output table
Notation設定ファイルの構造
Notationの設定は~/.config/notation/ディレクトリで管理されます。主要ファイルを次の表に示します。
| ファイル | 役割 |
|---|---|
signingkeys.json | 使用する鍵とプラグインの紐付け定義 |
trustpolicy.json | 検証ポリシー(対象レジストリ・信頼レベル)の定義 |
truststore/ | 署名検証時に信頼する証明書のストア |
署名鍵の登録例を次に示します。
# AWS Signerプロファイルを署名鍵として登録
notation key add aws-signer-key \
--id "arn:aws:signer:ap-northeast-1:123456789012:/signing-profiles/ContainerSigningProfile" \
--plugin com.amazonaws.signer.notation.plugin
# 登録済み鍵の確認
notation key ls
# 出力例:
# NAME PLUGIN ID
# * aws-signer-key com.amazonaws.signer.notation.plugin arn:aws:signer:...
4-2. ECRイメージ署名と検証
ECRへの署名フロー
ECRイメージへの署名はnotation signコマンドで実行します。署名はOCIアーティファクトとしてイメージと同一リポジトリに保管されるため、特別なストレージ設定は不要です。
# ECR認証(東京リージョン例)
aws ecr get-login-password --region ap-northeast-1 \
| docker login --username AWS --password-stdin \
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com
# 署名対象のイメージダイジェストを取得
IMAGE_DIGEST=$(aws ecr describe-images \
--repository-name myapp \
--image-ids imageTag=v1.2.0 \
--query 'imageDetails[0].imageDigest' \
--output text)
# 署名実行
notation sign \
--key aws-signer-key \
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myapp@${IMAGE_DIGEST}
# 署名の内容確認
notation inspect \
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myapp@${IMAGE_DIGEST}
署名後、ECRリポジトリをマネジメントコンソールで参照すると、対象イメージのタグ一覧に署名アーティファクト(sha256-<digest>.sig形式)が追加されていることを確認できます。
検証ポリシー(trustpolicy.json)の設計
trustpolicy.jsonは、どのアーティファクトをどのTrust Storeで検証するかを定義するファイルです。本番環境ではstrictレベルで運用し、未署名イメージや検証失敗を即座に拒否することを推奨します。
{
"version": "1.0",
"trustPolicies": [
{
"name": "production-policy",
"registryScopes": [
"123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myapp"
],
"signatureVerification": {
"level": "strict"
},
"trustStores": ["signingAuthority:aws-signer"],
"trustedIdentities": [
"arn:aws:signer:ap-northeast-1:123456789012:/signing-profiles/ContainerSigningProfile"
]
},
{
"name": "audit-policy",
"registryScopes": ["*"],
"signatureVerification": {
"level": "audit"
},
"trustStores": ["signingAuthority:aws-signer"],
"trustedIdentities": ["*"]
}
]
}
signatureVerification.levelの選択基準を次の表に示します。
| レベル | 動作 | 推奨場面 |
|---|---|---|
strict | 未署名・検証失敗を即座に拒否 | 本番ワークロード |
permissive | 一部エラーを警告として続行 | ステージング移行期 |
audit | 検証失敗をログに記録して続行 | 初期導入時のインベントリ把握 |
skip | 検証を省略 | デバッグ用途のみ(本番禁止) |
Trust Storeの設定
Trust StoreはNotationが署名検証時に参照する証明書のリポジトリです。AWS Signerのルート証明書をTrust Storeに登録することで、AWS Signerが発行した証明書を信頼できます。
# AWS Signerのルート証明書バンドルをダウンロード
curl -O https://d2hvyiie56hcat.cloudfront.net/aws-signer-notation-root-ca.pem
# Trust Storeへ証明書を追加
notation cert add \
--type signingAuthority \
--store aws-signer \
aws-signer-notation-root-ca.pem
# Trust Storeの確認
notation cert ls
検証コマンドの実行
デプロイ前にnotation verifyで署名を検証します。trustpolicy.jsonでstrictが設定されたリポジトリへの検証失敗はエラーで終了し、後続のデプロイを止めることができます。
# 検証実行(strict設定リポジトリ)
notation verify \
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myapp@${IMAGE_DIGEST}
# 成功時の出力例
# Successfully verified signature for \
#123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myapp@sha256:abc123...
Kubernetes Admission Controllerでの署名検証強制
Kubernetesクラスター上でデプロイ時の署名検証を自動化するには、Admission Controllerと統合します。代表的な選択肢を次の表に示します。
| ツール | 署名方式 | AWS Signer連携 | 特徴 |
|---|---|---|---|
| Ratify | Notation / Cosign | Notation公式連携 | CNCF Notary Projectの検証フレームワーク |
| Kyverno | OPA/Policy Engine | Notation互換 | Kubernetes-nativeなポリシー記述 |
| OPA Gatekeeper | Rego | カスタム実装が必要 | 高い柔軟性・設定が複雑 |
| Cosign(Sigstore) | Sigstore独自 | 未対応 | AWS Signerとは独立した署名エコシステム |
AWS SignerとNotation連携ではRatifyが公式に推奨されます。RatifyはKubernetesのExternal Data Provider仕様をサポートし、KyvernoまたはGatekeeperと組み合わせてAdmission Controlポリシーを実装できます。
Ratify + Kyvernoの設定例を次に示します。
# Trust Storeの定義
apiVersion: config.ratify.deislabs.io/v1beta1
kind: CertificateStore
metadata:
name: aws-signer-certs
spec:
provider: inline
parameters:
value: |
-----BEGIN CERTIFICATE-----
<AWS Signerルート証明書>
-----END CERTIFICATE-----
---
# 検証設定
apiVersion: config.ratify.deislabs.io/v1beta1
kind: Verifier
metadata:
name: notation-verifier
spec:
name: notation
artifactTypes: application/vnd.cncf.notary.signature
parameters:
verificationCertStores:
signingAuthority:
- aws-signer-certs
trustPolicyDoc:
version: "1.0"
trustPolicies:
- name: default
registryScopes: ["*"]
signatureVerification:
level: strict
trustStores: ["signingAuthority:aws-signer-certs"]
trustedIdentities:
- "arn:aws:signer:ap-northeast-1:123456789012:/signing-profiles/ContainerSigningProfile"
ECS/Fargate環境での署名検証
ECSタスク起動時のネイティブ署名検証はサポートされていません。CodePipeline内にnotation verifyを実行するステップを組み込み、デプロイゲートとして機能させます。
# CodeBuild buildspec.ymlのデプロイ前検証例
phases:
pre_build:
commands:
- notation verify ${REGISTRY}/${REPO}@${IMAGE_DIGEST}
- echo "Signature verification passed - proceeding to deploy"
build:
commands:
- aws ecs update-service \
--cluster prod \
--service myapp \
--force-new-deployment
4-3. コンテナ署名の運用
イメージタグと署名の整合
Notationはタグではなくイメージダイジェスト(sha256:…)を対象に署名します。タグはミュータブル(変更可能)であるため、署名の整合性はダイジェストで管理することが原則です。
運用上の注意点は次のとおりです。
latestタグへの署名は避けてください。latestタグが指すダイジェストを更新すると、古い署名は新しいイメージに紐付かなくなります。- セマンティックバージョニングタグ(
v1.2.0等)を付与し、タグに対応するダイジェストを特定してから署名します。 - ECRのイミュータブルタグ設定(
imageTagMutability: IMMUTABLE)と組み合わせることで、タグとダイジェストの一致を担保できます。
# ECRリポジトリのイミュータブルタグを有効化
aws ecr put-image-tag-mutability \
--repository-name myapp \
--image-tag-mutability IMMUTABLE
# タグからダイジェストを解決して署名
IMAGE_TAG="v1.2.0"
IMAGE_DIGEST=$(aws ecr describe-images \
--repository-name myapp \
--image-ids imageTag=${IMAGE_TAG} \
--query 'imageDetails[0].imageDigest' \
--output text)
notation sign \
--key aws-signer-key \
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myapp@${IMAGE_DIGEST}
マルチアーキテクチャイメージへの対応
manifest list(OCI Image Index)形式のマルチアーキテクチャイメージは、各プラットフォーム(linux/amd64、linux/arm64等)のイメージマニフェストをまとめたインデックスとして管理されます。Notationはインデックスのダイジェストに対して署名を付与できます。
# manifest listのダイジェストを取得して署名
MANIFEST_DIGEST=$(docker buildx imagetools inspect \
--format '{{.Manifest.Digest}}' \
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myapp:v1.2.0)
notation sign \
--key aws-signer-key \
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myapp@${MANIFEST_DIGEST}
インデックスに署名しておくと、各アーキテクチャ固有のダイジェストへの個別署名なしに、1回の検証でマルチアーキテクチャイメージ全体を検証できます。
署名の更新と失効管理の連携
本番環境では次のライフサイクルで署名を管理します。
- 署名有効期間の把握: AWS Signerの署名プロファイルには有効期間が設定されています。有効期間が切れる前に再署名するパイプラインを整備してください。
- 再署名のトリガー: CI/CDパイプラインに有効期間チェックのステップを組み込み、期限切れが近いイメージを自動的に再署名します。
- 失効時の対応: 署名プロファイルを失効させると、失効後の署名ジョブ実行は不可になります。タイムスタンプを持つ署名は、タイムスタンプ時点での有効性が保証されます(詳細は§5で解説)。
既存コンテナ記事との関係
ECRリポジトリポリシーの設定やコンテナスキャン(Image Scanning)の基礎については、既存のコンテナ運用記事を参照してください。本セクションはAWS SignerとNotationを使った署名・サプライチェーン完全性担保の固有機能に集中して解説しています。
ECRパブリックリポジトリでは、Notationの署名アーティファクトも外部に公開されます。プライベートリポジトリとパブリックリポジトリで署名ポリシーを分けて管理し、意図しない署名情報の公開を防いでください。
5. 失効・信頼・検証
署名は失効管理と検証ワークフローが伴って初めて機能します。本セクションでは、署名失効・Trust Store・検証ワークフローを解説します。
5-1. 署名プロファイルの失効
署名プロファイルの失効(Revocation)は、秘密鍵の漏洩・不正使用・コンプライアンス要件への対応に必要な運用操作です。失効した署名プロファイルバージョンは署名生成に使用できなくなり、指定した発効時刻以降に生成された署名がすべて無効化されます。
失効の仕組みと発効時刻
RevokeSigningProfile APIに失効発効時刻(effectiveTime)を指定して呼び出すことで、特定バージョンの署名プロファイルを失効させます。
aws signer revoke-signing-profile \
--profile-name my-lambda-signing-profile \
--profile-version "AbCdEf1234" \
--reason "秘密鍵の漏洩が疑われる緊急失効" \
--effective-time "2024-06-01T00:00:00Z"
effectiveTime は失効チェックの基準時刻です。この時刻以降に生成された署名を持つアーティファクトは、Lambda Code Signing Configuration(CSC)のEnforceモード環境でデプロイが拒否されます。effectiveTime より前に生成された署名は引き続き有効なため、失効前にデプロイ済みのLambda関数は継続して動作します。これにより、既存の本番環境への影響を最小化しながら、失効後の不正な署名によるデプロイのみを防止できます。
失効後の署名生成不可
失効した署名プロファイルバージョンでは、新規の署名ジョブを開始できません。StartSigningJob APIを呼び出すと ValidationException が返されます。継続的な署名運用が必要な場合は、新しい署名プロファイルバージョンを発行し、CI/CDパイプラインの設定を更新してください。
署名プロファイルのバージョン一覧と失効状態は次のコマンドで確認できます。
aws signer list-signing-profile-versions \
--profile-name my-lambda-signing-profile \
--query 'items[*].{Version:profileVersion,Status:status,EffectiveOn:revocationRecord.effectiveOn}'
LambdaデプロイにおけるCSC失効チェック動作
Lambda CSCがデプロイ時に実行する署名検証の詳細な動作は次のとおりです。
| 状況 | WarnモードCSC | EnforceモードCSC |
|---|---|---|
| 有効な署名付きバンドル | デプロイ成功 | デプロイ成功 |
失効した署名プロファイルによる署名(effectiveTime以降) | 警告ログを出力してデプロイ成功 | デプロイ拒否・エラー |
失効した署名プロファイルによる署名(effectiveTimeより前) | デプロイ成功 | デプロイ成功 |
| 未署名バンドル | 警告ログを出力してデプロイ成功 | デプロイ拒否・エラー |
| CSCに登録されていない署名プロファイルによる署名 | 警告ログを出力してデプロイ成功 | デプロイ拒否・エラー |
Warnモードは段階的な導入の移行期間に適しており、Enforceモードは本番環境でのサプライチェーン完全性を強制します。Warnモードで一定期間運用して問題がないことを確認してからEnforceモードへ移行する、段階的な適用が推奨されます。
5-2. Trust Storeと検証ワークフロー
Trust Storeの概念と役割
Trust Store(信頼ストア)は、署名検証時に信頼するルート証明書・中間証明書の集合体です。Notationの信頼ポリシーは、どのTrust Storeを使用して署名を検証するかを定義します。AWS Signerが発行する署名証明書は、AWSが管理するルート認証局(CA)が信頼アンカーとなります。
Notationのコンテキストでは、Trust Storeは ~/.config/notation/truststore/ ディレクトリ以下に証明書ファイルとして管理します。
# Trust Storeに証明書を追加
notation certificate add \
--type signingAuthority \
--store aws-signer \
/path/to/aws-signer-root-ca.pem
# Trust Storeの証明書を一覧表示
notation certificate list
AWS Signerを使用する場合、notation aws-signer-pluginが自動的にAWS SignerのPKIを参照するため、ルートCA証明書を手動でTrust Storeに追加する必要はありません。企業独自の中間CAを使用するハイブリッド構成では、その中間CA証明書をTrust Storeに追加する設定が必要です。
信頼ポリシーの設定
Notationの信頼ポリシーファイル(trustpolicy.json)は、どのレジストリ・リポジトリの署名を、どのTrust Storeで検証するかを定義します。
{
"version": "1.0",
"trustPolicies": [
{
"name": "production-policy",
"registryScopes": [
"123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/my-app"
],
"signatureVerification": {
"level": "strict"
},
"trustStores": ["signingAuthority:aws-signer"],
"trustedIdentities": [
"arn:aws:signer:ap-northeast-1:123456789012:/signing-profiles/my-container-signing-profile"
]
}
]
}
signatureVerification.level を strict に設定することで、署名の真正性・完全性・証明書チェーン・失効状態・タイムスタンプをすべて検証します。permissive では一部の検証をスキップするため、本番環境では strict が推奨されます。
署名検証フロー
Notationが署名を検証する際の処理ステップは次のとおりです。
- 署名メタデータの取得 — OCIレジストリから対象イメージのdescriptorに紐づく署名アーティファクト(OCI Referrer)を取得します
- 証明書チェーン検証 — 署名証明書がTrust Storeに登録されたルートCA/中間CAまで信頼チェーンを構築して検証します
- 署名アルゴリズム検証 — 使用された署名アルゴリズム(ECDSA-SHA384)が許可リストに含まれるかを確認します
- 失効状態チェック — 署名プロファイルの失効状態(
effectiveTimeとの比較)を確認します - タイムスタンプ検証 — RFC 3161タイムスタンプが含まれている場合は、タイムスタンプの信頼性を検証します
- 信頼アイデンティティ照合 — 署名に使用された署名プロファイルARNが、信頼ポリシーの
trustedIdentitiesに含まれるかを確認します
これらのステップがすべて成功した場合のみ、署名が有効と判定されデプロイが許可されます。いずれか1ステップでも失敗した場合、検証は失敗となりコンテナの実行が阻止されます。
5-3. タイムスタンプと長期検証
Trusted Timestampingの意義
署名証明書には有効期間(通常90日〜1年程度)があります。証明書の有効期間が切れたあとに署名検証を行う場合、証明書が失効しているため検証が失敗します。この問題を解決するのがRFC 3161に準拠したTrusted Timestamping(信頼できるタイムスタンプ)です。
Trusted Timestampingでは、署名生成時にタイムスタンプ局(TSA: Timestamp Authority)から署名時刻の証明を取得し、署名に埋め込みます。TSAが発行するタイムスタンプトークンには次の情報が含まれます。
- 署名対象データのハッシュ値
- 署名が生成された時刻(TSA証明書で保証された正確な時刻)
- TSAの電子署名
この仕組みにより、将来的に署名証明書の有効期間が切れても「証明書が有効だったとき(署名時刻)に署名が生成されたこと」を証明できます。長期間保存されるLambdaバンドルやコンテナイメージのアーカイブでは、Trusted Timestampingが欠かせません。
AWS Signerにおけるタイムスタンプ
AWS Signerは署名ジョブの実行時に、AWSが管理するタイムスタンプ局(AWS TSA)から自動的にRFC 3161タイムスタンプを取得して署名に埋め込みます。ユーザーが明示的にTSAを指定する必要はなく、署名ジョブを実行するだけでタイムスタンプが付与されます。
# 署名ジョブの詳細でタイムスタンプ情報を確認
aws signer describe-signing-job \
--job-id "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" \
--query '{Status:status,CompletedAt:completedAt,SignedObject:signedObject}'
署名されたバンドルのメタデータには署名時刻が含まれており、NotationによるOCI検証時やLambda CSCの検証時にこのタイムスタンプが参照されます。
長期保存アーティファクトの検証設計
コンプライアンス要件やリーガルホールドのためにビルドアーティファクトを数年間保存する場合、長期検証を考慮した設計が必要です。
| 考慮点 | 推奨対応 |
|---|---|
| 署名証明書の有効期間切れ | Trusted Timestampingで署名時刻を証明。AWS Signerは自動付与 |
| TSA証明書の失効 | AWS TSAが管理するため追加対応は不要。独自TSA使用時はTSAの証明書も長期保管 |
| アーカイブ形式の互換性 | OCI Referrer仕様に準拠した署名アーティファクトはECRに長期保存可能 |
| 検証ツールのバージョン管理 | Notationのメジャーバージョンアップで信頼ポリシー形式が変わる場合があるため、検証環境のバージョン管理が必要 |
AWS Signerが自動でタイムスタンプを付与する特性を活かし、5年以上の保存が必要な金融・医療・官公庁向けシステムでも、追加設定なしで長期検証に対応できます。
失効管理のベストプラクティス
失効管理を確実に運用するために、以下のベストプラクティスを適用してください。
1. 署名プロファイルの定期棚卸し
有効な署名プロファイルバージョンを定期的に棚卸しし、不要なバージョンを失効させます。list-signing-profile-versions と get-signing-profile を組み合わせた定期スキャンをEventBridgeスケジュールで自動化できます。
# アクティブな署名プロファイル一覧
aws signer list-signing-profiles \
--include-canceled false \
--query 'items[?status==`Active`].{Name:profileName,Version:profileVersion}'
2. 失効イベントのSNS通知設定
署名プロファイルの失効はCloudTrailに記録されます。EventBridgeルールでCloudTrailイベントを受け取り、SNSトピックへ通知することで失効操作を即座に検知できます。
{
"source": ["aws.signer"],
"detail-type": ["AWS API Call via CloudTrail"],
"detail": {
"eventName": ["RevokeSigningProfile"]
}
}
3. 緊急失効手順のRunbook整備
鍵漏洩・インシデント発生時にすみやかに行動できるよう、緊急失効手順のRunbookを事前に整備します。失効実行者のIAMロール・失効対象プロファイルの特定方法・effectiveTimeの決定基準・失効後のCI/CD設定変更手順を手順書に明記してください。
4. 署名健全性のモニタリング
新規デプロイに使用される署名プロファイルが失効していないかを確認するカスタムCloudWatchメトリクスを実装することで、失効済みプロファイルが誤って使用されようとした際にアラームを発報できます。
- 過去の時刻を指定した場合: それ以降に発行済みの署名がすべて無効になります。稼働中のLambda関数のデプロイが次回から拒否されるリスクがあるため、effectiveTimeは失効操作実行時刻よりも未来の時刻(余裕を持った時刻)を指定してください
- Warnモードのまま放置: 失効した署名プロファイルによるデプロイがWarnモードでは通ってしまいます。本番環境ではEnforceモードへの移行を必ず完了させてください
- 失効前バンドルの取り扱い: effectiveTime以前に署名されたバンドルは引き続き有効です。脆弱性を含む可能性がある場合は、該当バンドルそのものをS3ライフサイクルポリシーで隔離するか削除してください
6. CI/CD統合・運用・コスト

署名はCI/CDパイプラインに組み込むことで継続的に運用できます。本セクションでは、パイプライン署名自動化・監査・コストを解説します。
6-1. パイプライン署名自動化
CI/CDパイプラインへの署名組み込みは、手動署名の漏れを防ぎ、継続的なサプライチェーン保証を実現します。自動化の核心は「ビルド成功直後に署名ジョブを実行し、署名済みアーティファクトのみをデプロイゲートで通過させる」設計です。
署名ジョブの基本コマンド
AWS CLIでLambdaデプロイパッケージへの署名ジョブを開始する例を示します。
# S3上のLambdaデプロイパッケージへの署名
aws signer start-signing-job \
--source 's3={bucketName=my-lambda-artifacts,key=function.zip,version=abc123}' \
--destination 's3={bucketName=my-signed-artifacts,prefix=signed/}' \
--profile-name MyLambdaSigningProfile \
--query jobId --output text
署名ジョブはコマンド発行後に非同期で実行されます。完了を待機する場合はwaitサブコマンドを使用します。
JOB_ID=$(aws signer start-signing-job \
--source 's3={bucketName=my-lambda-artifacts,key=function.zip,version=abc123}' \
--destination 's3={bucketName=my-signed-artifacts,prefix=signed/}' \
--profile-name MyLambdaSigningProfile \
--query jobId --output text)
# 完了まで待機
aws signer wait successful-signing-job --job-id ${JOB_ID}
# 署名ジョブの状態確認
aws signer describe-signing-job --job-id ${JOB_ID} \
--query '{status:status,statusReason:statusReason}'
CodeBuild統合(buildspec.yml)
CodeBuildのbuildspec.ymlにpost_buildフェーズで署名ジョブを追加する例を示します。
phases:
build:
commands:
- zip -r function.zip src/ requirements.txt
- aws s3 cp function.zip s3://${ARTIFACTS_BUCKET}/
post_build:
commands:
- |
OBJECT_VERSION=$(aws s3api head-object \
--bucket ${ARTIFACTS_BUCKET} \
--key function.zip \
--query VersionId --output text)
JOB_ID=$(aws signer start-signing-job \
--source "s3={bucketName=${ARTIFACTS_BUCKET},key=function.zip,version=${OBJECT_VERSION}}" \
--destination "s3={bucketName=${SIGNED_BUCKET},prefix=signed/}" \
--profile-name ${SIGNING_PROFILE} \
--query jobId --output text)
aws signer wait successful-signing-job --job-id ${JOB_ID}
echo "Signing completed: ${JOB_ID}"
S3のバージョニングを有効化しておき、署名対象のオブジェクトバージョンIDを明示的に指定することで、署名対象の特定が確実になります。
GitHub Actions統合
GitHub ActionsからAWSへの認証にはOIDC連携を使用し、長期アクセスキーの配置を避けることを強く推奨します。
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsSigningRole
aws-region: ap-northeast-1
- name: Sign Lambda package
run: |
JOB_ID=$(aws signer start-signing-job \
--source "s3={bucketName=${{ env.ARTIFACTS_BUCKET }},key=function.zip}" \
--destination "s3={bucketName=${{ env.SIGNED_BUCKET }},prefix=signed/}" \
--profile-name ${{ env.SIGNING_PROFILE }} \
--query jobId --output text)
aws signer wait successful-signing-job --job-id ${JOB_ID}
デプロイゲートの設計
Lambda Code Signing Configuration(CSC)をEnforceモードに設定することで、未署名または検証失敗のデプロイを自動的にブロックします。段階的な導入には、まずWarnモードで運用してCloudTrailログを確認し、異常がなければEnforceモードへ移行する方法を推奨します。Warnモードでは未署名デプロイがログに記録されつつも実行されるため、移行前に署名漏れのある関数を把握できます。
マルチステージ署名と職務分離
開発環境・ステージング環境・本番環境で異なる署名プロファイルを使用することで、環境ごとの成果物を識別できます。本番プロファイルへの署名実行権限(signer:StartSigningJob)は、セキュリティ管理者または専用CIロールに限定し、開発者の権限から分離することを推奨します。失効権限(signer:RevokeSigningProfile・signer:RevokeSignature)はセキュリティ管理者ロールのみに付与します。
6-2. 監査ログと運用
CloudTrailによる署名ジョブの監査
AWS Signerのすべての操作はCloudTrailに記録されます。主な監査対象イベントを次の表に示します。
| イベント名 | 監査ポイント |
|---|---|
| StartSigningJob | 誰が・いつ・どのプロファイルで署名したか |
| CancelSigningJob | 署名ジョブの中断(誰が・なぜ中断したか) |
| PutSigningProfile | 署名プロファイルの作成・更新 |
| RevokeSigningProfile | 署名プロファイルの失効(重大な運用変更) |
| RevokeSignature | 個別署名の失効 |
| AddProfilePermission | 署名プロファイルへのクロスアカウント権限追加 |
CloudTrail Insightsと組み合わせることで、異常な署名ジョブの急増(侵害されたビルドパイプラインによる大量署名)を自動検知できます。
IAM最小権限設計
CI/CDシステム用のIAMポリシーは署名実行に必要な範囲へ絞ります。次の例はLambda署名専用のポリシーです。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"signer:StartSigningJob",
"signer:DescribeSigningJob",
"signer:ListSigningJobs"
],
"Resource": "arn:aws:signer:ap-northeast-1:123456789012:/signing-profiles/MyLambdaSigningProfile"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3:::my-lambda-artifacts/*"
},
{
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::my-signed-artifacts/signed/*"
}
]
}
signer:RevokeSigningProfileとsigner:RevokeSignatureはCI/CDシステムには付与しません。セキュリティ管理者ロールのみに限定することが重要です。
署名プロファイル失効の手順
セキュリティインシデント発覚時の対応手順を示します。
- CloudTrailログで不審な
StartSigningJobイベントを特定し、影響を受けた署名ジョブの時刻範囲を確認します。 - 署名プロファイルを失効させます。
--effective-timeパラメーターで失効発効時刻を指定すると、その時刻以降に作成された署名が無効化されます。 - 失効したプロファイルで署名されたリソースを列挙し、再署名が必要な成果物の影響範囲を把握します。
- 新しい署名プロファイルを作成し、正規のビルドパイプラインから再署名します。
CloudWatchアラームを設定してRevokeSigningProfileイベントを検知し、即時通知を自動化することを推奨します。
マルチアカウント運用
複数のAWSアカウント(開発・ステージング・本番)で同一の署名プロファイルを参照するには、Resource-based policyによるクロスアカウント権限を使用します。AddProfilePermission APIで許可するアカウントを明示的に指定することで、不要なアカウントからの署名実行を防ぎます。
6-3. コスト構造
AWS Signerの課金モデル
AWS Signerは署名ジョブ単位で課金されます。
| 対象プラットフォーム | 課金単位 |
|---|---|
| AWSLambda-SHA384-ECDSA(Lambda署名) | 署名ジョブ1件あたり |
| Notation-OCI-SHA384-ECDSA(コンテナ署名) | 署名ジョブ1件あたり |
Lambda CSC(Code Signing Configuration)自体の追加料金はなく、署名ジョブの実行回数が費用を決定します。最新の料金は公式ドキュメントでリージョンごとに確認してください。
月次コスト見積もりの考え方
デプロイ頻度から月次の署名ジョブ回数を見積もります。
- 1サービスあたりデプロイ1日3回 × 20稼働日 = 60署名ジョブ/月
- 10サービス構成の場合: 600署名ジョブ/月
コンテナイメージは同一ダイジェストを再署名しても有効性は変わらないため、同じコンテンツのビルドアーティファクトを繰り返し署名する必要はありません。
コスト最適化のアプローチ
不変アーティファクトの活用が第1のアプローチです。コンテナイメージのSHA256ダイジェストが同一であれば再署名は不要です。CI/CDのビルドキャッシュヒットを活用し、同一コミットから生成したアーティファクトへの重複署名をスキップする設計を取り入れます。
環境ごとの署名ポリシー分離が第2のアプローチです。開発環境(dev/sandbox)では署名をWarnモードまたは省略し、ステージング・本番環境のみEnforceモードで署名を強制することで、非本番環境の費用を抑えられます。
署名のバッチ化が第3のアプローチです。マイクロサービス構成でも、同一リリーストレインに含まれる複数サービスの署名ジョブを同じCodeBuildプロジェクトでまとめて実行することで、パイプライン管理の複雑さを抑えながらコストを最適化できます。
GovCloudリージョン対応
AWS GovCloudリージョン(us-gov-east-1・us-gov-west-1)でもAWS Signerを利用できます。FedRAMP High認証が求められる環境では、GovCloudのSignerを使用し、署名来歴情報と署名証明書をGovCloud上のS3バケットに保管します。リージョンをまたいだ署名の相互検証はサポートされていないため、本番デプロイリージョンと同一リージョンのSignerを使用することを推奨します。
7. 実戦統合パターン — SLSA準拠のサプライチェーン全体設計

本セクションでは、AWS Signerを既存のセキュリティ基盤と組み合わせ、SLSA準拠のサプライチェーンを設計する統合パターンを解説します。
7-1. SLSAフレームワークと到達レベル
SLSA(Supply-chain Levels for Software Artifacts)は、Googleが提唱したソフトウェアサプライチェーンセキュリティのフレームワークで、L1〜L4の4段階でセキュリティ強度を定義しています。AWS Signerはこのフレームワークの複数要件を満たすコアコンポーネントです。
SLSA L1: ドキュメント化されたビルドプロセス
SLSA L1の要件は「アーティファクトがドキュメント化されたビルドプロセスで生成されること」です。AWS SignerでLambdaバンドルやコンテナイメージに署名するだけで、L1相当の基礎が整います。署名ジョブのメタデータ(プロファイル名・タイムスタンプ・ジョブID)がCloudTrailに記録され、ビルド来歴の証拠となります。
SLSA L2: 管理されたビルドサービス + Provenance生成
SLSA L2の要件は「管理されたビルドサービスがProvenanceを自動生成すること」です。AWS SignerはLambda署名ジョブのメタデータとして、署名プロファイル・タイムスタンプ・プラットフォームIDを記録します。CodeBuild + AWS Signerの組み合わせでL2のProvenance証拠を収集できます。
# CodeBuildのpost_buildフェーズでProvenance情報を収集
SIGNING_JOB_ID=$(aws signer start-signing-job \
--source "s3={bucketName=$SOURCE_BUCKET,key=input/function.zip,version=$SOURCE_VERSION}" \
--destination "s3={bucketName=$SIGNING_BUCKET,prefix=output/}" \
--profile-name ProdLambdaSigningProfile \
--query 'jobId' --output text)
# Provenance情報をJSONで保存
cat > provenance.json << EOF
{
"buildType": "https://aws.amazon.com/codebuild/",
"signingJobId": "$SIGNING_JOB_ID",
"signingProfile": "ProdLambdaSigningProfile",
"platform": "AWSLambda-SHA384-ECDSA"
}
EOF
aws s3 cp provenance.json s3://$SIGNING_BUCKET/provenance/$SIGNING_JOB_ID.json
SLSA L3: 非改ざんの来歴(強固なビルド環境)
SLSA L3の要件は「ビルド環境が外部から変更不可で、Provenanceが信頼できる方法で生成・署名されること」です。CodeBuild + AWS Signerの組み合わせではL3に近づけられますが、完全な達成にはビルド環境の隔離とProvenance自体への署名が必要です。
実践的なL3相当の構成:
– CodeBuildをVPC内の隔離環境で実行(外部ネットワーク制限)
– IAM Roles AnywhereでCI/CDランナーのIDを証明
– 署名ジョブの実行権限をCodeBuildロールのみに限定
– CloudTrailログをS3 Object Lockで改ざん不可にする
SLSA L4: 二者確認ビルドプロセス
SLSA L4の要件は「2人のレビュアーがビルドプロセスを承認すること」です。AWSマネージドサービスのみでのL4完全達成は難しいですが、CodePipelineの手動承認アクションと組み合わせることでL3+相当を実現できます。
AWS Signerが貢献するSLSA要件の整理
| SLSA要件 | AWS Signerでの対応 | 達成レベル |
|---|---|---|
| 署名されたアーティファクト | Lambda CSC + Enforceモード | L1〜L4 |
| Provenance記録 | CloudTrailでの署名ジョブ記録 | L2相当 |
| 鍵管理の信頼性 | AWSが管理する署名鍵(HSM保護) | L2相当 |
| 失効管理 | 署名プロファイル失効API | L2〜L3 |
| 検証の強制 | CSC Enforceによるデプロイゲート | L1〜L3 |
| ビルド環境の隔離 | CodeBuild VPC内実行 | L3相当 |
SBOM(Software Bill of Materials)との統合
SLSA準拠のサプライチェーンでは、署名と合わせてSBOMを生成・管理することが推奨されます。AWS Signer自体にSBOM生成機能はありませんが、署名ジョブIDとSBOMを関連付けることで「このバンドルの構成要素(SBOM)が署名済みであること」を証明できます。
# SBOMを生成してS3に保存(syftを使用する例)
syft $DOCKER_IMAGE -o spdx-json > sbom.json
aws s3 cp sbom.json "s3://my-sbom-bucket/$SIGNING_JOB_ID/sbom.json"
# 署名ジョブとSBOMの対応をDynamoDBに記録
aws dynamodb put-item \
--table-name ArtifactProvenance \
--item "{
\"signingJobId\": {\"S\": \"$SIGNING_JOB_ID\"},
\"sbomUri\": {\"S\": \"s3://my-sbom-bucket/$SIGNING_JOB_ID/sbom.json\"}
}"
SLSAレベル達成のロードマップ
SLSA準拠は段階的に進めることを推奨します。
- 即時実施(L1相当): 全Lambda関数にCSCをWarnモードで紐付け、署名パイプラインを構築する
- 1ヶ月以内(L2相当): CSCをEnforceモードへ移行し、コンテナ署名をNotation+ECRで自動化する
- 3ヶ月以内(L2+相当): CloudTrailログをS3 Object Lockで保護し、SBOMとの紐付けを確立する
- 6ヶ月以内(L3相当): CodeBuildのVPC隔離・IAM Roles Anywhere統合・手動承認ゲートを実装する
7-2. CloudHSM・Roles Anywhereとのセキュリティ連環
セキュリティ基盤の3層連環
AWS Signerは単体で使うより、既存のセキュリティ基盤と連環させることで真価を発揮します。CloudHSMとRoles Anywhereとの連環パターンを紹介します。
CloudHSM(ハードウェア保護ルート鍵)
↓ 鍵を保護してCA階層を構築
AWS Private CA(CA階層構築・証明書発行)
↓ CA証明書をTrust Anchorに登録
IAM Roles Anywhere(CI/CDランナーのID認証)
↓ X.509証明書で一時認証情報を取得
CI/CDランナー(GitHub Actions / Jenkins等)
↓ 一時認証情報でSignerを呼び出す
AWS Signer(署名ジョブ実行)
↓ 署名済みアーティファクトをS3に出力
Lambda CSC / Notation(デプロイ時署名検証)
CloudHSM保護の秘密鍵でPrivate CAを構築し、そのCAをRoles AnywhereのTrust Anchorに登録します。CI/CDランナーはX.509証明書で一時認証情報を取得し、その認証情報でSignerの署名ジョブを実行します。これにより「誰(ランナー)が、どの鍵で(HSM保護)、何を(アーティファクト)署名したか」が完全に追跡可能になります。
CloudHSMとPrivate CA・Roles Anywhereの設定方法については各専門記事を参照してください。本項では統合パターンの接続部分に集中します。
CI/CDランナー統合パターン
GitHub ActionsでRoles AnywhereからAWS認証情報を取得してSignerを呼び出すフローを示します。
# 1. GitHubランナーの証明書をSecrets Managerから取得
# (Private CAで発行されたX.509証明書を事前配置)
# 2. aws_signing_helperで一時認証情報を取得
aws_signing_helper credential-process \
--certificate /path/to/runner-cert.pem \
--private-key /path/to/runner-key.pem \
--trust-anchor-arn "$TRUST_ANCHOR_ARN" \
--profile-arn "$ROLES_ANYWHERE_PROFILE_ARN" \
--role-arn "$SIGNING_ROLE_ARN"
# 3. 取得した認証情報でLambdaバンドルに署名
aws s3 cp function.zip "s3://$SIGNING_BUCKET/input/function.zip"
SIGNING_JOB_ID=$(aws signer start-signing-job \
--source "s3={bucketName=$SIGNING_BUCKET,key=input/function.zip,version=latest}" \
--destination "s3={bucketName=$SIGNING_BUCKET,prefix=output/}" \
--profile-name ProdLambdaSigningProfile \
--query 'jobId' --output text)
# 4. 署名完了を待機
aws signer wait successful-signing-job --job-id "$SIGNING_JOB_ID"
# 5. 署名済みZIPを取得してLambdaへデプロイ
SIGNED_KEY=$(aws signer describe-signing-job \
--job-id "$SIGNING_JOB_ID" \
--query 'signedObject.s3.key' --output text)
aws lambda update-function-code \
--function-name "$FUNCTION_NAME" \
--s3-bucket "$SIGNING_BUCKET" \
--s3-key "$SIGNED_KEY"
マルチアカウント署名管理パターン
大規模組織では、署名プロファイルをセキュリティアカウントで一元管理し、デプロイ先の本番/ステージングアカウントからクロスアカウントで参照するパターンを推奨します。
[セキュリティアカウント]
└── 署名プロファイル(集中管理)
│
├── RAM共有 → [本番アカウント] CSCの許可リストに登録
├── RAM共有 → [ステージングアカウント] CSCの許可リストに登録
└── RAM共有 → [開発アカウント] Warnモードで運用
RAM(Resource Access Manager)を使って署名プロファイルをOrganization内で共有します。
# セキュリティアカウント: RAMで署名プロファイルを組織内共有
aws ram create-resource-share \
--name "SharedSigningProfiles" \
--resource-arns \
"arn:aws:signer:ap-northeast-1:111222333444:/signing-profiles/ProdLambdaSigningProfile" \
--principals \
"arn:aws:organizations::111222333444:organization/o-xxxxxxxxxx" \
--allow-external-principals false
# 本番アカウント: 共有された署名プロファイルでCSCを作成
aws lambda create-code-signing-config \
--description "Lambda prod CSC (cross-account signing)" \
--allowed-publishers \
'{"SigningProfileVersionArns": ["arn:aws:signer:ap-northeast-1:111222333444:/signing-profiles/ProdLambdaSigningProfile/version1"]}' \
--code-signing-policies '{"UntrustedArtifactOnDeployment": "Enforce"}'
セキュリティ三部作の連携ポイント
本連環パターンを実装する際の参照先を整理します。HSM保護鍵の設定はCloudHSM記事を、CI/CDランナーのX.509証明書管理はRoles Anywhere記事を参照してください。それぞれ独立した専門記事として解説されており、本節ではAWS Signerとの接続部分のみに集中しています。
7-3. エンドツーエンドの完全性保証
ゼロトラストサプライチェーンの設計原則
ゼロトラストサプライチェーンでは、「ビルドサーバーは信頼できる」という前提を排除します。代わりに、各段階でアーティファクトの完全性を暗号的に証明します。
| フェーズ | 攻撃ベクター | 対策 |
|---|---|---|
| ソース | コードリポジトリ改ざん | コミット署名(git commit -S)・ブランチ保護 |
| ビルド | ビルド環境汚染 | 隔離環境(CodeBuild)・Provenance生成 |
| 署名 | 署名鍵の漏洩 | CloudHSM鍵保護・Roles Anywhere認証 |
| レジストリ | イメージ差し替え | Notation署名・immutableタグ設定 |
| デプロイ | 未署名コード実行 | CSC Enforce・Admission Controller |
Lambda + コンテナのフルスタックサプライチェーン
LambdaとEKS/ECSのコンテナが混在する環境では、両方の署名を組み合わせた設計が必要です。
Lambda関数:
AWS Signer (AWSLambda-SHA384-ECDSA)
→ CSC Enforce → Lambda Versionの発行
EKSコンテナ:
AWS Signer + Notation (Notation-OCI-SHA384-ECDSA)
→ ECRに署名付きイメージを保存
→ Kyverno Admission Controllerで署名を検証
→ Podの実行を許可
IaC (CloudFormation / Terraform):
ハッシュ検証 + CodePipelineの手動承認ゲート
ゼロトラストパイプライン設計
CI/CDパイプライン全体をゼロトラスト原則で設計します。各ステージで署名・検証・最小権限を徹底します。
# Stage1: ビルド後に署名ジョブを実行
SIGNING_JOB_ID=$(aws signer start-signing-job \
--source "s3={bucketName=$ARTIFACTS_BUCKET,key=function.zip,version=$VERSION}" \
--destination "s3={bucketName=$SIGNING_BUCKET,prefix=signed/}" \
--profile-name ProdLambdaSigningProfile \
--query 'jobId' --output text)
aws signer wait successful-signing-job --job-id "$SIGNING_JOB_ID"
# Stage2: 署名ジョブの成功を確認してデプロイゲートを通過
JOB_STATUS=$(aws signer describe-signing-job \
--job-id "$SIGNING_JOB_ID" \
--query 'status' --output text)
if [ "$JOB_STATUS" != "Succeeded" ]; then
echo "Signing job failed. Stopping pipeline."
exit 1
fi
# Stage3: 手動承認後に本番デプロイ(CodePipelineのApproval Actionで制御)
echo "Signing verification passed. Awaiting manual approval."
ガバナンスと監査フロー
署名運用のガバナンスには定期的な監査が不可欠です。
- 週次: CloudTrailで未署名デプロイ試行数を確認し、Warnログを検索する
- 月次: 署名プロファイルの有効期限一覧を確認し、期限90日前にアラームを設定する
- 四半期: CSCに登録されているプロファイルバージョンの棚卸しを実施する
- 年次/インシデント時: 署名プロファイルのローテーションと失効テストを実施する
CloudWatchダッシュボードで署名健全性をリアルタイム可視化します。
# 署名ジョブの成功数を週次で確認
aws cloudwatch get-metric-statistics \
--namespace AWS/Signer \
--metric-name SigningJobSucceeded \
--dimensions Name=SigningProfileName,Value=ProdLambdaSigningProfile \
--start-time "$(date -u -v-7d +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -d '7 days ago' +%Y-%m-%dT%H:%M:%SZ)" \
--end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--period 86400 \
--statistics Sum
既存セキュリティ基盤との連携ポイント
AWS Signerは、CloudHSMとRoles Anywhereとともに「鍵保護・ID・コード完全性」の三位一体セキュリティ基盤を形成します。
- HSM保護鍵でコード署名の根拠を強固にする方法は CloudHSM 本番運用 Vol1 を参照してください。
- CI/CDランナーのワークロードIDをX.509で管理する方法は IAM Roles Anywhere 本番運用 Vol1 を参照してください。
- ECRコンテナイメージへのNotation署名実装は AWS Container 本番運用 Vol1 を参照してください。
- CloudHSM — 署名鍵の硬い根(ルート鍵をHSMで保護)
- IAM Roles Anywhere — ビルダーのID(CI/CDランナーを証明書で認証)
- AWS Signer — コードの完全性証明(デプロイされるものを署名で保証)
8. 詰まりポイントとアンチパターン・まとめ
AWS Signerの本番運用では、署名検証ならではの落とし穴があります。本セクションでは、現場で頻出する詰まりポイントとアンチパターン、そして次のステップを示します。
8-1. よくある詰まりポイント
AWS Signerは「鍵管理をAWSに委譲しシンプルに見える」一方で、設定の抜け漏れや挙動の誤解が本番インシデントにつながるサービスです。以下に現場で頻出する詰まりポイントを整理します。
詰まりポイント1: CSC(Code Signing Configuration)をWarnモードのままにしてデプロイが強制されない
症状: 未署名のLambdaパッケージをデプロイできてしまい、署名ポリシーが形骸化する。
原因: CSCの UntrustedArtifactOnDeployment を Warn のまま放置している。Warnモードは署名検証に失敗してもデプロイを拒否しません。CloudWatchのLambda/Signerメトリクスに警告が記録されるだけです。
対処: 本番環境のCSCは Enforce モードに変更します。段階導入する場合は、まずステージング環境でEnforceを有効にして動作確認してから、本番に展開します。
# CSC を Enforce モードに更新する例
aws lambda update-code-signing-config \
--code-signing-config-arn arn:aws:lambda:ap-northeast-1:123456789012:code-signing-config:csc-xxxx \
--code-signing-policies '{"untrustedArtifactOnDeployment":"Enforce"}'
詰まりポイント2: 署名プロファイル失効後の既存Lambda関数への影響を誤解する
症状: 署名プロファイルを失効させたのに、既存のLambda関数が引き続き実行されており「失効が効いていない」と混乱する。
原因: 署名プロファイルの失効は「新規デプロイ」にのみ影響します。稼働中の関数が実行時にリアルタイム署名検証を行うわけではありません。失効後のデプロイ(更新)のみブロックされます。
対処: プロファイル失効は将来のデプロイに対するガードです。既存関数への影響を望む場合は、関数コードを再デプロイ(新しい有効プロファイルで署名)する必要があります。
詰まりポイント3: Notation信頼ポリシーの誤設定によりコンテナ検証エラー
症状: 署名済みコンテナイメージを notation verify しようとすると no trust policy applies または certificate is not trusted エラーが発生する。
原因: ~/.config/notation/trustpolicy.json の設定ミスが主な原因です。よくあるパターンは以下のとおりです。
registryScopesに対象ECRリポジトリのURIを正確に記載していない(ワイルドカード*の誤用を含む)trustStoresに参照するトラストストア名が一致していないtrustedIdentitiesに署名プロファイルARNではなくプロファイル名(短縮形)を指定している
対処: 信頼ポリシーには完全なプロファイルARN(arn:aws:signer:...:/signing-profiles/ProfileName)を記載します。
{
"version": "1.0",
"trustPolicies": [
{
"name": "aws-signer-tp",
"registryScopes": [
"123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/my-app"
],
"signatureVerification": { "level": "strict" },
"trustStores": ["signingAuthority:aws-signer-ts"],
"trustedIdentities": [
"arn:aws:signer:ap-northeast-1:123456789012:/signing-profiles/ContainerProfile"
]
}
]
}
詰まりポイント4: マルチアカウント署名でIAM権限の設定漏れによる403エラー
症状: 開発アカウントのCI/CDパイプラインから署名専用アカウントの署名プロファイルを使って署名ジョブを実行しようとすると AccessDeniedException が発生する。
原因: クロスアカウント署名を有効にするには2つの権限設定が必要です。
- 署名プロファイル側のリソースポリシー(開発アカウントのロールに
signer:StartSigningJobを許可) - 開発アカウントのIAMロールのアイデンティティポリシー(
signer:StartSigningJobを許可)
どちらか一方だけでは不十分です。またS3を経由する場合は、ソース・デスティネーションバケットのアクセス権限も確認します。
詰まりポイント5: 署名コストの想定外増加
症状: 大規模なCI/CDパイプラインで毎回署名ジョブを実行したところ、月の署名ジョブ費用が想定の数倍に膨らみました。
原因: AWS Signerの課金は署名ジョブ数に基づきます(2025年時点の料金は公式を参照)。毎コミット・毎ブランチで署名ジョブを実行すると急激にコストが増加します。
対処: 本番ブランチへのマージ時のみ署名するように制限します。また、すでに署名済みのアーティファクトをS3やECRでキャッシュし、変更がない場合は再署名をスキップするパイプライン設計が有効です。
詰まりポイント6: タイムスタンプ未設定で証明書失効後に長期検証が失敗する
症状: 2年前に署名したアーティファクトを検証しようとすると、署名証明書が失効済みで検証エラーになった。
原因: 署名時にタイムスタンプ(RFC 3161準拠)を付与していない場合、証明書の有効期限が切れると「署名時点で証明書が有効だったか」を証明できなくなります。
対処: Notation v1.1以降と最新の notation-aws-signer プラグインを使用すると、署名時に自動でタイムスタンプが付与されます。長期保存するアーティファクトは必ずタイムスタンプ付きで署名します。
詰まりポイント7: Notationプラグインのバージョン不一致によるエラー
症状: notation verify 実行時に unsupported signature envelope format や plugin error が発生する。
原因: notation-plugin-aws-signer のバージョンとNotation CLIのバージョンに互換性がない組み合わせを使用している。特に、古いNotation CLI(v1.0以前)と新しいプラグインの組み合わせで頻発します。
対処: AWSドキュメントの互換バージョン表を確認し、推奨バージョンの組み合わせを使用します。CI/CD環境のNotationとプラグインのバージョンをPinningして管理し、不用意なアップデートを防ぎます。
詰まりポイント8-A: Notationのトラストストアの証明書登録漏れ
症状: notation verify を実行すると no certificate found in trust store エラーが発生し、検証が完了しない。
原因: Notation検証にはAWS Signerが発行する証明書チェーンを notation certificate add でトラストストアへ登録する必要があります。この手順を省略すると、信頼できる証明書が見つからず検証に失敗します。
対処: AWS Signerの署名に使用する中間CA証明書をダウンロードしてNotationのトラストストアに追加します。
# AWS Signer証明書のダウンロード
aws signer list-signing-certificates \
--profile-name ContainerProfile > certs.json
# Notationトラストストアに証明書を追加
notation certificate add \
--type signingAuthority \
--store aws-signer-ts \
<certificate.pem>
詰まりポイント8: CI/CD環境からAWS APIを呼ぶための認証設定漏れ
症状: GitHub ActionsやJenkinsなどのCI/CD環境から署名ジョブを実行しようとするとAWS認証エラーになる。
原因: CI/CD環境がAWS APIを呼ぶための一時認証情報の取得設定が漏れている。GitHub Actionsの場合、OIDCプロバイダーの設定とIAMロールへの信頼関係が必要です。
対処: GitHub ActionsではOIDCフェデレーション(aws-actions/configure-aws-credentials)で一時認証情報を取得します。オンプレミスのCI/CD環境ではIAM Roles Anywhereを活用すると長期認証情報を不要にできます(詳細は「AWS IAM Roles Anywhere 本番運用 Vol1」を参照)。
8-2. アンチパターン → 正解
AWS Signerの設計・運用でよく見かけるアンチパターンと、その正解を示します。
| # | アンチパターン | 問題 | 正解 |
|---|---|---|---|
| 1 | 開発者が自前の秘密鍵でコード署名し、鍵ファイルをCI/CDサーバーに配置 | 秘密鍵の漏洩リスク・鍵管理が属人化・ローテーションが困難 | AWS Signerの署名プロファイルに鍵管理を委任。開発者は秘密鍵に触れない |
| 2 | CSCをWarnモードのまま本番運用して「署名ポリシーを導入済み」とする | 未署名コードがデプロイされてもブロックされず、ポリシーが形骸化 | EnforceモードでデプロイをBlockし、署名なしでは絶対にデプロイできない環境を作る |
| 3 | すべての署名ジョブを本番AWSアカウントの管理者ロールで実行 | 権限過剰・サプライチェーンの攻撃対象が広くなる | 署名専用アカウントを設け、クロスアカウント署名で鍵管理と開発を分離 |
| 4 | 署名プロファイルを失効後に同名で再作成 | 失効前後の署名検証が曖昧になり、古い署名の有効性判断が困難になる | 失効後は別名のプロファイルを新規作成して切り替える |
| 5 | コンテナイメージはECRプライベートレジストリで管理しているから署名不要とする | ECR内部の侵害・CI/CDパイプラインへの不正イメージ混入には対応できない | Notation + AWS Signerで全本番イメージに署名し、デプロイ時にNotation検証ポリシーで強制する |
| 6 | 毎回のコミット・プルリクエストで署名ジョブを実行する | 署名コストが無駄に膨らみ、CI/CD速度も低下する | 本番ブランチへのマージ・リリース時のみ署名を実行する。署名済みアーティファクトはキャッシュして再利用 |
アンチパターン補足: 署名と暗号化の役割混同
コード署名をコードの「暗号化」と混同するケースがあります。暗号化は「許可された者しか内容を読めない」ことを目的とし、署名は「誰が作成したか・署名後に改ざんされていないか」を証明します。Lambda関数コードはAWS Signerで署名しても、関数本体の内容は暗号化されません。コードの機密性を守りたい場合は、KMSを使ったS3オブジェクトの暗号化や、コンテナイメージの秘密情報管理(Secrets Manager連携)を別途検討してください。
アンチパターン補足: 署名プロファイルを組織で共有する
複数チームが1つの署名プロファイルを共有している構成では、プロファイルの失効・有効期間管理・監査ログのチームへの帰属が困難になります。チームごと・サービスごとに署名プロファイルを分割することで、CloudTrailの監査ログから「どのチームのどのサービスが署名したか」を明確に区別できます。また、特定チームのプロファイルを失効させても他のチームの署名に影響しないため、インシデント対応が迅速になります。
8-3. まとめと次のステップ
本記事ではAWS Signerによるコード署名とサプライチェーンセキュリティの実践を解説しました。
Vol1の要点まとめ
- 署名プロファイルは署名設定の中核リソースです。AWSが証明書と秘密鍵を管理するため、鍵の漏洩リスクがなく、クロスアカウント署名による権限分離も容易です
- 署名プラットフォームIDはLambdaとコンテナで異なります。Lambda .zipには
AWSLambda-SHA384-ECDSA、コンテナ/OCIにはNotation-OCI-SHA384-ECDSAを使用します - Code Signing ConfigurationはLambdaデプロイの署名検証を担います。本番環境は必ずEnforceモードに設定し、未署名コードのデプロイを物理的にブロックします
- Notation + AWS Signerの組み合わせはOCIアーティファクト署名のデファクトスタンダードです。ECRとの統合により、コンテナイメージのサプライチェーン完全性を保証できます
- 失効管理とタイムスタンプは見落とされがちですが、長期的な運用で重要です。証明書失効後も署名時点の有効性を保証するためにはタイムスタンプが欠かせません
- 詰まりポイントの共通原因は「設定ミス」「バージョン不一致」「権限の二段階設定漏れ」の3パターンに集約されます。本セクションのチェックリストを導入時の確認手順として活用してください
サプライチェーンセキュリティの次のステップ
AWS Signerはサプライチェーンセキュリティの「署名・検証」レイヤーを担います。より高いSLSAレベルへの到達には、以下の組み合わせが効果的です。
- CloudHSM: 署名鍵の専有HSM保護が規制要件で必要な場合、マネージドHSMによる鍵保護でFIPS 140-3 Level 3を達成できます
- IAM Roles Anywhere: CI/CDビルドサーバーへの長期認証情報の配布をなくすワークロードID基盤として有効です
- CodePipeline + CodeBuild: ビルド→署名→検証のパイプライン署名自動化により、継続的なサプライチェーン保証を実現できます
- Vol2では、AWS Signerの高度な運用(SBOMとの統合・マルチアーキテクチャ署名・GitOps統合・組織規模での証跡管理)を解説予定です
SLSAとAWS Signerの整合性
SLSA(Supply chain Levels for Software Artifacts)フレームワークでは、ソフトウェアの来歴(Provenance)と完全性(Integrity)を段階的に強化します。AWS SignerはSLSAの「成果物の完全性保証(Artifact Integrity)」を担うコアコンポーネントです。
CodeBuildの署名付き来歴(Signed Provenance for Builds)とAWS Signerのコード署名を組み合わせると、「このコードはいつ・どのリポジトリコミットから・認証されたビルドサービスで生成され・署名された」という証跡をSLSA L2/L3水準で構築できます。詳細な統合パターンについては§7を参照してください。
組織規模での段階導入ロードマップ
AWS Signerの導入は、ゼロから一気に全サービスへ展開するのではなく、段階的に進めることを推奨します。
フェーズ1(Warn運用・可視化): まず全Lambdaに対してCSCをWarnモードで適用します。どの関数が未署名でデプロイされているか、CloudWatchメトリクスで可視化します。この段階で署名漏れのパターンをすべて把握します。
フェーズ2(高リスク領域のEnforce化): 本番APIゲートウェイや決済処理など、セキュリティ感度の高い関数からEnforceモードに切り替えます。CSCをEnforceへ切り替える前に、CI/CDパイプラインの署名ジョブが正常動作することを必ず確認します。
フェーズ3(全サービス Enforce化): フェーズ2の成果を踏まえ、残りのすべてのLambda関数・コンテナイメージへとEnforceを拡大します。新規デプロイワークフローには署名ジョブを標準組み込みにして、署名なしデプロイが物理的に不可能な状態を作ります。
フェーズ4(クロスアカウント・SLSA準拠へ): 署名専用アカウントの設置、CloudHSMとの連携、SBOMへの対応など、SLSA L3以上を目標に設計を高度化します。
運用チェックリスト(本番移行前)
本番環境でAWS Signerを稼働させる前に、以下を確認してください。
- [ ] 全Lambdaに対応するCSCが作成済みで、Enforceモードが有効
- [ ] 使用する署名プロファイルのステータスがActiveであること
- [ ] CI/CDパイプラインに署名ジョブが組み込まれており、署名なしのデプロイがブロックされること
- [ ] 署名プロファイルのIAM権限が最小権限(StartSigningJob + DescribeSigningJob)になっていること
- [ ] コンテナの場合、Notation信頼ポリシーが正確に設定され、
notation verifyが成功すること - [ ] CloudTrailで署名ジョブのイベントが記録されていること
- [ ] 署名プロファイルの有効期間をカレンダーに登録し、失効前にアラートが届く仕組みを用意していること
- [ ] 署名プロファイルのロールバック手順(旧プロファイルでの再署名手順)が文書化されていること