

# Implementar a revogação de certificados para TLS mútua (visualizador) com o CloudFront Functions e o KeyValueStore
<a name="implement-certificate-revocation"></a>

É possível funções de conexão do CloudFront com o KeyValueStore para implementar a verificação de revogação de certificados. Isso permite manter uma lista de números de série de certificados revogados e comparar os certificados de cliente com essa lista durante o handshake do TLS.

Para implementar a revogação de certificados, os seguintes componentes são necessário:
+ Uma distribuição configurada com mTLS de visualizador.
+ Um KeyValueStore contendo números de série de certificados revogados.
+ Uma função de conexão que consulta o KeyValueStore para verificar o status do certificado.

Quando um cliente se conecta, o CloudFront valida o certificado em relação ao armazenamento confiável e, em seguida, executa a função de conexão. A função compara o número de série do certificado com o número de série no KeyValueStore e permite ou nega a conexão.

**Topics**
+ [Etapa 1: criar um KeyValueStore para certificados revogados](create-kvs-revoked-certificates.md)
+ [Etapa 2: criar a função de conexão de revogação](create-revocation-connection-function.md)
+ [Etapa 3: testar a função de revogação](test-revocation-function.md)
+ [Etapa 4: associar a função à distribuição](associate-function-distribution.md)
+ [Cenários avançados de revogação](advanced-revocation-scenarios.md)

# Etapa 1: criar um KeyValueStore para certificados revogados
<a name="create-kvs-revoked-certificates"></a>

Crie um KeyValueStore para armazenar números de série de certificados revogados que a função de conexão possa verificar durante conexões mTLS.

Primeiro, prepare os números de série de certificados revogados no formato JSON:

```
{
  "data": [
    {
      "key": "ABC123DEF456",
      "value": ""
    },
    {
      "key": "789XYZ012GHI", 
      "value": ""
    }
  ]
}
```

Faça upload desse arquivo JSON em um bucket do S3 e, em seguida, crie o 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"
  }'
```

Aguarde até que o KeyValueStore conclua o provisionamento. Verifique o status com:

```
aws cloudfront get-key-value-store --name "revoked-serials-kvs"
```

# Etapa 2: criar a função de conexão de revogação
<a name="create-revocation-connection-function"></a>

Crie uma função de conexão que compare os números de série de certificado em relação ao KeyValueStore para determinar se os certificados foram revogados.

Crie uma função de conexão que compare o número de série dos certificados com os números presentes no 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
```

O arquivo de configuração especifica a associação do 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"
      }
    ]
  }
}
```

O código da função de conexão verifica se há certificados revogados no KeyValueStore:

```
import cf from 'cloudfront';

async function connectionHandler(connection) {
    const kvsHandle = cf.kvs();
    
    // Get parsed client serial number from client certificate
    const clientSerialNumber = connection.clientCertInfo.serialNumber;
    
    // Check KVS to see if serial number exists as a key
    const serialNumberExistsInKvs = await kvsHandle.exists(clientSerialNumber);
    
    // Deny connection if serial number exists in KVS
    if (serialNumberExistsInKvs) {
        console.log("Connection denied - certificate revoked");
        return connection.deny();
    }
    
    // Allow connections that don't exist in kvs
    console.log("Connection allowed");
    return connection.allow();
}
```

# Etapa 3: testar a função de revogação
<a name="test-revocation-function"></a>

Use o console do CloudFront para testar a função de conexão com certificados de exemplo. Acesse a função de conexão no console e use a guia “Testar”.

**Teste com certificados de exemplo**

1. Cole um certificado de exemplo no formato PEM na interface de teste.

1. Opcionalmente, especifique um endereço IP de cliente para testar a lógica baseada em IP.

1. Selecione **Detalhes** para visualizar os resultados da execução da função.

1. Analise os logs de execução para verificar a lógica de função.

Teste com certificados válidos e revogados para garantir que a função gerencie os dois cenários corretamente. Os logs de execução mostram a saída console.log e quaisquer erros que ocorram durante a execução da função.

# Etapa 4: associar a função à distribuição
<a name="associate-function-distribution"></a>

Depois de publicar a função de conexão, associe-a à sua distribuição habilitada para mTLS para ativar a verificação de revogação de certificados.

É possível associar a função na página de configurações de distribuição ou na tabela de distribuições associadas à função de conexão. Navegue até suas configurações de distribuição, acesse a seção **Autenticação mútua (mTLS) de visualizador**, selecione a função de conexão e salve as alterações.

# Cenários avançados de revogação
<a name="advanced-revocation-scenarios"></a>

Com relação a requisitos de revogação de certificados mais complexos, considere estas configurações adicionais:

**Topics**
+ [Converter listas de revogação de certificados (CRLs) no formato do KeyValueStore](#convert-crl-kvs-format)
+ [Lidar com várias autoridades de certificação](#handle-multiple-cas)
+ [Adicionar dados personalizados aos logs de conexão](#add-custom-data-logs)
+ [Gerenciar atualizações de CRL](#manage-crl-updates)
+ [Planejar a capacidade do KeyValueStore](#plan-kvs-capacity)

## Converter listas de revogação de certificados (CRLs) no formato do KeyValueStore
<a name="convert-crl-kvs-format"></a>

Se você tiver um arquivo de lista de revogação de certificados (CRL), poderá convertê-lo no formato JSON do KeyValueStore usando OpenSSL e jq:

**Converter CRLs no formato do KeyValueStore**

Extraia os números de série do arquivo de CRL:

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

Converta os números de série no formato JSON do KeyValueStore:

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

Faça upload do arquivo formatado no S3 e crie o KeyValueStore conforme descrito na Etapa 1.

## Lidar com várias autoridades de certificação
<a name="handle-multiple-cas"></a>

Quando sua TrustStore contém várias autoridades de certificação (CAs), inclua as informações do emissor nas chaves do KeyValueStore para evitar conflitos entre certificados de CAs diferentes que possam ter o mesmo número de série.

Em cenários com várias CAs, use uma combinação do hash SHA1 do emissor e o número de série como chave:

```
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();
    }
}
```

**nota**  
O uso do identificador do emissor e do número de série cria chaves mais longas, o que pode reduzir o número total de entradas que é possível armazenar no KeyValueStore.

## Adicionar dados personalizados aos logs de conexão
<a name="add-custom-data-logs"></a>

As funções de conexão podem adicionar dados personalizados aos logs de conexão do CloudFront usando o método logCustomData. Isso permite incluir resultados da verificação de revogação, informações do certificado ou outros dados relevantes nos logs.

```
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();
}
```

Os dados personalizados são limitados a 800 bytes de texto UTF-8 válido. Se você exceder esse limite, o CloudFront truncará os dados até o limite UTF-8 válido mais próximo.

**nota**  
O registro em log de dados personalizados só funciona quando os logs de conexão estão habilitados para a distribuição. Se os logs de conexão não estiverem configurados, o método logCustomData não fará nada.

## Gerenciar atualizações de CRL
<a name="manage-crl-updates"></a>

As autoridades de certificação podem emitir dois tipos de CRL:
+ **CRLs completas**: contêm uma lista completa de todos os certificados revogados.
+ **CRLs delta**: listam somente certificados revogados desde a última CRL completa.

Para atualizações de CRLs completas, crie um KeyValueStore com os dados atualizados e redirecione a associação da função de conexão para o novo KeyValueStore. Essa abordagem é mais simples do que calcular diferenças e realizar atualizações incrementais.

Para atualizações de CRLs delta, use o comando update-keys para adicionar novos certificados revogados ao KeyValueStore existente:

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

## Planejar a capacidade do KeyValueStore
<a name="plan-kvs-capacity"></a>

O KeyValueStore tem um limite de tamanho total de 5 MB e comporta até 10 milhões de pares de chave-valor. Planeje a capacidade da lista de revogação com base no formato da chave e no tamanho dos dados:
+ **Somente número de série**: armazenamento eficiente para verificação simples de revogação.
+ **Identificador do emissor \$1 número de série**: chaves mais longas para ambientes com várias CAs.

Para listas de revogação extensas, considere a possibilidade de implementar uma abordagem em camadas em que você mantenha os KeyValueStores separados para diferentes categorias de certificado ou períodos.