

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

# 寫入 CloudFront 連線函數程式碼以進行交互 TLS （檢視器） 驗證
<a name="write-connection-function-code"></a>

CloudFront Connection Functions 可讓您為 mTLS 憑證驗證和自訂身分驗證邏輯撰寫輕量型 JavaScript 函數。您的 Connection Function 程式碼可以驗證用戶端憑證、實作裝置特定的身分驗證規則、處理憑證撤銷案例，以及針對全球 CloudFront 節點的 TLS 連線做出允許/拒絕決策。

連線函數提供強而有力的方式來使用您自己的商業邏輯擴展 CloudFront 的內建憑證驗證。與處理 HTTP 資料的檢視器請求和檢視器回應函數不同，Connection Functions 會在 TLS 層運作，並可存取憑證資訊、用戶端 IP 地址和 TLS 連線詳細資訊。這使得它們非常適合用於實作零信任安全模型、裝置身分驗證系統和超出標準 PKI 驗證的自訂憑證驗證政策。

您的 Connection Function 程式碼會在安全、隔離且啟動時間低於毫秒的環境中執行，並且可以擴展以處理每秒數百萬個連線。執行時間已針對憑證驗證工作負載進行最佳化，並提供與 CloudFront KeyValueStore 的內建整合，以進行即時資料查詢操作，實現複雜的身分驗證案例，例如憑證撤銷清單檢查和裝置允許清單驗證。

為了協助您撰寫有效的連線函數程式碼，請參閱下列主題。如需完整的程式碼範例和step-by-step教學課程，請參閱本指南中的教學課程章節，並探索 CloudFront 主控台中提供的連線函數範例。

**Topics**
+ [CloudFront Connection Function 使用案例和用途](#connection-function-use-cases)
+ [CloudFront Connection Function 事件結構和回應格式](#connection-function-event-structure)
+ [CloudFront Connection Functions JavaScript 執行期功能](#connection-function-javascript-runtime)
+ [CloudFront Connection Function 協助程式方法和 APIs](#connection-function-helper-methods)
+ [CloudFront Connection Function KeyValueStore 整合](#connection-function-kvs-integration)
+ [使用非同步並等待](#connection-function-async-await)
+ [連線函數程式碼範例](#connection-function-code-examples)

## CloudFront Connection Function 使用案例和用途
<a name="connection-function-use-cases"></a>

寫入 CloudFront Connection Function 之前，請仔細判斷您需要實作的憑證驗證或身分驗證邏輯類型。連線函數是專為需要超出標準 PKI 憑證檢查自訂驗證的特定使用案例而設計。了解您的使用案例可協助您設計符合您安全需求的高效程式碼，同時維持最佳效能。

常見的連線函數使用案例包括：
+ **憑證撤銷處理** – 實作自訂政策來處理撤銷的憑證，包括憑證輪換的寬限期、內部裝置的信任網路例外狀況，或撤銷的憑證可能需要暫時存取的緊急存取案例。
+ **選用的 mTLS 支援** – 使用不同的身分驗證政策處理 mTLS 和非 mTLS 連線，可讓您為支援憑證的用戶端提供增強的安全性，同時保持與舊版用戶端的相容性。
+ **以 IP 為基礎的身分**驗證 – 結合憑證驗證與用戶端 IP 地址檢查，以提高安全性，例如限制來自特定地理區域、公司網路或已知惡意 IP 範圍的存取。
+ **多租戶憑證驗證** – 實作租戶特定的驗證規則，其中根據用戶端憑證發行者或主體屬性，套用不同的憑證授權單位或驗證條件。
+ **以時間為基礎的存取控制** – 強制執行以時間為基礎的限制，其中憑證僅在特定時間、維護時段或商業期間內有效，即使憑證本身尚未過期。

在 CloudFront 執行標準憑證驗證 （信任鏈驗證、過期檢查和簽章驗證） 之後，但在建立 TLS 連線之前執行連線函數。此時間可讓您靈活地新增自訂驗證條件，同時受益於 CloudFront 的內建憑證驗證。您的函數會收到標準驗證的結果，並可以根據標準和自訂條件，做出是否允許或拒絕連線的明智決策。

設計連線函數時，請考慮驗證邏輯的效能影響。函數具有 5 毫秒的執行限制，因此應針對速度最佳化複雜的操作。使用 KeyValueStore 進行快速資料查詢，而非複雜的計算，並建構驗證邏輯以針對無效的憑證快速失敗。

## CloudFront Connection Function 事件結構和回應格式
<a name="connection-function-event-structure"></a>

CloudFront Connection Functions 會收到與檢視器請求和檢視器回應函數不同的事件結構。連線函數會收到憑證和連線資訊，供您用來做出身分驗證決策，而不是 HTTP 請求/回應資料。

**Topics**
+ [Connection Functions 的事件結構](#connection-function-event-structure-details)
+ [Connection Functions 回應格式](#connection-function-response-format)

### Connection Functions 的事件結構
<a name="connection-function-event-structure-details"></a>

Connection Functions 會收到事件物件，其中包含憑證和連線資訊。函數的事件結構如下所示：

```
{
  "clientCertificate": {
    "certificates": {
      "leaf": {
        "serialNumber": "string",
        "issuer": "string",
        "subject": "string",
        "validity": {
          "notBefore": "string",
          "notAfter": "string",
        },
        "sha256Fingerprint": "string"
      }
    }
  },
  "clientIp": "string",
  "endpoint": "string",
  "distributionId": "string",
  "connectionId": "string"
}
```

以下是事件物件結構的範例：

```
{
  "clientCertificate": {
    "certificates": {
      "leaf": {
        "serialNumber": "00:9e:2a:af:16:56:e5:47:25:7d:2e:38:c3:f9:9d:57:fa",
        "issuer": "C=US, O=Ram, OU=Edge, ST=WA, CN=mTLS-CA, L=Snoqualmie",
        "subject": "C=US, O=Ram, OU=Edge, ST=WA, CN=mTLS-CA, L=Snoqualmie",
        "validity": {
          "notBefore": "2025-09-10T23:43:10Z",
          "notAfter": "2055-09-11T00:43:02Z"
        },
        "sha256Fingerprint": "_w6bJ7aOAlGOj7NUhJxTfsfee-ONg_xop3_PTgTJpqs="
      }
    }
  },
  "clientIp": "127.0.0.1",
  "endpoint": "d3lch071jze0cb.cloudfront.net",
  "distributionId": "E1NXS4MQZH501R",
  "connectionId": "NpvTe1925xfj24a67sPQr7ae42BIq03FGhJJKfrQYWZcWZFp96SIIg=="
}
```

### Connection Functions 回應格式
<a name="connection-function-response-format"></a>

您的 Connection Function 必須傳回回應物件，指出是否允許或拒絕連線。使用協助程式方法來做出連線決策：

```
function connectionHandler(connection) {
    // Helper methods to allow or deny connections
    if (/* some logic to determine if function should allow connection */) {
        connection.allow();
    } else {
        connection.deny();
    }
}
```

與檢視器請求和檢視器回應函數不同，連線函數無法修改 HTTP 請求或回應。他們只能允許或拒絕 TLS 連線。

## CloudFront Connection Functions JavaScript 執行期功能
<a name="connection-function-javascript-runtime"></a>

CloudFront Connection Functions 使用 CloudFront Functions JavaScript 執行期 2.0，可提供專為憑證驗證工作負載最佳化的安全且高效能環境。執行時間設計為在幾毫秒內開始，並處理 CloudFront 全球邊緣網路中數百萬個並行執行。

執行期環境包含完整的 JavaScript 語言支援：
+ **ECMAScript 2020 (ES11) 支援** – 現代 JavaScript 功能，包括用於處理大型憑證序號的選用鏈結 (？.)、 nullish coalescing (？？) 和 BigInt 
+ **內建物件** – 物件、陣列、JSON、數學和日期等標準 JavaScript 物件
+ **主控台記錄** – 使用 console.log() 進行偵錯和監控憑證驗證決策。日誌可在測試期間即時提供，有助於疑難排解開發中的驗證邏輯
+ **KeyValueStore 整合** – 原生存取 CloudFront KeyValueStore 以進行超快速的資料查詢操作，啟用即時憑證撤銷檢查、裝置允許清單驗證和租用戶特定的組態擷取

連線函數已針對憑證驗證案例的高效能進行最佳化。執行時間會自動處理記憶體管理、垃圾收集和資源清理，以確保數百萬個並行連線的一致效能。所有操作的設計都具有決定性和快速性，KeyValueStore 查詢通常在微秒內完成。

執行時間環境在函數執行之間完全隔離，確保不同用戶端連線之間的資料不會洩漏。每個函數執行都以清除狀態開頭，無法存取先前的執行結果或來自其他連線的用戶端資料。

## CloudFront Connection Function 協助程式方法和 APIs
<a name="connection-function-helper-methods"></a>

CloudFront Connection Functions 提供專門的協助程式方法，旨在簡化憑證驗證決策並增強可觀測性。這些方法針對連線驗證工作流程進行最佳化，並與 CloudFront 的連線記錄和監控系統無縫整合。
+ **connection.allow()** – 允許 TLS 連線繼續。此方法會通知 CloudFront 完成 TLS 交握，並允許用戶端建立連線。當憑證驗證通過且滿足任何自訂身分驗證邏輯時，請使用此選項
+ **connection.deny()** – 拒絕 TLS 連線並終止交握。此方法會立即關閉連線，並防止任何 HTTP 流量流動。用戶端將收到 TLS 連線錯誤。將此用於無效的憑證、失敗的身分驗證或政策違規
+ **connection.logCustomData()** – 將自訂資料新增至連線日誌 （最多 800 個位元組的 UTF-8 文字）。此方法可讓您在 CloudFront 連線日誌中包含驗證結果、憑證詳細資訊或決策理由，以進行安全性監控、合規稽核和故障診斷

這些方法提供簡潔的宣告式界面，用於做出連線決策，並記錄監控和偵錯的相關資訊。允許/拒絕模式可確保函數的意圖明確，且 CloudFront 可以根據您的決定最佳化連線處理。CloudFront 連線日誌會立即提供自訂記錄資料，並可搭配日誌分析工具使用，以進行安全性監控和操作洞察。

在函數完成之前，請務必呼叫 connection.allow() 或 connection.deny()。如果不呼叫任何方法，CloudFront 預設會拒絕連線，作為安全預防措施。

## CloudFront Connection Function KeyValueStore 整合
<a name="connection-function-kvs-integration"></a>

CloudFront Connection Functions 可以使用 CloudFront KeyValueStore 針對憑證驗證案例執行超快速的資料查詢。KeyValueStore 對 Connection Functions 特別強大，因為它可在所有 CloudFront 節點提供全域、最終一致的資料存取，以及微秒的查詢時間。這使得它非常適合用於維護 TLS 交握期間需要存取的憑證撤銷清單、裝置允許清單、租戶組態和其他驗證資料。

KeyValueStore 整合專為高效能連線驗證工作流程而設計：
+ **kvsHandle.exists(key)** – 檢查 KeyValueStore 中是否存在金鑰，而不擷取值。這是二進位驗證案例最有效的方法，例如憑證撤銷檢查，您只需知道憑證序號是否在撤銷清單中
+ **kvsHandle.get(key)** – 針對更複雜的驗證案例，從 KeyValueStore 擷取值。當您需要存取與憑證或裝置識別符相關聯的組態資料、驗證規則或中繼資料時，請使用此選項

KeyValueStore 操作是非同步的，必須搭配非同步/等待語法使用。KeyValueStore 的總大小限制為 10MB，並支援最多 1，000 萬個鍵值對。KeyValueStore 資料最終在所有節點保持一致，更新通常會在幾秒鐘內傳播。

為了獲得最佳效能，請建構您的 KeyValueStore 金鑰，將查詢操作降至最低。使用憑證序號做為簡易撤銷檢查的金鑰，或建立合併多 CA 環境發行者雜湊和序號的複合金鑰。設計資料結構時，請考慮關鍵複雜性與 KeyValueStore 容量之間的權衡。

## 使用非同步並等待
<a name="connection-function-async-await"></a>

連線函數支援使用非同步/等待語法的非同步操作，這對於使用 KeyValueStore 操作或其他非同步任務至關重要。非同步/等待模式可確保函數在做出連線決策之前等待 KeyValueStore 查詢完成，同時維持 TLS 交握處理所需的高效能特性。

適當的非同步/等待用量對於連線函數至關重要，因為 KeyValueStore 操作雖然速度非常快，但仍是需要跨 CloudFront 分散式基礎設施協調的網路操作。執行時間會自動處理 promise 解析度，並確保您的函數在 5 毫秒執行限制內完成。

**Example ：使用 KeyValueStore 的非同步連線函數**  

```
import cf from 'cloudfront';

async function connectionHandler(connection) {
    const kvsHandle = cf.kvs();
    
    // Async operation to check KeyValueStore for certificate revocation
    const isRevoked = await kvsHandle.exists(connection.clientCertificate.certificates.leaf.serialNumber);
    
    if (isRevoked) {
        // Log the revocation decision with certificate details
        connection.logCustomData(`REVOKED_CERT:${connection.clientCertificate.certificates.leaf.serialNumber}:${connection.clientCertificate.certificates.leaf.issuer}`);
        console.log(`Denying connection for revoked certificate: ${connection.clientCertificate.certificates.leaf.serialNumber}`);
        return connection.deny();
    }
    
    // Log successful validation for monitoring
    connection.logCustomData(`VALID_CERT:${connection.clientCertificate.certificates.leaf.serialNumber}`);
    console.log(`Allowing connection for valid certificate: ${connection.clientCertificate.certificates.leaf.serialNumber}`);
    return connection.allow();
}
```

呼叫 KeyValueStore 方法或其他非同步操作時，一律使用非同步/等待。Connection Function 執行時間會自動處理 promise 解析，並確保在 TLS 交握處理的嚴格時間限制內有適當的執行流程。避免使用 .then() 或回呼模式，因為非同步/等待可在連線函數環境中提供更明確的錯誤處理和更好的效能。

設計非同步連線函數時，請建構您的程式碼，以盡可能減少 KeyValueStore 操作的數量，並儘早在驗證邏輯中執行這些操作。這可確保最大效能，並降低高流量期間逾時問題的風險。請考慮批次處理相關的驗證檢查，並針對您的使用案例使用最有效率的 KeyValueStore 方法 (exists() vs get())。

## 連線函數程式碼範例
<a name="connection-function-code-examples"></a>

下列範例示範適用於不同驗證案例的常見連線函數模式。使用這些範例做為您自己的連線函數實作的起點。

**Example ：裝置憑證驗證**  
此範例會驗證 IoT 裝置、遊戲主控台和其他用戶端身分驗證案例的裝置序號和憑證主旨欄位：  

```
async function connectionHandler(connection) {
    // Custom validation: check device serial number format
    const serialNumber = connection.clientCertificate.certificates.leaf.serialNumber;
    if (!serialNumber.startsWith("DEV")) {
        connection.logCustomData(`INVALID_SERIAL:${serialNumber}`);
        return connection.deny();
    }
    
    // Validate certificate subject contains required organizational unit
    const subject = connection.clientCertificate.certificates.leaf.subject;
    if (!subject.includes("OU=AuthorizedDevices")) {
        connection.logCustomData(`INVALID_OU:${subject}`);
        return connection.deny();
    }
    
    // Allow connection for valid devices
    connection.logCustomData(`VALID_DEVICE:${serialNumber}`);
    return connection.allow();
}
```
除了標準憑證驗證之外，此函數會執行多個驗證檢查，包括裝置序號格式和組織單位驗證。

**Example ：選用具有混合身分驗證的 mTLS**  
此範例使用不同的身分驗證政策處理 mTLS 和非 mTLS 連線：  

```
async function connectionHandler(connection) {
    if (connection.clientCertificate) {
        // mTLS connection - enhanced validation for certificate holders
        const subject = connection.clientCertificate.certificates.leaf.subject;
        connection.logCustomData(`MTLS_SUCCESS:${subject}:${connection.clientIp}`);
        console.log(`mTLS connection from: ${subject}`);
        return connection.allow();
    } else {
        // Non-mTLS connection - apply IP-based restrictions
        const clientIp = connection.clientIp;
        
        // Only allow non-mTLS from specific IP ranges
        if (clientIp.startsWith("203.0.113.") || clientIp.startsWith("198.51.100.")) {
            connection.logCustomData(`NON_MTLS_ALLOWED:${clientIp}`);
            console.log(`Non-mTLS connection allowed from: ${clientIp}`);
            return connection.allow();
        }
        
        connection.logCustomData(`NON_MTLS_DENIED:${clientIp}`);
        return connection.deny();
    }
}
```
此函數為具有憑證的用戶端提供增強的安全性，同時保持與信任 IP 範圍內舊版用戶端的相容性。