How to configure and associate an mTLS certificate to a domain

Mutual Transport Layer Security (mTLS) is a security protocol that enables two-way authentication and encryption for network interaction. It confirms that both the client and the server are authenticated and have the clearance for effective communication.

To configure mTLS in your applications, you need a digital certificate with mTLS support signed by a third-party certificate authority (CA). At Azion, this type of certificate is called a Trusted CA.


Adding a Trusted CA certificate and associating it to a domain

Section titled Adding a Trusted CA certificate and associating it to a domain
  1. Access Azion Console > Digital Certificates.
  2. Click the Add certificate button.
  3. Select the Trusted CA Certificate option from the dropdown.
  4. Give your certificate an easy-to-remember name.
  5. In the Certificate field, paste your Trusted CA, including the begin and end tags.
  1. Click the Save button.

After adding a Trusted CA to your certificate library, you need to configure which domains should operate with mTLS.

  1. Access Azion Console > Domains.
  2. Click on the domain you’d like to configure mTLS for.
  3. Enable the Enable Mutual Authentication (mTLS) switch.
  4. Choose which verification mode you wish to use.
  • By selecting Enforce (default), mTLS is enabled in your edge application’s domain and all incoming traffic will comply with client and server authentication.
  • By selecting Permissive, you must configure this mode in Edge Firewall.
  1. Select the Trusted CA Certificate you created.
  2. Click the Save button.
  1. Run the following POST request in your terminal, replacing [TOKEN VALUE] with your personal token and the certificate in the certificate property:
Terminal window
curl --location 'https://api.azionapi.net/digital_certificates' \
--header 'Accept: application/json; version=3' \
--header 'Authorization: Token [TOKEN VALUE]' \
--header 'Content-Type: application/json' \
--data '{
"name": "Trusted CA - mydomain.com",
"certificate": "-----BEGIN CERTIFICATE-----\nMIIDCTCCAfGgAwIBAgIJAPpKHOLMIGuAMA0GCSqGSIb3DQEBBQUAMBsxGTAXBgNV\nBAMMEHd3dy5teWRvbWFpbi5jb20wHhcNMTgwMzI3MjAwOTA0WhcNMjgwMzI0MjAw\nOTA0WjAbMRkwFwYDVQQDDBB3d3cubXlkb21haW4uY29tMIIBIjANBgkqhkiG9w0B\nAQEFAAOCAQ8AMIIBCgKCAQEAt25cziDBsHbZzZhy9BPLApPf9OmE67k9pr7VezsR\nkIw4trY2xtJXFB7itT1p7HxbLBoL5u8FGmMKssB+XTmztmgty43ogor1KSjUgfZg\nrpAqyXtrbSM5g+14c0VO9S0LkkePlHvul0UiblJj7K+gkvc6sZqXZY+TI1BPqeuO\ns9A4LLCUGziyNv0qJfIL5RZm07Yy35BEBTTxUWVL2msfaUH2uPM5XN5eFC7oKN0/\n3NuYIboRmyk+P7CDC99M8Mp/wOjiB+yVGZVTjeqGPI8nFWJl2wtyuiZ4VvW84xQP\njwtid1v1KENK/ixMAAXi2cQ9gNRX+/USoneuWj5n4QUj6QIDAQABo1AwTjAdBgNV\nHQ4EFgQU2sDgtyYMDXvw79OhdvAFqcLmcwkwHwYDVR0jBBgwFoAU2sDgtyYMDXvw\n79OhdvAFqcLmcwkwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAKzCM\niG67IPwJK6MIJ31N734AofjkOf+fffxNtfYmH0XGORHPYUxCxsLxXiSFgPvubWh+\n7vLsKAm67bflMWbn982aiOR0O/LJhLvhj6F+wgv0aDYup181Hm8Ob/88ldbF6ND1\nTqzVATS0WDfl+z1QBKtNdDm3Nv45IZ83ob7OhIzD9MwL6tflBPDpWOYtmBDn0xSP\n6ra9d8oa6jK1fe2/5A7LY41acjbbNrLbFDYP7hcx02TmCfSMut+ysaZ/blay4Sbb\nwNlt92KhJw07UEKgXXbgyXGoFQkU8V+r2AZcgt0XM9jvwTc01Sbq/gegd2GMAj3x\nrTwkn5UNzFs56FCgNg==\n-----END CERTIFICATE-----",
"certificate_type": "trusted_ca_certificate"
}'
KeyDescription
nameName of the certificate instance
certificateString that holds the certificate value. Must include the begin and end tags. Line feeds must be replaced by escape sequences (\n)
certificate_typeEnum that indicates the type of the certificate. Trusted CA certificates are assigned the value trusted_ca_certificate
  1. You’ll receive a response similar to this:
{
"results": {
"id": <digital_certificate_id>,
"name": "Trusted CA - mydomain.com",
"issuer": "CA name",
"subject_name": [],
"validity": "2028-03-24 20:09:00-03:00",
"status": "Active",
"certificate_type": "trusted_ca_certificate",
"managed": false
}
}
  1. Copy the digital_certificate_id value. You’ll need it while associating it with a domain.
  2. Run the following POST request in your terminal, replacing [TOKEN VALUE] with your personal token, the <edge_application_id> with an edge application ID, and the <digital_certificate_id> with the ID of the Trusted CA you created:
Terminal window
curl --location 'https://api.azionapi.net/domains' \
--header 'Accept: application/json; version=3' \
--header 'Authorization: Token [TOKEN VALUE]' \
--header 'Content-Type: application/json' \
--data '{
"name": "mydomain.com",
"cnames": [
"mydomain.com"
],
"digital_certificate_id": null,
"edge_application_id": <edge_application_id>,
"is_mtls_enabled": true,
"mtls_verification": "enforce",
"mtls_trusted_ca_certificate_id": <digital_certificate_id>
}'
KeyDescription
nameName of the domain instance
cnamesAccepts an array of strings containing the CNAMEs for the domain as values
digital_certificate_idEnum that, when null, selects the Azion SAN certificate
edge_application_idThe ID of the application linked to the domain
is_mtls_enabledBoolean that, when true, activates mTLS verification for the domain
mtls_verificationEnum that sets the verification mode. Can be enforce or permissive
mtls_trusted_ca_certificate_idThe ID of the Trusted CA
  1. You’ll receive a response similar to this:
{
"id": <domain_id>,
"name": "mydomain.com",
"cnames": [
"mydomain.com"
],
"cname_access_only": true,
"digital_certificate_id": null,
"edge_application_id": <edge_application_id>,
"is_active": true,
"domain_name": "abcde12345.map.azionedge.net",
"environment": "production",
"is_mtls_enabled": true,
"mtls_verification": "enforce",
"mtls_trusted_ca_certificate_id": <digital_certificate_id>,
"edge_firewall_id": null
}
  1. Wait for the propagation time. Your domain should now be using the mTLS protocol.

Creating specific rules for Permissive mTLS

Section titled Creating specific rules for Permissive mTLS

To configure a firewall to block access to a domain using the Permissive mode in mTLS, you must use the Rules Engine for Edge Firewall. The following example describes a rule set that will block any incoming network traffic with the hostname mydomain.com whose client certificate validation isn’t true and deliver a 403 Forbidden error.

  1. Access Azion Console > Edge Firewall.
  2. Configure an edge firewall for the mTLS domain.
  3. Click the Rules Engine tab of the Edge Firewall.
  4. Click the New Rule button.
  5. Give your rule an easy-to-remember name.
  6. In the Criteria section, as a variable, select Hostname.
  7. As a comparison operator, select is equal.
  8. As an argument, enter mydomain.com.
  9. Click the + And button to add a new criteria.
  10. As a variable, select Client Certificate Validation.
  11. As a comparison operator, select is not equal to.
  12. As an argument, enter true.
  13. In the Behavior section, select Deny (403 Forbidden).
  14. Click the Save button.
  1. Run the following POST request in your terminal, replacing [TOKEN VALUE] with your personal token and the <edge_firewall_id> with the ID of the firewall associated with the mTLS domain:
Terminal window
curl --location 'https://api.azionapi.net/edge_firewall/<edge_firewall_id>/rules_engine' \
--header 'Accept: application/json; version=3' \
--header 'Authorization: Token [TOKEN VALUE]' \
--header 'Content-Type: application/json' \
--data '{
"name": "403 Host=mydomain.com and CCV!=true",
"description": "Delivers a 403 if the hostname does not match mydomain.com and if the certificate validation fails.",
"behaviors": [
{
"name": "deny"
}
],
"criteria": [
[
{
"variable": "host",
"operator": "is_equal",
"conditional": "if",
"argument": "mydomain.com"
},
{
"variable": "client_certificate_validation",
"operator": "is_not_equal",
"conditional": "and",
"argument": "true"
}
]
]
}'
KeyDescription
nameName of the rule
descriptionDescription of the rule
behaviorsArray that stores objects that define behaviors
criteriaArray that stores objects that define criteria
  1. You’ll receive a response similar to this:
{
"results": {
"name": "403 Host=mydomain.com and CCV!=true",
"description": "Delivers a 403 if the hostname does not match mydomain.com and if the certificate validation fails.",
"behaviors": [
{
"name": "deny"
}
],
"criteria": [
[
{
"variable": "host",
"operator": "is_equal",
"conditional": "if",
"argument": "mydomain.com"
},
{
"variable": "client_certificate_validation",
"operator": "is_not_equal",
"conditional": "and",
"argument": "true"
}
]
],
"id": <rule_set_id>,
"order": 0
}
}

Specifying mTLS variables in HTTP headers

Section titled Specifying mTLS variables in HTTP headers

If your application is part of the Open Banking model, you must specify the variables ${ssl_client_escaped_cert} and ${ssl_client_s_dn_parsed} in the HTTP headers of your application. You can use the Rules Engine for Edge Application to create this behavior for your whole application.

Requires:

To test whether the headers you add are being sent in requests, you can run the following cURL command in your terminal from a directory containing the .pem files of your Trusted CA and its private key:

Terminal window
curl -skv https://mydomain.com/ -H "Pragma: azion-debug-cache" -o /dev/stdout --cert cert.pem --key key.pem
  1. Access Azion Console > Edge Application.
  2. Find and click on the application with the mTLS domain.
  3. Click the Rules Engine tab.
  4. Click the New Rule button and select Request Phase.
  5. Give your rule an easy-to-remember name.
  6. In the Criteria field, enter the desired mTLS variable. Example: ${ssl_client_escaped_cert}.
  7. Select the comparison operator exists.
  8. In the Behaviors section, select the Add Response Header behavior.
  9. As an argument, enter Mtls-Variable-Name: ${ssl_variable_name}, replacing the name and variable with the mTLS variable you wish to insert in your application’s header.
    • Example: Escaped-Client-Cert: ${ssl_client_escaped_cert}
  1. To add another variable, click the And button in the Criteria section and repeat the remaining steps.
  2. Click the Save button when you’re done.
  1. Run the following POST request in your terminal, replacing [TOKEN VALUE] with your personal token and the <edge_application_id> with the ID of the application associated with the mTLS domain:
Terminal window
curl --location 'https://api.azionapi.net/edge_applications/<edge_application_id>/rules_engine/request/rules' \
--header 'Accept: application/json; version=3' \
--header 'Content-Type: application/json' \
--header 'Authorization: Token [TOKEN VALUE]' \
--data '{
"name": "mTLS variables",
"description": "Adds certificate values according to Open Banking standards",
"phase": "request",
"behaviors": [
{
"name": "add_request_header",
"target": "Escaped-Client-Cert: ${ssl_client_escaped_cert}"
}
],
"criteria": [
[
{
"variable": "${ssl_client_escaped_cert}",
"operator": "exists",
"conditional": "if",
"input_value": ""
}
]
]
}'
  1. You’ll receive a response similar to this:
{
"results": {
"id": <rule_id>,
"name": "mTLS variables",
"phase": "request",
"behaviors": [
{
"name": "add_request_header",
"target": "Escaped-Client-Cert: ${ssl_client_escaped_cert}"
}
],
"criteria": [
[
{
"variable": "${ssl_client_escaped_cert}",
"operator": "exists",
"conditional": "if",
"input_value": ""
}
]
],
"description": "Adds certificate values according to Open Banking standards"
}
}
  1. Repeat the previous step for each mTLS variable required in the headers.



Contributors