mTLS (Mutual TLS) Setup
February 14, 2026 ยท View on GitHub
Optional mutual TLS for ASAP transport (SD-6). mTLS provides certificate-based authentication for both client and server in enterprise deployments. mTLS is optional and never required.
Overview
- Server: Presents its certificate to clients; optionally requires client certificates.
- Client: Presents its certificate to the server; verifies the server's certificate.
- Use cases: Enterprise networks, zero-trust architectures, regulated industries.
Certificate Generation
Self-Signed CA and Certificates (Development/Testing)
# Create CA
openssl genrsa -out ca.key 4096
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.crt \
-subj "/CN=ASAP-Test-CA"
# Server certificate
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr -subj "/CN=localhost"
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out server.crt -days 365 -sha256
# Client certificate
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr -subj "/CN=asap-client"
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out client.crt -days 365 -sha256
Production
Use your organization's PKI or a public CA. Ensure:
- Server cert has correct SAN (Subject Alternative Name) for your hostname.
- Client certs are issued by a CA the server trusts.
- Keys are stored with restrictive permissions (e.g.
chmod 600).
Server Configuration
1. Create mTLS Config
from asap.transport.mtls import MTLSConfig
from asap.transport.server import create_app
from asap.models.entities import Manifest, Capability, Endpoint, Skill
mtls_config = MTLSConfig(
cert_file="server.crt",
key_file="server.key",
ca_certs="ca.crt", # CA to verify client certs; omit to skip client verification
)
manifest = Manifest(
id="urn:asap:agent:my-agent",
name="My Agent",
version="1.0.0",
description="mTLS-protected agent",
capabilities=Capability(
asap_version="0.1",
skills=[Skill(id="echo", description="Echo")],
state_persistence=False,
),
endpoints=Endpoint(asap="https://localhost:8443/asap"),
)
app = create_app(manifest, mtls_config=mtls_config)
2. Run Uvicorn with SSL
import uvicorn
from asap.transport.mtls import mtls_config_to_uvicorn_kwargs
# Get uvicorn SSL kwargs from mtls_config
ssl_kwargs = mtls_config_to_uvicorn_kwargs(mtls_config)
uvicorn.run(
app,
host="0.0.0.0",
port=8443,
**ssl_kwargs,
)
Or via CLI:
uvicorn asap.transport.server:app --host 0.0.0.0 --port 8443 \
--ssl-keyfile server.key \
--ssl-certfile server.crt \
--ssl-ca-certs ca.crt \
--ssl-cert-reqs 2
(--ssl-cert-reqs 2 = CERT_REQUIRED)
Client Configuration
from asap.transport.client import ASAPClient
from asap.transport.mtls import MTLSConfig
mtls_config = MTLSConfig(
cert_file="client.crt",
key_file="client.key",
ca_certs="ca.crt", # CA to verify server; omit for system default
)
async with ASAPClient(
"https://localhost:8443",
mtls_config=mtls_config,
) as client:
response = await client.send(envelope)
WebSocket with mTLS
Both HTTP and WebSocket transports support mTLS. When mtls_config is provided to ASAPClient, it applies to:
- HTTP requests (POST /asap)
- WebSocket connections (wss://)
- Manifest fetches
Backward Compatibility
- Servers without
mtls_configrun as before (plain HTTP or TLS without client certs). - Clients without
mtls_configconnect without presenting a client certificate. - mTLS is opt-in; existing deployments are unaffected.
Security Notes
- Store private keys with
chmod 600; never commit them. - Use environment variables or secrets managers for paths in production.
- Rotate certificates before expiry; monitor expiration dates.
- For
ca_certs, use a CA that only signs known clients/servers.