Mutual Transport Layer Security (mTLS) is an authentication method in which both the client and server verify each other’s SSL/TLS certificates. This two-way validation establishes a trusted relationship and ensures secure, authenticated communication.
Configurations
You can set up the mTLS authentication using either of the following methods:
For setting up mTLS authentication using the Traceable platform, you must have the following configurations:
Configuration | Description |
|---|---|
Client Certificate | A client certificate is a digital certificate that the client presents during the TLS handshake to prove its identity to the server. This server validates this certificate along with its own to establish a secure and authenticated communication channel. The certificate must be provided in PEM format. |
Client Key | A client key is the private key associated with the client's digital certificate. |
Client Key Passphrase | A client key passphrase is the password used to protect the private key associated with the client's digital certificate. |
Client Authority Certificate | A bundle of trusted CA certificates for validating the server's certificate. |
You can set up mTLS authentication directly from the CLI using a JSON file and environment variables. To do so, use the following syntax:
{
"host:port" : {
"client_cert": <Path to the Client Certificate>,
"client_key": <Path to the Client Key>,
"root_ca": <Path to the Client Authority Certificate>,
"passphrase": <(Optional) Path to the Client Key Passphrase>
}
"host:port" : {
"client_cert": <Path to the Client Certificate>,
"client_key": <Path to the Client Key>,
"root_ca": <Path to the Client Authority Certificate>,
},
"default" : {
"client_cert": "/certs/client_default.crt",
"client_key": "/certs/client_default.key",
"root_ca": "/certs/CA_default.pem"
}
}Note
The default section in the above JSON acts as a fallback mechanism when Traceable does not find any matching host.
For example, the JSON file would look like the following:
{
"mysite.local:8443" : {
"client_cert": "/home/work/traceable/ast/pov_tools/mtls/certs/cas.client.crt",
"client_key": "/home/work/traceable/ast/pov_tools/mtls/certs/cas.client.key",
"root_ca": "/home/work/traceable/ast/pov_tools/mtls/certs/CA.pem",
"passphrase": "" # This represents an empty passphrase
}
"anotherhost.com:443" : {
"client_cert": "/certs/client.crt",
"client_key": "/certs/client.key",
"root_ca": "/certs/CA.pem",
},
"default" : {
"client_cert": "/certs/client_default.crt",
"client_key": "/certs/client_default.key",
"root_ca": "/certs/CA_default.pem"
}
}After defining the JSON file, export one of the following environment variables in the shell, invoking the CLI:
Use one environment variable, for example:
export TARGET_TLS_CONFIG_FILE = /path/mtls_config.jsonYou can define the JSON file (
mtls_config.json) like the one above.Note
This method authenticates all hosts mentioned in the JSON file.
Use multiple environment variables, for example:
export ROOT_CA_FILE = /path/CA.pem export TARGET_CLIENT_CERT_FILE = /path/client.crt export TARGET_CLIENT_KEY_FILE = /path/client.key export TARGET_CLIENT_KEY_PASSPHRASE = "<passphrase>"
Example
The following are some samples that you can use to configure the JWT mechanism in the Advanced mode:
Sample 1
from traceable import config
import io
import tempfile
from traceable.ast.constants import (
DEFAULT_HOST,
CLIENT_CERT,
CLIENT_KEY,
KEY_PASSPHRASE,
ROOT_CA
)
def mtls_hook(scanctx: ScanContext, pluginctx: PluginContext, testcase: TestCase, **kwargs) -> list[Assertion]:
def string_to_absolute_filepath(content, file_extension='.txt'):
# Create a temporary file in a secure location
with tempfile.NamedTemporaryFile(mode='w', suffix=file_extension, delete=False) as temp_file:
# Write the string content to the temporary file
temp_file.write(content)
# Get the absolute path of the temporary file
absolute_filepath = os.path.abspath(temp_file.name)
# The temporary file will be automatically closed and deleted
# as it goes out of scope, but you can also explicitly delete it here:
return absolute_filepath
attributes = testcase.get_attributes()
url = attributes.get_one("mutated.http.request.url", default="")
http_client = testcase.get_http_client(url)
# Typecase http_client
attributes = testcase.get_attributes()
# Set the certificate and key contents as strings
client_cert = "client_cert"
client_key = "client_key"
root_ca = "root_ca"
mtls_dict = {CLIENT_CERT: string_to_absolute_filepath(client_cert),
CLIENT_KEY: string_to_absolute_filepath(client_key),
}
if len(root_ca) > 0:
mtls_dict[ROOT_CA] = string_to_absolute_filepath(root_ca)
config.TLS_CONFIG[DEFAULT_HOST][CLIENT_CERT] = mtls_dict[CLIENT_CERT]
config.TLS_CONFIG[DEFAULT_HOST][CLIENT_KEY] = mtls_dict[CLIENT_KEY]
if ROOT_CA in mtls_dict:
config.TLS_CONFIG[DEFAULT_HOST][ROOT_CA] = mtls_dict[ROOT_CA]
return []