

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 憑證撤銷
<a name="certificate-revocation"></a>

當憑證因入侵、政策變更或終止的關係而需要撤銷時，您需要在 mTLS 交握期間拒絕這些憑證的機制。CloudFront 提供兩種憑證撤銷的原生方法，您可以結合它們進行分層控制。
+ **OCSP （線上憑證狀態通訊協定）** — CloudFront 會即時查詢憑證授權單位的 OCSP 回應程式，以檢查用戶端憑證是否已撤銷。在信任存放區上啟用 OCSPCloudFront 會在 TLS 交握期間自動處理驗證。OCSP 結果也會顯示在 Connection Functions 中，讓您以程式設計方式存取撤銷狀態以進行自訂決策。
+ **CloudFront Functions 和 KeyValueStore** — 您可以在 CloudFront KeyValueStore 中維護撤銷的憑證序號清單。連線函數會在 TLS 交握期間查詢 KeyValueStore，並允許或拒絕連線。這可讓您完全控制撤銷資料、更新時間，以及自訂邏輯，例如寬限期或 IP 型例外狀況。


**比較：OCSP 與使用 KeyValueStore 的 CloudFront 函數**  

|  | OCSP | CloudFront 函數 \+ KeyValueStore | 
| --- | --- | --- | 
| 資料來源 | 憑證授權單位的 OCSP 回應程式 | 您可以管理撤銷清單 | 
| 更新機制 | CA 的即時查詢 | 您將更新推送至 KeyValueStore | 
| 自訂邏輯 | 透過 Connection Functions 提供 | 內建於函數程式碼中 | 
| 外部相依性 | 需要 CA OCSP 回應程式可用性 | 無外部相依性 | 
| 最適合 | 維護 OCSP 回應者的 CAs；即時 CA 授權狀態 | 自我管理撤銷；自訂政策；無 OCSP 支援的 CAs  | 

您可以同時使用這兩種方法。啟用 OCSP 進行 CA 授權撤銷檢查，然後使用連線函數在 OCSP 結果之上分層其他邏輯，例如，允許在寬限期內從信任的 IP 範圍撤銷憑證。

## OCSP （線上憑證狀態通訊協定）
<a name="ocsp-revocation"></a>

OCSP 是一種即時通訊協定，可直接向憑證授權單位 (CA) 檢查憑證的撤銷狀態。在憑證簽署程序期間，CA 會在憑證中嵌入 OCSP 回應程式 URL。當用戶端在 mTLS 交握期間呈現其憑證時，CloudFront 會將 OCSP 請求傳送至內嵌的回應程式 URL，並對回應採取動作：有效憑證繼續，撤銷的憑證會終止。

CloudFront 會根據各自的 OCSP 回應程式 URLs，驗證整個憑證鏈：分葉憑證和最多三個中繼憑證。信任存放區中的根憑證會從 OCSP 驗證中排除。

### 啟用 OCSP
<a name="enable-ocsp"></a>

在信任存放區上啟用 OCSP。啟用時，CloudFront 會自動對其授權資訊存取 (AIA) 延伸模組中包含 OCSP 回應者 URL 的任何用戶端憑證執行 OCSP 驗證。啟用 OCSP 後，整個用戶端憑證鏈必須具有 OCSP URL。如果用戶端憑證鏈中的任何憑證不包含 OCSP URL，CloudFront 將不會建立連線。

CloudFront 會在邊緣快取 OCSP 回應，以減少往返時間並防止 OCSP 回應程式停機時間。OCSP 回應會快取約 30 分鐘，而更新的撤銷狀態最多可能需要 30 分鐘才會反映。

### OCSP 會產生連線函數
<a name="ocsp-results-connection-functions"></a>

在相同分佈上設定連線函數時，CloudFront 會在 OCSP 驗證完成後叫用它。連線物件包含分葉和中繼憑證的 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`、`Unknown`、 `Revoked`或 `Error`。當狀態為 `OCSP response verification failed: {Type}`時， `errorType` 欄位包含 `InternalError`或 `Error`。

連線函數可以覆寫 OCSP 結果 – 例如，允許從信任 IP 範圍撤銷的憑證，或拒絕 OCSP 根據其他商業邏輯回報為「良好」的憑證。

**注意**  
只有當狀態為 時， `errorType` 欄位才會出現`Error`。

### 範例：具有信任 IP 例外狀況的自訂 OCSP 處理
<a name="ocsp-example"></a>

```
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 失敗行為
<a name="ocsp-failure-behavior"></a>

當 CloudFront 無法判斷憑證的撤銷狀態時，因為 OCSP 回應程式無法連線、 傳回錯誤或傳回「未知」時，CloudFront 預設會拒絕連線。若要實作軟失敗行為，請使用連線函數。如果啟用 OCSP 且用戶端憑證中沒有 OCSP URL，則不會執行連線函數。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 的憑證撤銷
<a name="kvs-revocation"></a>

您可以使用 CloudFront Connection Functions 搭配 KeyValueStore 實作憑證撤銷檢查，而不需要任何外部相依性。您可以在 KeyValueStore 中維護撤銷的憑證序號清單，而且連線函數會在 TLS 交握期間針對此清單檢查每個用戶端憑證。

憑證撤銷程序的運作方式如下：

1. 將撤銷的憑證序號儲存在 CloudFront KeyValueStore 中。

1. 當用戶端提供憑證時，就會叫用您的連線函數。

1. 函數會根據 KeyValueStore 檢查憑證的序號。

1. 如果在存放區中找到序號，則會撤銷憑證。

1. 您的函數拒絕已撤銷憑證的連線。

此方法提供跨 CloudFront 全球邊緣網路的near-real-time撤銷檢查。

若要實作此方法，您需要：
+ 使用檢視器 mTLS 設定的分佈
+ 包含撤銷憑證序號的 KeyValueStore 
+ 查詢 KeyValueStore 以檢查憑證狀態的連線函數

當用戶端連線時，CloudFront 會根據信任存放區驗證憑證，然後執行連線函數。您的函數會根據 KeyValueStore 檢查憑證序號，並允許或拒絕連線。

### 步驟 1：為已撤銷的憑證建立 KeyValueStore
<a name="step1-create-kvs"></a>

以 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：建立撤銷連線函數
<a name="step2-create-revocation-function"></a>

建立連線函數，根據 KeyValueStore 檢查憑證序號：

```
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"
      }
    ]
  }
}
```

連線函數程式碼範例：

```
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：測試您的撤銷函數
<a name="step3-test-revocation-function"></a>

使用 CloudFront 主控台以範例憑證測試連線函數。導覽至 主控台中的連線函數，並使用測試索引標籤。
+ 將 PEM 格式的範例憑證貼入測試界面。
+ 選擇性地指定用戶端 IP 地址，以測試 IP 型邏輯。
+ 選擇**測試函數**以查看執行結果。
+ 檢閱執行日誌以驗證您的函數邏輯。

使用有效和已撤銷的憑證進行測試，以確保函數正確處理這兩種案例。

### 步驟 4：將函數與分佈建立關聯
<a name="step4-associate-function"></a>

發佈連線函數後，請將其與啟用 mTLS 的分佈建立關聯，以啟用憑證撤銷檢查。導覽至您的分佈設定，捲動至「檢視者交互驗證 (mTLS)」區段，選取連線函數，然後儲存變更。

## 進階撤銷策略
<a name="advanced-revocation-strategies"></a>

### 結合 OCSP 與連線函數邏輯
<a name="combine-ocsp-kvs"></a>

您可以為 CA 授權撤銷檢查啟用 OCSP，並在自訂政策的頂端分層連線函數。Connection Function 會收到 OCSP 結果，並可套用其他邏輯：
+ **寬限期** — 允許在憑證輪換期間，在定義的期間內從內部網路撤銷憑證。
+ **緊急存取** — 即使 OCSP 報告撤銷狀態，也允許來自特定 IPs連線。
+ **自訂拒絕邏輯** — 根據您在 KeyValueStore 中的撤銷資料，封鎖 OCSP 報告為「良好」的憑證。

**Example 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 授權撤銷，並在兩者之間處理自訂例外狀況。