証明書の取り消し
侵害、ポリシーの変更、または関係の終了により証明書を取り消す必要がある場合は、mTLS ハンドシェイク中にこれらの証明書を拒否するメカニズムが必要です。CloudFront は、証明書失効に対する 2 つのネイティブアプローチを提供しており、それらをレイヤードコントロールのために組み合わせることができます。
-
OCSP (オンライン証明書ステータスプロトコル) - CloudFront は、認証機関の OCSP レスポンダーにリアルタイムでクエリを実行して、クライアント証明書が取り消されたかどうかを確認します。信頼ストアで OCSP を有効にすると、CloudFront は TLS ハンドシェイク中に検証を自動的に処理します。OCSP の結果は Connection Functions にも表示されるため、失効ステータスにプログラムからアクセスし、意思決定をカスタマイズできます。
-
CloudFront Functions と KeyValueStore - 取り消された証明書のシリアル番号のリストを CloudFront KeyValueStore に保持します。Connection Function は、TLS ハンドシェイク中に KeyValueStore をクエリし、接続を許可または拒否します。これにより、失効データ、更新タイミング、猶予期間や IP ベースの例外などのカスタムロジックを完全に制御できます。
| OCSP | CloudFront Functions + KeyValueStore | |
|---|---|---|
| データソース | 認証機関の OCSP レスポンダー | お客様が失効リストを管理 |
| 更新メカニズム | CA へのリアルタイムクエリ | 更新を KeyValueStore にプッシュする |
| カスタムロジック | Connection Functions 経由で利用可能 | 関数コードに組み込まれる |
| 外部依存関係 | CA OCSP レスポンダーの可用性が必要 | 外部依存なし |
| 次の用途に適しています | OCSP レスポンダーを維持する CA、リアルタイムの CA 権限ステータス | セルフマネージド型の失効運用、カスタムポリシー、OCSP をサポートしていない CA |
両方のアプローチを一緒に使用できます。CA 権限による失効チェックのために OCSP を有効にし、Connection Function を使用して OCSP 結果の上に追加のロジックをレイヤーします。例えば、猶予期間中は信頼された IP 範囲からの失効した証明書を許可するなどです。
OCSP (オンライン証明書ステータスプロトコル)
OCSP は、証明書の失効ステータスを認証局 (CA) に直接確認するリアルタイムプロトコルです。証明書の署名プロセス中、CA は証明書に OCSP レスポンダー URL を埋め込みます。クライアントが mTLS ハンドシェイク中に証明書を提示すると、CloudFront は埋め込みレスポンダー URL に OCSP リクエストを送信し、レスポンスに基づいて処理します。有効な証明書は続行され、失効した証明書は処理を終了します。
CloudFront は、リーフ証明書と最大 3 つの中間証明書を含む証明書チェーン全体を、それぞれ対応する OCSP レスポンダー URL に対して検証します。信頼ストアのルート証明書は OCSP 検証から除外されます。
OCSP を有効にする
信頼ストアで OCSP を有効にします。有効にすると、CloudFront は、認証局情報アクセス (AIA) 拡張機能に OCSP レスポンダー URL を含むクライアント証明書に対して OCSP 検証を自動的に実行します。OCSP を有効にすると、クライアント証明書チェーン全体に OCSP URL が必要になります。クライアント証明書チェーン内のいずれかの証明書に OCSP URL が含まれていない場合、CloudFront は接続を確立しません。
CloudFront は OCSP レスポンスをエッジでキャッシュしてラウンドトリップタイムを短縮し、OCSP レスポンダーのダウンタイムを防ぎます。OCSP レスポンスは約 30 分間キャッシュされ、更新された失効ステータスが反映されるまでに最大 30 分かかる場合があります。
Connection Functions における OCSP の結果
Connection Function が同じディストリビューションに設定されている場合、CloudFront は OCSP 検証の完了後に Connection Function を呼び出します。接続オブジェクトには、リーフ証明書と中間証明書の OCSP ステータスが含まれます。
{ "clientCertificate": { "certificates": { "leaf": { "subject": "CN=client.example.com, O=Example Org", "issuer": "CN=Intermediate CA, O=Example Org", "serialNumber": "00:a7:30:9e:73:7b:3e:63:bd:b7:c0:7e:bf:d5:c9:86", "validity": { "notBefore": "2024-01-01T00:00:00Z", "notAfter": "2025-01-01T00:00:00Z" }, "sha256Fingerprint": "AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90", "ocspEndpoint": "http://ocsp.example.org" }, "intermediates": [ { "subject": "CN=Intermediate CA, O=Example Org", "issuer": "CN=Root CA, O=Example Org", "serialNumber": "00:a7:30:9e:73:7b:3e:63:bd:b7:c0:7e:bf:d5:c9:86", "validity": { "notBefore": "2020-01-01T00:00:00Z", "notAfter": "2030-01-01T00:00:00Z" }, "sha256Fingerprint": "12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF", "ocspEndpoint": "http://ocsp.example.org" } ] }, "revocationStatus": { "chainValidity": "Valid", // "Valid" | "Invalid" | "Unknown" "certificates": { "leaf": { "method": "OCSP", // "OCSP" "status": "Good", // "Good" | "Revoked" | "Unknown" | "Error" "serialNumber": "00:a7:30:9e:73:7b:3e:63:bd:b7:c0:7e:bf:d5:c9:86" }, "intermediates": [ { "method": "OCSP", // "OCSP" "status": "Error", // "Good" | "Revoked" | "Unknown" | "Error" "errorType": "InternalError", // "InternalError" | "OCSP response verification failed: {Type}" "serialNumber": "00:a7:30:9e:73:7b:3e:63:bd:b7:c0:7e:bf:d5:c9:86" } ] } } }, "clientIp":"127.0.0.1", "endpoint":"d123.cloudfront.net", "distributionId":"E1NXS4MQZH501R", "connectionId":"xdzQ6lJUDUt8b7OuqOD8lmzOC9HcMaXPmhH5ZdzLCZpKxqzfCPpR4A==" }
chainValidity フィールドは、Valid、Invalid、Unknown のいずれかになります。個々の証明書の status 値は、Good、Revoked、Unknown、Error のいずれかになります。ステータスが Error の場合、errorType フィールドには、InternalError または OCSP response verification
failed: {Type} が含まれます。
Connection Function は、OCSP の結果を上書きできます。例えば、信頼された IP 範囲から取り消された証明書を許可したり、OCSP が追加のビジネスロジックに基づいて「良好」と報告した証明書を拒否したりできます。
注記
errorType フィールドは、ステータスが Error の場合にのみ表示されます。
例: 信頼できる IP 例外を使用したカスタム OCSP 処理
function connectionHandler(connection) { var revocationStatus = connection.clientCertificate.revocationStatus; var trustedIP = (connection.clientIp === "[IP_ADDRESS]"); if (revocationStatus.chainValidity === "Invalid") { if (trustedIP) { connection.allow(); } else { connection.deny(); } } else if (revocationStatus.certificates.leaf.status === "Error") { console.log(revocationStatus.certificates.leaf.errorType); connection.deny(); } else { connection.allow(); } }
OCSP の失敗動作
CloudFront が証明書の失効ステータスを判断できない場合 (OCSP レスポンダーに到達できない、エラーを返す、または「不明」を返すなど)、CloudFront はデフォルトで接続を拒否します。ソフトフェイル動作を実装するには、Connection Function を使用します。OCSP が有効で、クライアント証明書に OCSP URL がない場合、Connection Functions は実行されません。OCSP の結果は接続オブジェクトで使用でき、OCSP ステータスが未確定の場合でも関数は接続を許可できます。
async function connectionHandler(connection) { var revocationStatus = connection.clientCertificate.revocationStatus; if (revocationStatus.certificates.leaf.status === "Error" || revocationStatus.certificates.leaf.status === "Unknown") { // OCSP responder unreachable — allow connection (soft-fail) connection.logCustomData(`OCSP_SOFT_FAIL:${revocationStatus.certificates.leaf.errorType}`); return connection.allow(); } if (revocationStatus.chainValidity === "Invalid") { return connection.deny(); } return connection.allow(); }
CloudFront Functions と KeyValueStore を使用した証明書失効
CloudFront Connection Functions と KeyValueStore を使用すれば、外部依存関係なしに証明書失効チェックを実装できます。失効した証明書のシリアル番号のリストを KeyValueStore に保持し、Connection Function は TLS ハンドシェイク中に各クライアント証明書をこのリストと照合します。
証明書の失効プロセスは次のように機能します。
-
失効した証明書のシリアル番号を CloudFront KeyValueStore に保存します。
-
クライアントが証明書を提示すると、Connection Function が呼び出されます。
-
関数は、証明書のシリアル番号と KeyValueStore を照合します。
-
シリアル番号がストアで見つかった場合、証明書は失効しています。
-
関数は、失効した証明書の接続を拒否します。
このアプローチは、CloudFront のグローバルエッジネットワーク全体でほぼリアルタイムの失効チェックを提供します。
このアプローチを実装するには、以下が必要です。
-
ビューワー mTLS で設定されたディストリビューション
-
失効した証明書のシリアル番号を含む KeyValueStore
-
KeyValueStore にクエリを実行して証明書のステータスを確認する Connection Function
クライアントが接続されると、CloudFront はトラストストアに対して証明書を検証し、Connection Function を実行します。関数は証明書のシリアル番号と KeyValueStore を確認し、接続を許可または拒否します。
ステップ 1: 失効した証明書の KeyValueStore を作成する
失効した証明書のシリアル番号を JSON 形式で準備します。
{ "data": [ { "key": "ABC123DEF456", "value": "" }, { "key": "789XYZ012GHI", "value": "" } ] }
この JSON ファイルを S3 バケットにアップロードし、KeyValueStore を作成します。
aws s3 cp revoked-serials.json s3://your-bucket-name/revoked-serials.json aws cloudfront create-key-value-store \ --name revoked-serials-kvs \ --import-source '{ "SourceType": "S3", "SourceARN": "arn:aws:s3:::your-bucket-name/revoked-serials.json" }'
KeyValueStore がプロビジョニングを完了するまで待ちます。次の方法でステータスを確認します。
aws cloudfront get-key-value-store --name "revoked-serials-kvs"
ステップ 2: 失効 Connection Function を作成する
証明書のシリアル番号と KeyValueStore を確認する Connection Function を作成します。
aws cloudfront create-connection-function \ --name "revocation-control" \ --connection-function-config file://connection-function-config.json \ --connection-function-code file://connection-function-code.txt
設定ファイルで KeyValueStore の関連付けを指定します。
{ "Runtime": "cloudfront-js-2.0", "Comment": "A function that implements revocation control via KVS", "KeyValueStoreAssociations": { "Quantity": 1, "Items": [ { "KeyValueStoreArn": "arn:aws:cloudfront::account-id:key-value-store/kvs-id" } ] } }
Connection Function のサンプルコード。
import cf from 'cloudfront'; async function connectionHandler(connection) { const kvsHandle = cf.kvs(); // Get client serial number from client certificate const clientSerialNumber = connection.clientCertificate.certificates.leaf.serialNumber; // Check KVS to see if serial number exists as a key // Remove : from the clientSerialNumber if KVS entries dont have it const serialNumberExistsInKvs = await kvsHandle.exists(clientSerialNumber.replaceAll(":", "")); // Deny connection if serial number exists in KVS if (serialNumberExistsInKvs) { console.log("Connection denied — certificate revoked"); connection.logCustomData("Connection denied — certificate revoked"); return connection.deny(); } // Allow connections that don't exist in KVS console.log("Connection allowed"); return connection.allow(); }
ステップ 3: 失効関数をテストする
CloudFront コンソールを使用し、サンプル証明書を使用して Connection Function をテストします。コンソールの Connection Function に移動し、[テスト] タブを使用します。
-
PEM 形式のサンプル証明書をテストインターフェイスに貼り付けます。
-
オプションで、IP ベースのロジックをテストするクライアント IP アドレスを指定します。
-
[関数をテスト] を選択して、実行結果を表示します。
-
実行ログを確認し、関数ロジックを検証します。
有効な証明書と失効した証明書の両方を使用してテストし、関数が両方のシナリオを正しく処理することを確認します。
ステップ 4: 関数をディストリビューションに関連付ける
Connection Function を発行したら、mTLS が有効なディストリビューションに関連付けて、証明書失効チェックを有効にします。ディストリビューション設定に移動し、「ビューワー相互認証 (mTLS)」セクションまでスクロールし、Connection Function を選択して変更を保存します。
高度な失効戦略
OCSP と Connection Function ロジックを組み合わせる
CA 権限による失効チェックのために OCSP を有効にし、その上にカスタムポリシー用の Connection Function を重ねることができます。Connection Function は OCSP の結果を受け取り、追加のロジックを適用できます。
-
猶予期間 - 証明書のローテーション中に、定義された期間、内部ネットワークから失効した証明書を許可します。
-
緊急アクセス - OCSP が失効ステータスを報告しても特定の IP からの接続を許可します。
-
カスタム拒否ロジック - KeyValueStore の独自の失効データに基づいて、OCSP が「良好」と報告する証明書をブロックします。
例 OCSP + KVS を組み合わせた失効管理
import cf from 'cloudfront'; async function connectionHandler(connection) { var kvsHandle = cf.kvs(); var revocationStatus = connection.clientCertificate.revocationStatus; var serialNumber = connection.clientCertificate.certificates.leaf.serialNumber; // Check your own revocation list first (immediate revocation, no cache delay) var inKvs = await kvsHandle.exists(serialNumber.replaceAll(":", "")); if (inKvs) { connection.logCustomData("KVS_REVOKED:" + serialNumber); return connection.deny(); } // Then check OCSP result if (revocationStatus.chainValidity === 'Valid' && revocationStatus.certificates.leaf.status === "Revoked") { // OCSP says revoked — allow grace period from trusted IPs if (connection.clientIp.startsWith("10.0.")) { connection.logCustomData("GRACE_PERIOD:" + serialNumber + ":" + connection.clientIp); return connection.allow(); } connection.logCustomData("OCSP_REVOKED:" + serialNumber); return connection.deny(); } connection.allow(); }
このパターンでは、KVS 経由の即時失効 (キャッシュ遅延なし) と OCSP 経由の CA 権限による失効があり、その間にカスタム例外処理が行われます。