Skip to content

Support TLS 1.3 mTLS for async cert/A2A auth (#41, #43) - #48

Draft
DanPeterson wants to merge 2 commits into
mainfrom
danpeterson-tls13-support
Draft

Support TLS 1.3 mTLS for async cert/A2A auth (#41, #43)#48
DanPeterson wants to merge 2 commits into
mainfrom
danpeterson-tls13-support

Conversation

@DanPeterson

Copy link
Copy Markdown
Contributor

Summary

Fixes #41 and #43 in one change.

SPP 9.0 enables TLS 1.3. On TLS 1.3, certificate/A2A auth requires the client to answer a post-handshake CertificateRequest (RFC 8446 §4.6.2), which Python's ssl.SSLContext only does when post_handshake_auth = True. The async (aiohttp) path never set it, so async cert/A2A auth failed on 9.0 with 60094 Authorization is denied. The sync (requests/urllib3) path already enables it by default and was unaffected.

Changes

  • Bugfix (async): AsyncSafeguardClient._create_ssl_context now sets post_handshake_auth = True. This is the one change required for async cert/A2A auth to work on 9.0.
  • Opt-in TLS version pinning: new min_tls_version / max_tls_version (ssl.TLSVersion | None, default None = negotiate) on SafeguardClient, AsyncSafeguardClient, A2AContext, AsyncA2AContext, and the A2A quick_* classmethods.
    • Async applies the pins in _create_ssl_context.
    • Sync mounts a _TlsVersionAdapter using urllib3's native ssl_minimum_version / ssl_maximum_version, only when a pin is set — the default transport path is unchanged.
  • HTTP/1.1 preserved on both stacks (HTTP/2 disallows the post-handshake CertificateRequest).
  • Version bumped to 8.2.0 (backward-compatible minor).

Usage:

import ssl
# Require TLS 1.3
SafeguardClient(host, auth=auth, min_tls_version=ssl.TLSVersion.TLSv1_3)
# Interim: cap at TLS 1.2
A2AContext(host, cert, key, max_tls_version=ssl.TLSVersion.TLSv1_2)

Tests

  • New unit tests: tests/test_tls.py (post-handshake auth enabled; pins applied; sync adapter mounted only when pinned; defaults unchanged; A2A forwarding).
  • New integration tests (auto-skip without an appliance): TLS-1.3 cert-auth in test_certificate_auth.py and TLS-1.3 A2A retrieval in test_a2a.py.
  • Full unit suite green (336 passed); ruff, ruff format --check src/, mypy --strict clean.

Docs

AGENTS.md (TLS 1.3 section), README, and the a2a-workflow + api-patterns skills.

⚠️ Before merge — live validation still pending

I have not yet validated against live appliances. Please confirm on real hardware:

  • SPP 9.0 (TLS 1.3): async + sync certificate auth and A2A credential retrieval succeed (this is the core fix).
  • SPP 8.x (TLS 1.2): no regression — async + sync cert/A2A auth still work.
  • min_tls_version=TLSv1_3 succeeds on 9.0; max_tls_version=TLSv1_2 still works on both.

The sync side is a review-confident change (uses urllib3's documented version knobs), but the whole point is TLS behavior against real appliances, so live sign-off is required.

Enable post-handshake authentication (RFC 8446 4.6.2) on the aiohttp
SSLContext so async certificate and A2A credential retrieval succeed
over TLS 1.3 on SPP 9.0 (previously failed with error 60094). The sync
requests/urllib3 path already enabled this by default.

Add opt-in min_tls_version / max_tls_version (ssl.TLSVersion | None,
default None) to SafeguardClient, AsyncSafeguardClient, A2AContext,
AsyncA2AContext, and the A2A quick_* classmethods. Async applies them in
_create_ssl_context; sync mounts a _TlsVersionAdapter using urllib3's
native ssl_minimum_version / ssl_maximum_version only when a pin is set,
so the default transport path is unchanged. HTTP/1.1 is preserved.

Add unit tests (tests/test_tls.py) and TLS 1.3 cert-auth / A2A
integration tests. Update AGENTS.md, README, and the a2a-workflow and
api-patterns skills. Bump version to 8.2.0.
Promote the TLS 1.3 guidance to a discoverable top-level README section covering what changed (post-handshake auth), version pinning, and Python-specific gotchas (HTTP/2 incompatibility, OpenSSL 1.1.1+ requirement, ssl.TLSVersion usage, verify=False context behavior).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support TLS 1.3 mTLS in async (aiohttp) A2A: enable post-handshake auth + add TLS-version option

1 participant