

# Mutual TLS authentication with CloudFront (Viewer mTLS)
<a name="mtls-authentication"></a>

Mutual TLS Authentication (Mutual Transport Layer Security Authentication — mTLS) is a security protocol that extends standard TLS authentication by requiring bidirectional certificate-based authentication, where both client and server must prove their identity before establishing a secure connection. Using mutual TLS, you can ensure that only clients presenting trusted TLS certificates gain access to your CloudFront distributions.

## How it works
<a name="how-mtls-works"></a>

In a standard TLS handshake, only the server presents a certificate to prove its identity to the client. With mutual TLS, the authentication process becomes bidirectional. When a client attempts to connect to your CloudFront distribution, CloudFront requests a client certificate during the TLS handshake. The client must present a valid X.509 certificate that CloudFront validates against your configured trust store before establishing the secure connection.

CloudFront performs this certificate validation at AWS edge locations, offloading the authentication complexity from your origin servers while maintaining CloudFront's global performance benefits. You can configure mTLS in two modes: verify mode (which requires all clients to present valid certificates) or optional mode (which validates certificates when presented but also allows connections without certificates).

## Use cases
<a name="mtls-use-cases"></a>

Mutual TLS authentication with CloudFront addresses several critical security scenarios where traditional authentication methods are insufficient:
+ **Device authentication with content caching** - You can authenticate gaming consoles, IoT devices, or corporate hardware before allowing access to firmware updates, game downloads, or internal resources. Each device contains a unique certificate that proves its authenticity while benefiting from CloudFront's caching capabilities.
+ **API-to-API authentication** - You can secure machine-to-machine communication between trusted business partners, payment systems, or micro-services. Certificate-based authentication eliminates the need for shared secrets or API keys while providing strong identity verification for automated data exchanges.

**Topics**
+ [How it works](#how-mtls-works)
+ [Use cases](#mtls-use-cases)
+ [Trust stores and certificate management](trust-stores-certificate-management.md)
+ [Enable mutual TLS for CloudFront distributions](enable-mtls-distributions.md)
+ [Associate a CloudFront Connection Function](connection-functions.md)
+ [Configuring additional settings](configuring-additional-settings.md)
+ [Viewer mTLS headers for cache policies and forwarded to origin](viewer-mtls-headers.md)
+ [Revocation using CloudFront Connection Function and KVS](revocation-connection-function-kvs.md)
+ [Observability using connection logs](connection-logs.md)

# Trust stores and certificate management
<a name="trust-stores-certificate-management"></a>

Creating and configuring a trust store is a mandatory requirement for implementing mutual TLS authentication with CloudFront. Trust stores contain the Certificate Authority (CA) certificates that CloudFront uses to validate client certificates during the authentication process.

## What is a trust store?
<a name="what-is-trust-store"></a>

A trust store is a repository of CA certificates that CloudFront uses to validate client certificates during mutual TLS authentication. Trust stores contain the root and intermediate CA certificates that form the chain of trust for authenticating client certificates.

When you implement mutual TLS with CloudFront, the trust store defines which Certificate Authorities you trust to issue valid client certificates. CloudFront validates each client certificate against your trust store during the TLS handshake. Only clients presenting certificates that chain to one of the CAs in your trust store will be authenticated successfully.

Trust stores in CloudFront are account-level resources that you can associate with multiple distributions. This allows you to maintain consistent certificate validation policies across your entire CloudFront deployment while simplifying CA certificate management.

## Certificate Authority support
<a name="ca-support"></a>

CloudFront supports certificates issued by both AWS Private Certificate Authority and third-party private Certificate Authorities. This flexibility allows you to use your existing certificate infrastructure or leverage AWS managed certificate services based on your organizational requirements.
+ **AWS Private Certificate Authority:** You can use certificates issued by AWS Private CA, which provides a managed private certificate authority service. This integration simplifies certificate lifecycle management and provides seamless integration with other AWS services.
+ **Third-party private Certificate Authorities:** You can also use certificates from your existing private Certificate Authority infrastructure, including enterprise CAs or other third-party certificate providers. This allows you to maintain your current certificate management processes while adding CloudFront's mTLS capabilities.

## Certificate requirements and specifications
<a name="certificate-requirements"></a>

Trust stores have specific requirements for the CA certificates they contain:

### CA certificate format requirements
<a name="ca-cert-format-requirements"></a>
+ **Format:** PEM (Privacy Enhanced Mail) format
+ **Content boundaries:** Certificates must be enclosed within the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- boundaries
+ **Comments:** Must be preceded by a \$1 character and cannot contain any - characters
+ **Line breaks:** No blank lines are allowed between certificates

### Supported certificate specifications
<a name="supported-cert-specs"></a>
+ **Certificate type:** X.509v3
+ **Public key types:**
  + RSA 2048, RSA 3072, RSA 4096
  + ECDSA: secp256r1, secp384r1
+ **Signature algorithms:**
  + SHA256, SHA384, SHA512 with RSA
  + SHA256, SHA384, SHA512 with EC
  + SHA256, SHA384, SHA512 with RSASSA-PSS with MGF1

### Example certificate bundle format
<a name="example-cert-bundle"></a>

Multiple certificates (PEM-encoded):

```
# Root CA Certificate
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKoK/OvD/XqiMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTcwNzEyMTU0NzQ4WhcNMjcwNzEwMTU0NzQ4WjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAuuExKvY1xzHFylsHiuowqpmzs7rEcuuylOuEszpFp+BtXh0ZuEtts9LP
-----END CERTIFICATE-----
# Intermediate CA Certificate
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKoK/OvD/XqjMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTcwNzEyMTU0NzQ4WhcNMjcwNzEwMTU0NzQ4WjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
CgKCAQEAuuExKvY1xzHFylsHiuowqpmzs7rEcuuylOuEszpFp+BtXh0ZuEtts9LP
-----END CERTIFICATE-----
```

## Create a trust store
<a name="create-trust-store"></a>

Before creating a trust store, you must upload your CA certificate bundle in PEM format to an Amazon S3 bucket. The certificate bundle should contain all the trusted root and intermediate CA certificates needed to validate your client certificates.

The CA certificate bundle is only read once from S3 when creating a trust store. If future changes are made to the CA certificate bundle, then the trust store will have to be manually updated. No sync is maintained between the trust store and the S3 CA certificate bundle.

### Prerequisites
<a name="trust-store-prerequisites"></a>
+ A certificate bundle from your Certificate Authority (CA) uploaded to an Amazon S3 bucket
+ The necessary permissions to create CloudFront resources

### To create a trust store (Console)
<a name="create-trust-store-console"></a>

1. Sign in to the AWS Management Console and open the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home).

1. In the navigation pane, choose **Trust stores**.

1. Choose **Create trust store**.

1. For **Trust store name**, enter a name for your trust store.

1. For **Certificate authority (CA) bundle**, enter the Amazon S3 path to your PEM-format CA certificate bundle.

1. Choose **Create trust store**.

### To create a trust store (AWS CLI)
<a name="create-trust-store-cli"></a>

```
aws cloudfront create-trust-store \
  --name MyTrustStore \
  --ca-certificates-bundle-source '{"CaCertificatesBundleS3Location":{"Bucket":"my-bucket","Key":"ca-bundle.pem","Region":"bucket-region"}}' \
  --tags Items=[{Key=Environment,Value=Production}]
```

## Associate trust store with distributions
<a name="associate-trust-store"></a>

After creating a trust store, you must associate it with a CloudFront distribution to enable mutual TLS authentication.

### Prerequisites
<a name="associate-prerequisites"></a>
+ An existing CloudFront distribution with HTTPS-only viewer protocol policy enabled and HTTP3 support disabled.

### To associate a trust store (Console)
<a name="associate-trust-store-console"></a>

There are two avenues to associate a trust store within the CloudFront console: through the trust store details page or through the distribution settings page.

**Associating a trust store through the trust store details page:**

1. Sign in to the AWS Management Console and open the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home).

1. In the navigation pane, choose **Trust stores**.

1. Choose the name of the trust store you want to associate.

1. Choose **Associate to distribution**.

1. Configure the available Viewer mTLS options:
   + **Client certificate validation mode:** Choose between Required and Optional mode. In required mode, all clients are required to present certificates. In optional mode, clients that present certificates are validated, while clients that do not present certificates are permitted access.
   + **Advertise trust store CA names:** Choose whether to advertise the CA names in your trust store to clients during TLS handshake.
   + **Ignore certificate expiration date:** Choose whether to allow connections with expired certificates (other validation criteria still apply).
   + **Connection Function:** An optional Connection Function can be associated to allow/deny connections based on other custom criteria.

1. Select one or more distributions to associate with the trust store. Only distributions with HTTP3 disabled and with HTTPS-only cache behaviors can support Viewer mTLS.

1. Choose **Associate**.

**Associating a trust store through the distribution settings page:**

1. Sign in to the AWS Management Console and open the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home).

1. Select the distribution that you want to associate

1. Under the **General** tab, within the **Settings** container, choose **Edit** in the top right corner

1. Scroll down to the bottom of the page, within the **Connectivity** container, toggle the **Viewer mTLS** switch on

1. Configure the available Viewer mTLS options:
   + **Client certificate validation mode:** Choose between Required and Optional mode. In required mode, all clients are required to present certificates. In optional mode, clients that present certificates are validated, while clients that do not present certificates are permitted access.
   + **Advertise trust store CA names:** Choose whether to advertise the CA names in your trust store to clients during TLS handshake.
   + **Ignore certificate expiration date:** Choose whether to allow connections with expired certificates (other validation criteria still apply).
   + **Connection Function:** An optional Connection Function can be associated to allow/deny connections based on other custom criteria.

1. Choose **Save changes** in the bottom right corner.

### To associate a trust store (AWS CLI)
<a name="associate-trust-store-cli"></a>

Trust stores can be associated to distributions via the DistributionConfig.ViewerMtlsConfig property. This means we first need to fetch the distribution config and then provide the ViewerMtlsConfig in a subsequent UpdateDistribution request.

```
// First fetch the distribution
aws cloudfront get-distribution {DISTRIBUTION_ID}

// Update the distribution config, for example:
Distribution config, file://distConf.json: 
{
  ...other fields,
  ViewerMtlsConfig: {
    Mode: 'required',
    TrustStoreConfig: {
        AdvertiseTrustStoreCaNames: false,
        IgnoreCertificateExpiry: true,
        TrustStoreId: {TRUST_STORE_ID}
    }
  }
}

aws cloudfront update-distribution \
   --id {DISTRIBUTION_ID} \
   --if-match {ETAG} \
   --distribution-config file://distConf.json
```

## Manage trust stores
<a name="manage-trust-stores"></a>

### View trust store details
<a name="view-trust-store-details"></a>

1. Sign in to the AWS Management Console and open the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home).

1. In the navigation pane, choose **Trust stores**.

1. Choose the name of the trust store to view its details page.

The details page shows:
+ Trust store name and ID
+ Number of CA certificates
+ Creation date and last modified date
+ Associated distributions
+ Tags

### Modify a trust store
<a name="modify-trust-store"></a>

To replace the CA certificate bundle:

1. Sign in to the AWS Management Console and open the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home).

1. In the navigation pane, choose **Trust stores**.

1. Choose the name of the trust store.

1. Choose **Actions**, then **Edit**.

1. For **Certificate authority (CA) bundle**, enter the Amazon S3 location of the updated CA bundle PEM file.

1. Choose **Update trust store**.

### Delete a trust store
<a name="delete-trust-store"></a>

**Prerequisites:** You must first disassociate the trust store from all CloudFront distributions.

1. Sign in to the AWS Management Console and open the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home).

1. In the navigation pane, choose **Trust stores**.

1. Choose the name of the trust store.

1. Choose **Delete trust store**.

1. Choose **Delete** to confirm.

### Next steps
<a name="trust-store-next-steps"></a>

After creating and associating your trust store with a CloudFront distribution, you can proceed to enable mutual TLS authentication on your distribution and configure additional settings such as forwarding certificate headers to your origins. For detailed instructions on enabling mTLS on your distributions, see [Enable mutual TLS for CloudFront distributions](enable-mtls-distributions.md).

# Enable mutual TLS for CloudFront distributions
<a name="enable-mtls-distributions"></a>

## Prerequisites and requirements
<a name="mtls-prerequisites-requirements"></a>

CloudFront's mutual TLS verify mode requires all clients to present valid certificates during the TLS handshake and rejects connections without valid certificates. Before enabling mutual TLS on a CloudFront distribution, ensure you have:
+ Created a trust store with your Certificate Authority certificates
+ Associated the trust store with your CloudFront distribution
+ Ensured all distribution cache behaviors use an HTTPS-only viewer protocol policy
+ Ensured your distribution is using HTTP/2 (the default setting, Viewer mTLS is not supported on HTTP/3)

**Note**  
Mutual TLS authentication requires HTTPS connections between viewers and CloudFront. You cannot enable mTLS on a distribution with any cache behaviors that support HTTP connections.

## Enable mutual TLS (Console)
<a name="enable-mtls-console"></a>

### For new distributions
<a name="enable-mtls-new-distributions"></a>

Viewer mTLS cannot be configured in the process of creating a new distribution in the CloudFront console. First create the distribution by any means (console, CLI, API), then edit the distribution settings to enable Viewer mTLS per the existing distributions instructions below.

### For existing distributions
<a name="enable-mtls-existing-distributions"></a>

1. Sign in to the AWS Management Console and open the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home).

1. From the distribution list, select the distribution you want to modify.

1. Ensure the Viewer protocol policy is set to **Redirect HTTP to HTTPS** or **HTTPS Only** for all cache behaviors. (You can choose the **Cache behaviors** tab to view and update any cache behaviors with HTTP protocol policies.)

1. Choose the **General** tab.

1. In the **Settings** section, choose **Edit**.

1. In the **Connectivity** section, find **Viewer mutual authentication (mTLS)**.

1. Toggle **Enable mutual authentication** to On.

1. For **Client certificate validation mode**, select **Required** (all clients must present certificates) or **Optional** (clients can optionally present certificates).

1. For **Trust store**, select your previously created trust store.

1. (Optional) Toggle **Advertise trust store CA names** if you want CloudFront to send CA names to clients during the TLS handshake.

1. (Optional) Toggle **Ignore certificate expiration date** if you want to allow connections with expired certificates.

1. Choose **Save changes**.

## Enable mutual TLS (AWS CLI)
<a name="enable-mtls-cli"></a>

### For new distributions
<a name="enable-mtls-cli-new"></a>

The following example shows how to create a distribution configuration file (distribution-config.json) that includes mTLS settings:

```
{
  "CallerReference": "cli-example-1",
  "Origins": {
    "Quantity": 1,
    "Items": [
      {
        "Id": "my-origin",
        "DomainName": "example.com",
        "CustomOriginConfig": {
          "HTTPPort": 80,
          "HTTPSPort": 443,
          "OriginProtocolPolicy": "https-only"
        }
      }
    ]
  },
  "DefaultCacheBehavior": {
    "TargetOriginId": "my-origin",
    "ViewerProtocolPolicy": "https-only",
    "MinTTL": 0,
    "ForwardedValues": {
      "QueryString": false,
      "Cookies": {
        "Forward": "none"
      }
    }
  },
  "ViewerCertificate": {
    "CloudFrontDefaultCertificate": true
  },
  "ViewerMtlsConfig": {
    "Mode": "required", 
    "TrustStoreConfig": {
        "TrustStoreId": {TRUST_STORE_ID},
        "AdvertiseTrustStoreCaNames": true,
        "IgnoreCertificateExpiry": true
    }
  },
  "Enabled": true
}
```

Create the distribution with mTLS enabled using the following example command:

```
aws cloudfront create-distribution --distribution-config file://distribution-config.json
```

### For existing distributions
<a name="enable-mtls-cli-existing"></a>

Get the current distribution configuration using the following example command:

```
aws cloudfront get-distribution-config --id E1A2B3C4D5E6F7 --output json > dist-config.json
```

Edit the file to add mTLS settings. Add the following example section to your distribution configuration:

```
"ViewerMtlsConfig": {
    "Mode": "required", 
    "TrustStoreConfig": {
        "TrustStoreId": {TRUST_STORE_ID},
        "AdvertiseTrustStoreCaNames": true,
        "IgnoreCertificateExpiry": true
    }
}
```

Remove the ETag field from the file but save its value separately.

Update the distribution with the new configuration using the following example command:

```
aws cloudfront update-distribution \
    --id E1A2B3C4D5E6F7 \
    --if-match YOUR-ETAG-VALUE \
    --distribution-config file://dist-config.json
```

## Viewer protocol policies
<a name="viewer-protocol-policies"></a>

When using mutual TLS, all distribution cache behaviors must be configured with an HTTPS-only viewer protocol policy:
+ **Redirect HTTP to HTTPS** - Redirects HTTP requests to HTTPS before performing certificate validation.
+ **HTTPS Only** - Only accepts HTTPS requests and performs certificate validation.

**Note**  
The HTTP and HTTPS viewer protocol policy is not supported with mutual TLS since HTTP connections cannot perform certificate validation.

## Next steps
<a name="enable-mtls-next-steps"></a>

After enabling Viewer TLS on your CloudFront distribution, you can associate Connection Functions to implement custom certificate validation logic. Connection Functions allow you to extend the built-in mTLS authentication capabilities with custom validation rules, certificate revocation checking, and logging. For details on creating and associating Connection Functions, see [Associate a CloudFront Connection Function](connection-functions.md).

# Associate a CloudFront Connection Function
<a name="connection-functions"></a>

CloudFront Connection Functions allow you to implement custom certificate validation logic during TLS handshakes, providing extensions to the built-in mTLS authentication capabilities.

## What are Connection Functions?
<a name="what-are-connection-functions"></a>

Connection Functions are JavaScript functions that run during the TLS handshake after client certificates have been validated. The validated client certificate is passed to the Connection Function at which point the Connection Function can make an additional determination on whether to grant access or not. For detailed information about Connection Functions, see [Customize at the edge with CloudFront Functions](cloudfront-functions.md).

## How Connection Functions work with mTLS
<a name="how-connection-functions-work"></a>

When a client attempts to establish an mTLS connection to your CloudFront distribution, the following sequence occurs:

1. Client initiates TLS handshake with CloudFront edge location.

1. CloudFront requests and receives client certificate.

1. CloudFront performs standard certificate validation against trust store.

1. If the certificate passes standard validation, CloudFront invokes your Connection Function. If **IgnoreCertificateExpiry** is enabled within your **ViewerMtlsConfig**, then your expired—but otherwise valid—certificates are also passed to the Connection Function. If the client certificates are invalid, Connection Functions will not be invoked.

1. Your Connection Function receives parsed certificate information and connection details.

1. Your function makes an allow/deny decision based on custom logic.

1. CloudFront completes or terminates the TLS connection based on your decision.

Connection Functions are invoked for both verify mode and optional mode (when clients present certificates).

## Create a Connection Function
<a name="create-connection-function"></a>

You can create Connection Functions using the CloudFront console or AWS CLI.

### To create a Connection Function (Console)
<a name="create-connection-function-console"></a>

1. Sign in to the AWS Management Console and open the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home).

1. In the navigation pane, choose **Functions**.

1. Choose the **Connection Functions** tab and choose **Create Connection Function**.

1. Enter a function name that is unique within your AWS account.

1. Choose **Continue**.

1. In the function editor, write your JavaScript code for certificate validation. The function handler must call either allow or deny.

1. Optional: a KeyValue store can be associated to the Connection Function to implement revocation control.

1. Choose **Save changes**.

### To create a Connection Function (AWS CLI)
<a name="create-connection-function-cli"></a>

The following example shows how to create a Connection Function:

Write your function code in a separate file, for example code.js:

```
function connectionHandler(connection) {
  connection.allow();
}
```

```
aws cloudfront create-connection-function \
  --name "certificate-validator" \
  --connection-function-config '{
      "Comment": "Client certificate validation function",
      "Runtime": "cloudfront-js-2.0"
  }' \
  --connection-function-code fileb://code.js
```

## Connection Function code structure
<a name="connection-function-code-structure"></a>

Connection Functions implement connectionHandler function that receives a connection object containing certificate and connection information. Your function must use either `connection.allow()` or `connection.deny()` to make a decision about the connection.

### Basic Connection Function example
<a name="basic-connection-function-example"></a>

The following example shows a simple Connection Function that verifies the subject field of client certificates:

```
function connectionHandler(connection) {
    // Only process if a certificate was presented
    if (!connection.clientCertificate) {
        console.log("No certificate presented");
        connection.deny();
    }
    
    // Check the subject field for specific organization
    const subject = connection.clientCertificate.certificates.leaf.subject;
    if (!subject.includes("O=ExampleCorp")) {
        console.log("Certificate not from authorized organization");
       connection.deny();
    } else {
        // All checks passed
        console.log("Certificate validation passed");
        connection.allow();
    }
}
```

The full specification of client certificate properties available on the connection object are available here:

```
{
  "connectionId": "Fdb-Eb7L9gVn2cFakz7wWyBJIDAD4-oNO6g8r3vXDV132BtnIVtqDA==", // Unique identifier for this TLS connection
  "clientIp": "203.0.113.42", // IP address of the connecting client (IPv4 or IPv6)
  "clientCertificate": {
    "certificates": {
      "leaf": {
        "subject": "CN=client.example.com,O=Example Corp,C=US", // Distinguished Name (DN) of the certificate holder
        "issuer": "CN=Example Corp Intermediate CA,O=Example Corp,C=US", // Distinguished Name (DN) of the certificate authority that issued this certificate
        "serialNumber": "4a:3f:5c:92:d1:e8:7b:6c", // Unique serial number assigned by the issuing CA (hexadecimal)
        "validity": {
          "notBefore": "2024-01-15T00:00:00Z", // Certificate validity start date (ISO 8601 format)
          "notAfter": "2025-01-14T23:59:59Z"   // Certificate expiration date (ISO 8601 format)
        },
        "sha256Fingerprint": "a1b2c3d4e5f6...abc123def456", // SHA-256 hash of the certificate (64 hex characters)
      },
    },
  },
}
```

## Associate a Connection Function
<a name="associate-connection-function-section"></a>

After creating your Connection Function, you must publish it to the LIVE stage and associate it with your distribution.

### To publish and associate a Connection Function (Console)
<a name="publish-associate-console"></a>

1. Sign in to the AWS Management Console and open the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home).

1. In the navigation pane, choose **Functions**

1. Choose the **Connection Functions** tab and select your Connection Function.

1. Choose **Publish** to move it to the LIVE stage.

1. Choose **Add association** in the associated distributions table below the publishing section.

1. Select the distribution with Viewer mTLS enabled that you wish to associate.

Alternatively published Connection Functions can also be associated from the distribution details page.

1. Navigate to the console home page where all your distributions are listed.

1. Select the distribution that you wish to associate.

1. Choose the **General** tab.

1. In the **Settings** section, choose **Edit**.

1. In the **Connectivity** section, find **Viewer mutual authentication (mTLS)**.

1. For **Connection Function**, select your function.

1. Choose **Save changes**.

### To associate a Connection Function (AWS CLI)
<a name="associate-connection-function-cli"></a>

The following example shows how to associate a Connection Function with a distribution:

```
// DistributionConfig:
{
   ...other settings,
    "ConnectionFunctionAssociation": {
        "Id": "cf_30c2CV2elHwCoInb3LtcaUJkZeD"
    }
}
```

## Use cases for Connection Functions
<a name="connection-function-use-cases"></a>

Connection Functions enable several advanced mTLS use cases:
+ **Certificate attribute validation** - Verify specific fields in client certificates like organizational unit requirements or subject alternative name patterns.
+ **Certificate revocation checking** - Implement custom certificate revocation checking using KeyValueStore to store revoked certificate serial numbers.
+ **IP-based certificate policies** - Apply different certificate policies based on client IP addresses or geographic restrictions.
+ **Multi-tenant validation** - Implement tenant-specific validation rules where different certificate requirements apply based on hostnames or certificate attributes.

**Note**  
Connection Functions run once per client connection during the TLS handshake.  
Connection Functions can only allow or deny connections, not modify HTTP requests/responses.  
Only LIVE stage functions (published) can be associated with distributions.  
Each distribution can have at most one Connection Function.

## Next steps
<a name="connection-function-next-steps"></a>

After associating a Connection Function with your CloudFront distribution, you can configure optional settings to customize the behavior of your mTLS implementation. For detailed instructions on configuring additional settings such as an optional client certificate validation mode, see [Configuring additional settings](configuring-additional-settings.md).

# Configuring additional settings
<a name="configuring-additional-settings"></a>

After enabling basic mutual TLS authentication, you can configure additional settings to customize the authentication behavior for specific use cases and requirements.

## Client certificate validation Optional mode
<a name="optional-mode"></a>

CloudFront offers an alternative Optional client certificate validation mode that validates client certificates that are presented but allows access to clients that don't present certificates.

### Optional mode behavior
<a name="optional-mode-behavior"></a>
+ Grants connection to clients with valid certificates, (invalid certificates are denied).
+ Allows connection to clients without certificates
+ Allows mixed client authentication scenarios through a single distribution.

Optional mode is ideal for gradual migration to mTLS authentication, supporting clients with certificates and clients without certificates, or maintaining backward compatibility with legacy clients.

**Note**  
In optional mode, Connection Functions are still invoked even when clients don't present certificates. This allows you to implement custom logic such as logging client IP addresses or applying different policies based on whether certificates are presented.

### To configure optional mode (Console)
<a name="configure-optional-mode-console"></a>

1. In your distribution settings, navigate to the **General** tab, choose **Edit**.

1. Scroll to the **Viewer mutual authentication (mTLS)** section within the **Connectivity** container.

1. For **Client certificate validation mode**, select **Optional**.

1. Save changes.

### To configure optional mode (AWS CLI)
<a name="configure-optional-mode-cli"></a>

The following example shows how to configure optional mode:

```
"ViewerMtlsConfig": {
   "Mode": "optional",
   ...other settings
}
```

## Certificate Authority advertisement
<a name="ca-advertisement"></a>

The AdvertiseTrustStoreCaNames field controls whether CloudFront sends the list of trusted CA names to clients during the TLS handshake, helping clients select the appropriate certificate.

### To configure CA advertisement (Console)
<a name="configure-ca-advertisement-console"></a>

1. In your distribution settings, navigate to the **General** tab, choose **Edit**.

1. Scroll to the **Viewer mutual authentication (mTLS)** section within the **Connectivity** container.

1. Select or de-select the **Advertise trust store CA names** checkbox.

1. Choose **Save changes**.

### To configure CA advertisement (AWS CLI)
<a name="configure-ca-advertisement-cli"></a>

The following example shows how to enable CA advertisement:

```
"ViewerMtlsConfig": {
   "Mode": "required", // or "optional"
   "TrustStoreConfig": {
      "AdvertiseTrustStoreCaNames": true,
      ...other settings
   } 
}
```

## Certificate expiration handling
<a name="certificate-expiration-handling"></a>

The IgnoreCertificateExpiry property determines how CloudFront responds to expired client certificates. By default, CloudFront rejects expired client certificates, but you can configure it to accept them when necessary. This is typically enabled for devices with expired certificates that cannot be readily updated.

### To configure certificate expiration handling (Console)
<a name="configure-expiration-console"></a>

1. In your distribution settings, navigate to **General** tab, choose **Edit**.

1. Scroll to the **Viewer mutual authentication (mTLS)** section of the **Connectivity** container.

1. Select or deselect the **Ignore certificate expiration date** checkbox.

1. Choose **Save changes**.

### To configure certificate expiration handling (AWS CLI)
<a name="configure-expiration-cli"></a>

The following example shows how to ignore certificate expiration:

```
"ViewerMtlsConfig": {
  "Mode": "required", // or "optional"
  "TrustStoreConfig": {
     "IgnoreCertificateExpiry": false,
     ...other settings
  }
}
```

**Note**  
**IgnoreCertificateExpiry** only applies to the certificates Validity dates. All other certificate validation checks still apply (chain of trust, signature validation).

## Next steps
<a name="additional-settings-next-steps"></a>

After configuring additional settings, you can set up header forwarding to pass certificate information to your origins, implement certificate revocation using Connection Functions and KeyValueStore, and enable connection logs for monitoring. For details on forwarding certificate information to origins, see [Forward Headers to origins](viewer-mtls-headers.md).

# Viewer mTLS headers for cache policies and forwarded to origin
<a name="viewer-mtls-headers"></a>

When using mutual TLS authentication, CloudFront can extract information from client certificates and forward it to your origins as HTTP headers. This allows your origin servers to access certificate details without implementing certificate validation logic.

The following headers are available to for creating cache behaviors:


| Header name | Description | Example value | 
| --- | --- | --- | 
| CloudFront-Viewer-Cert-Serial-Number | Hexadecimal representation of the certificate serial number | 4a:3f:5c:92:d1:e8:7b:6c | 
| CloudFront-Viewer-Cert-Issuer | RFC2253 string representation of the issuer's distinguished name (DN) | CN=rootcamtls.com,OU=rootCA,O=mTLS,L=Seattle,ST=Washington,C=US | 
| CloudFront-Viewer-Cert-Subject | RFC2253 string representation of the subject's distinguished name (DN) | CN=client\$1.com,OU=client-3,O=mTLS,ST=Washington,C=US | 
| CloudFront-Viewer-Cert-Present | Either 1 (present) or 0 (not present) indicating whether the certificate is present. This value is always 1 in Required mode. | 1 | 
| CloudFront-Viewer-Cert-Sha256 | The SHA256 hash of the client certificate | 01fbf94fef5569753420c349f49adbfd80af5275377816e3ab1fb371b29cb586 | 

For origin requests, two additional headers are supplied, in addition to the headers above made available for cache behaviors. Due to potential header size, CloudFront-Viewer-Cert-Pem header is not exposed to edge functions (Lambda@Edge or CloudFront Functions) and is only forwarded to the origin.


| Header name | Description | Example value | 
| --- | --- | --- | 
| CloudFront-Viewer-Cert-Validity | ISO8601 format of the notBefore and notAfter date | CloudFront-Viewer-Cert-Validity: NotBefore=2023-09-21T01:50:17Z;NotAfter=2024-09-20T01:50:17Z | 
| CloudFront-Viewer-Cert-Pem | URL-encoded PEM format of the leaf certificate | CloudFront-Viewer-Cert-Pem: -----BEGIN%20CERTIFICATE-----%0AMIIG<...reduced...>NmrUlw%0A-----END%20CERTIFICATE-----%0A | 

## Configure header forwarding
<a name="configure-header-forwarding"></a>

### Console
<a name="configure-headers-console"></a>

In verify mode, CloudFront automatically adds the CloudFront-Viewer-Cert-\$1 headers to all viewer requests. To forward these headers to your origin:

1. From the main list distributions page, select your distribution with viewer mTLS enabled and go to the **Behaviors** tab

1. Select the cache behavior and choose **Edit**

1. In the **Origin request policy** section, choose **Create policy** or select an existing policy

1. Ensure the following headers are included in the origin request policy:
   + CloudFront-Viewer-Cert-Serial-Number
   + CloudFront-Viewer-Cert-Issuer
   + CloudFront-Viewer-Cert-Subject
   + CloudFront-Viewer-Cert-Present
   + Cloudfront-Viewer-Cert-Sha256
   + CloudFront-Viewer-Cert-Validity
   + CloudFront-Viewer-Cert-Pem

1. Choose **Create** (for new policies) or **Save changes** (for existing policies)

1. Select the policy within your cache behavior and save changes

### Using AWS CLI
<a name="configure-headers-cli"></a>

The following example shows how to create an origin request policy that includes mTLS headers for verify mode:

```
aws cloudfront create-origin-request-policy \
  --origin-request-policy-config '{
    "Name": "MTLSHeadersPolicy",
    "HeadersConfig": {
      "HeaderBehavior": "whitelist",
      "Headers": {
        "Quantity": 5,
        "Items": [
          "CloudFront-Viewer-Cert-Serial-Number",
          "CloudFront-Viewer-Cert-Issuer",
          "CloudFront-Viewer-Cert-Subject",
          "CloudFront-Viewer-Cert-Validity",
          "CloudFront-Viewer-Cert-Pem"
        ]
      }
    },
    "CookiesConfig": {
      "CookieBehavior": "none"
    },
    "QueryStringsConfig": {
      "QueryStringBehavior": "none"
    }
  }'
```

## Header processing considerations
<a name="header-processing-considerations"></a>

When working with certificate headers, consider these best practices:
+ **Header validation:** Verify certificate header values at your origin as an additional security measure
+ **Header size limits:** The PEM certificate headers can be large, ensure your origin server can handle them
+ **Cache considerations:** Using certificate headers in your cache key increases cache fragmentation
+ **Cross-origin requests:** If your application uses CORS, then you may need to configure it to allow the certificate headers

## Next steps
<a name="headers-next-steps"></a>

After configuring header forwarding, you can implement certificate revocation checking using CloudFront Connection Functions and KeyValueStore. For details on implementing revocation checks, see [Revocation using CloudFront Connection Function and KVS](revocation-connection-function-kvs.md).

# Revocation using CloudFront Connection Function and KVS
<a name="revocation-connection-function-kvs"></a>

You can implement certificate revocation checking for mutual TLS authentication by combining CloudFront Connection Functions with KeyValueStore. This approach provides a scalable, real-time certificate revocation mechanism that complements CloudFront's built-in certificate validation.

Connection Functions are JavaScript functions that run during TLS connection establishment at CloudFront edge locations and allow you to implement custom certificate validation logic for mTLS authentication. For detailed information about Connection Functions, see [Associate a CloudFront Connection Function](connection-functions.md).

## How certificate revocation works with Connection Functions
<a name="how-revocation-works"></a>

CloudFront's standard certificate validation verifies the certificate chain, signature, and expiration but doesn't include built-in certificate revocation checking. By using Connection Functions, you can implement custom revocation checking during the TLS handshake.

The certificate revocation process works as follows:

1. Store revoked certificate serial numbers in a CloudFront KeyValueStore.

1. When a client presents a certificate, your Connection Function is invoked.

1. The function checks the certificate's serial number against the KeyValueStore.

1. If the serial number is found in the store, the certificate is revoked.

1. Your function denies the connection for revoked certificates.

This approach provides near-real-time revocation checking across CloudFront's global edge network.

## Set up KeyValueStore for revoked certificates
<a name="setup-kvs-revoked-certs"></a>

First, create a KeyValueStore to store the serial numbers of revoked certificates:

### To create a KeyValueStore (Console)
<a name="create-kvs-console"></a>

1. Sign in to the AWS Management Console and open the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home).

1. In the navigation pane, choose **Key value stores**.

1. Choose **Create key value store**.

1. Enter a name for your key value store (e.g., revoked-certificates).

1. (Optional) Add a description.

1. Choose **Create key value store**.

### To create a KeyValueStore (AWS CLI)
<a name="create-kvs-cli"></a>

The following example shows how to create a KeyValueStore:

```
aws cloudfront create-key-value-store \
  --name "revoked-certificates" \
  --comment "Store for revoked certificate serial numbers"
```

## Import revoked certificate serial numbers
<a name="import-revoked-serials"></a>

After creating a KeyValueStore, you need to import the serial numbers of revoked certificates:

### Prepare revocation data
<a name="prepare-revocation-data"></a>

Create a JSON file with your revoked certificate serial numbers:

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

### Import from S3
<a name="import-from-s3"></a>

1. Upload the JSON file to an S3 bucket

1. Import the file to your KeyValueStore:

   ```
   aws cloudfront create-key-value-store \
     --name "revoked-certificates" \
     --import-source '{
       "SourceType": "S3",
       "SourceARN": "arn:aws:s3:::amzn-s3-demo-bucket1/revoked-serials.json"
     }'
   ```

## Create a Connection Function for revocation checking
<a name="create-revocation-connection-function"></a>

Create a Connection Function that checks certificate serial numbers against your KeyValueStore:

### Connection Function code example
<a name="revocation-function-example"></a>

The following example shows a Connection Function that performs certificate revocation checking:

```
import cf from 'cloudfront';

async function connectionHandler(connection) {
    const kvsHandle = cf.kvs();
    
    // Get client certificate serial number
    const clientSerialNumber = connection.clientCertificate.certificates.leaf.serialNumber;
    
    // Check if the serial number exists in the KeyValueStore
    const isRevoked = await kvsHandle.exists(clientSerialNumber.replaceAll(':', ''));
    
    if (isRevoked) {
        console.log(`Certificate ${clientSerialNumber} is revoked. Denying connection.`);
        connection.logCustomData(`REVOKED:${clientSerialNumber}`);
        connection.deny();
    } else {
        console.log(`Certificate ${clientSerialNumber} is valid. Allowing connection.`);
        connection.allow();
    }
    
}
```

### To create the Connection Function (AWS CLI)
<a name="create-revocation-function-cli"></a>

The following example shows how to create a Connection Function with KeyValueStore association:

```
aws cloudfront create-connection-function \
  --name "revocation-checker" \
  --connection-function-config '{
      "Comment": "Certificate revocation checking function",
      "Runtime": "cloudfront-js-2.0",
      "KeyValueStoreAssociations": {
          "Quantity": 1,
          "Items": [
              {
                  "KeyValueStoreARN": "arn:aws:cloudfront::123456789012:key-value-store/revoked-certificates"
              }
          ]
      }
  }' \
  --connection-function-code fileb://revocation-checker.js
```

## Associate the function with your distribution
<a name="associate-revocation-function"></a>

After creating and publishing your Connection Function, associate it with your mTLS-enabled CloudFront distribution as described in the [Associate a CloudFront Connection Function](connection-functions.md) section.

# Observability using connection logs
<a name="connection-logs"></a>

CloudFront connection logs provide detailed visibility into mutual TLS authentication events, allowing you to monitor certificate validation, track connection attempts, and troubleshoot authentication issues.

## What are connection logs?
<a name="what-are-connection-logs"></a>

Connection logs capture detailed information about TLS handshakes and certificate validation for mutual TLS-enabled distributions. Unlike standard access logs that record HTTP request information, connection logs focus specifically on the TLS connection establishment phase, including:
+ Connection status (success/failure)
+ Client certificate details
+ TLS protocol and cipher information
+ Connection timing metrics
+ Custom data from Connection Functions

These logs provide comprehensive visibility into certificate-based authentication events, helping you monitor security, troubleshoot issues, and meet compliance requirements.

## Enable connection logs
<a name="enable-connection-logs"></a>

Connection logs are available only for distributions with mutual TLS authentication enabled. You can send connection logs to multiple destinations including CloudWatch Logs, Amazon Data Firehose, and Amazon S3.

### Prerequisites
<a name="connection-logs-prerequisites"></a>

Before enabling connection logs:
+ Configure mutual TLS for your CloudFront distribution
+ Enable connection logs for your CloudFront distribution
+ Ensure you have the required permissions for your chosen logging destination
+ For cross-account delivery, configure appropriate IAM policies

### To enable connection logs (Console)
<a name="enable-connection-logs-console"></a>

1. Sign in to the AWS Management Console and open the CloudFront console at [https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home).

1. From the distribution list, select your mTLS-enabled distribution.

1. Choose the **Logging** tab.

1. Choose **Add**.

1. Select the service to receive your logs:
   + **CloudWatch Logs**
   + **Firehose**
   + **Amazon S3**

1. For **Destination**, select the resource for your chosen service:
   + For CloudWatch Logs, enter the **Log group name**
   + For Firehose, select the **Firehose delivery stream**
   + For Amazon S3, enter the **Bucket name** (optionally with a prefix)

1. (Optional) Configure additional settings:
   + **Field selection:** Select specific log fields to include.
   + **Output format:** Choose from JSON, Plain, w3c, Raw, or Parquet (S3 only).
   + **Field delimiter:** Specify how to separate log fields.

1. Choose **Save changes**

### To enable connection logs (AWS CLI)
<a name="enable-connection-logs-cli"></a>

The following example shows how to enable connection logs using the CloudWatch API:

```
# Step 1: Create a delivery source
aws logs put-delivery-source \
  --name "cf-mtls-connection-logs" \
  --resource-arn "arn:aws:cloudfront::123456789012:distribution/E1A2B3C4D5E6F7" \
  --log-type CONNECTION_LOGS

# Step 2: Create a delivery destination
aws logs put-delivery-destination \
  --name "s3-destination" \
  --delivery-destination-configuration \
  "destinationResourceArn=arn:aws:s3:::amzn-s3-demo-bucket1"

# Step 3: Create the delivery
aws logs create-delivery \
  --delivery-source-name "cf-mtls-connection-logs" \
  --delivery-destination-arn "arn:aws:logs:us-east-1:123456789012:delivery-destination:s3-destination"
```

**Note**  
When using the CloudWatch API, you must specify the US East (N. Virginia) Region (us-east-1) even when delivering logs to other regions.

## Connection log fields
<a name="connection-log-fields"></a>

Connection logs include detailed information about each TLS connection attempt:


| Field | Description | Example | 
| --- | --- | --- | 
| eventTimestamp | ISO 8601 timestamp when the connection was established or failed | 1731620046814 | 
| connectionId | Unique identifier for the TLS connection | oLHiEKbQSn8lkvJfA3D4gFowK3\$1iZ0g4i5nMUjE1Akod8TuAzn5nzg== | 
| connectionStatus |  The status of the mTLS connection attempt.  | Success or Failed | 
| clientIp | IP address of the connecting client | 2001:0db8:85a3:0000:0000:8a2e:0370:7334 | 
| clientPort | Port used by the client | 12137 | 
| serverIp | IP address of the CloudFront edge server | 99.84.71.136 | 
| distributionId | CloudFront distribution ID | E2DX1SLDPK0123 | 
| distributionTenantId | CloudFront distribution tenant ID (when applicable) | dt\$12te1Ura9X3R2iCGNjW123 | 
| tlsProtocol | TLS protocol version used | TLSv1.3 | 
| tlsCipher | TLS cipher suite used for the connection | TLS\$1AES\$1128\$1GCM\$1SHA256 | 
| tlsHandshakeDuration | Duration of the TLS handshake in milliseconds | 153 | 
| tlsSni | Server Name Indication value from the TLS handshake | d111111abcdef8.cloudfront.net | 
| clientLeafCertSerialNumber | Serial number of the client's certificate | 00:b1:43:ed:93:d2:d8:f3:9d | 
| clientLeafCertSubject | Subject field of the client's certificate | C=US, ST=WA, L=Seattle, O=Amazon.com, OU=CloudFront, CN=client.test.mtls.net | 
| clientLeafCertIssuer | Issuer field of the client's certificate | C=US, ST=WA, L=Seattle, O=Amazon.com, OU=CloudFront, CN=test.mtls.net | 
| clientLeafCertValidity | Validity period of the client's certificate | NotBefore=2025-06-05T23:28:21Z;NotAfter=2125-05-12T23:28:21Z | 
| connectionLogCustomData | Custom data added via Connection Functions | REVOKED:00:b1:43:ed:93:d2:d8:f3:9d | 

## Connection error codes
<a name="connection-error-codes"></a>

```
Failed:ClientCertMaxChainDepthExceeded
Failed:ClientCertMaxSizeExceeded
Failed:ClientCertUntrusted
Failed:ClientCertNotYetValid
Failed:ClientCertExpired
Failed:ClientCertTypeUnsupported
Failed:ClientCertInvalid
Failed:ClientCertIntentInvalid
Failed:ClientCertRejected
Failed:ClientCertMissing
Failed:TcpError
Failed:TcpTimeout
Failed:ConnectionFunctionError
Failed:ConnectionFunctionDenied
Failed:Internal
Failed:UnmappedConnectionError
```

When connections fail, CloudFront records specific reason codes:


| Code | Description | 
| --- | --- | 
| ClientCertMaxChainDepthExceeded | Maximum certificate chain depth exceeded | 
| ClientCertMaxSizeExceeded | Maximum certificate size exceeded | 
| ClientCertUntrusted | Certificate is untrusted | 
| ClientCertNotYetValid | Certificate is not yet valid | 
| ClientCertExpired | Certificate is expired | 
| ClientCertTypeUnsupported | Certificate type is unsupported | 
| ClientCertInvalid | Certificate is invalid | 
| ClientCertIntentInvalid | Certificate intent is invalid | 
| ClientCertRejected | Certificate rejected by custom validation | 
| ClientCertMissing | Certificate is missing | 
| TcpError |  An error occurred while attempting to establish a connection  | 
| TcpTimeout |  The connection was not able to be established within the timeout period  | 
| ConnectionFunctionError |  An uncaught exception was thrown during Connection Function execution  | 
| Internal |  An internal service error occurred  | 
| UnmappedConnectionError |  An error occurred that does not fall into any of the other categories  | 