

# 高级吊销场景
<a name="advanced-revocation-scenarios"></a>

对于更复杂的证书吊销要求，请考虑以下其他配置：

**Topics**
+ [将证书吊销列表（CRL）转换为 KeyValueStore 格式](#convert-crl-kvs-format)
+ [处理多个证书颁发机构](#handle-multiple-cas)
+ [将自定义数据添加到连接日志](#add-custom-data-logs)
+ [管理 CRL 更新](#manage-crl-updates)
+ [规划 KeyValueStore 容量](#plan-kvs-capacity)

## 将证书吊销列表（CRL）转换为 KeyValueStore 格式
<a name="convert-crl-kvs-format"></a>

如果您拥有证书吊销列表（CRL）文件，则可以使用 OpenSSL 和 jq 将其转换为 KeyValueStore JSON 格式：

**将 CRL 转换为 KeyValueStore 格式**

从 CRL 文件中提取序列号：

```
openssl crl -text -noout -in rfc5280_CRL.crl | \
  awk '/Serial Number:/ {print $3}' | \
  cut -d'=' -f2 | \
  sed 's/../&:/g;s/:$//' >> serialnumbers.txt
```

将序列号转换为 KeyValueStore JSON 格式：

```
jq -R -s 'split("\n") | map(select(length > 0)) | {data: map({"key": ., "value": ""})}' \
  serialnumbers.txt >> serialnumbers_kvs.json
```

将格式化的文件上传到 S3，然后按照第 1 步的说明创建 KeyValueStore。

## 处理多个证书颁发机构
<a name="handle-multiple-cas"></a>

当您的 TrustStore 包含多个证书颁发机构（CA）时，请在您的 KeyValueStore 键中包含颁发者信息，以避免来自不同 CA 的序列号相同的证书之间发生冲突。

对于多 CA 场景，请使用颁发者的 SHA1 哈希和序列号的组合作为键：

```
import cf from 'cloudfront';

async function connectionHandler(connection) {
    const kvsHandle = cf.kvs();
    const clientCert = connection.clientCertInfo;
    
    // Create composite key with issuer hash and serial number
    const issuer = clientCert.issuer.replace(/[^a-zA-Z0-9]/g, '').substring(0, 20);
    const serialno = clientCert.serialNumber;
    const compositeKey = `${issuer}_${serialno}`;
    
    const cert_revoked = await kvsHandle.exists(compositeKey);
    
    if (cert_revoked) {
        console.log(`Blocking revoked cert: ${serialno} from issuer: ${issuer}`);
        connection.deny();
    } else {
        connection.allow();
    }
}
```

**注意**  
使用颁发者标识符 \+ 序列号可创建较长的键，这可能会减少可存储在 KeyValueStore 中的条目总数。

## 将自定义数据添加到连接日志
<a name="add-custom-data-logs"></a>

连接函数可以使用 logCustomData 方法将自定义数据添加到 CloudFront 连接日志。这使您能够在日志中包含吊销检查结果、证书信息或其他相关数据。

```
async function connectionHandler(connection) {
    const kvsHandle = cf.kvs();
    const clientSerialNumber = connection.clientCertInfo.serialNumber;
    const serialNumberExistsInKvs = await kvsHandle.exists(clientSerialNumber);
    
    if (serialNumberExistsInKvs) {
        // Log revocation details to connection logs
        connection.logCustomData(`REVOKED:${clientSerialNumber}:DENIED`);
        console.log("Connection denied - certificate revoked");
        return connection.deny();
    }
    
    // Log successful validation
    connection.logCustomData(`VALID:${clientSerialNumber}:ALLOWED`);
    console.log("Connection allowed");
    return connection.allow();
}
```

自定义数据的限制为 800 字节的有效 UTF-8 文本。如果超过此限制，CloudFront 会将数据截断至最近的有效 UTF-8 边界。

**注意**  
仅在为分配启用连接日志时，自定义数据日志记录才起作用。如果未配置连接日志，则 logCustomData 方法将不执行任何操作。

## 管理 CRL 更新
<a name="manage-crl-updates"></a>

证书颁发机构可颁发两种类型的 CRL：
+ **完整 CRL**：包含所有已吊销证书的完整列表
+ **Delta CRL**：仅列出自上次完整 CRL 以来吊销的证书

对于完整 CRL 更新，使用更新后的数据创建一个新的 KeyValueStore，然后将连接函数关联重定向至此新的 KeyValueStore。这种方法比计算差异并执行增量更新更加简单。

对于 delta CRL 更新，使用 update-keys 命令将新的已吊销证书添加到现有 KeyValueStore：

```
aws cloudfront update-key-value-store \
  --name "revoked-serials-kvs" \
  --if-match "current-etag" \
  --put file://delta-revoked-serials.json
```

## 规划 KeyValueStore 容量
<a name="plan-kvs-capacity"></a>

KeyValueStore 的大小限制为 5 MB，并且最多支持 1000 万个键值对。根据您的键格式和数据大小规划吊销列表容量：
+ **仅序列号**：高效存储，用于进行简单吊销检查
+ **颁发者标识符 \+ 序列号**：用于多 CA 环境的较长键

对于大型吊销列表，可以考虑实施分层方法，为不同的证书类别或时段维护单独的 KeyValueStore。