Repository navigation
Scope the NIOSSL mTLS identity to its origin - #21
Merged
Merged
Conversation
`tlsLocalIdentityNetworkFramework` is a single client-wide identity, so every connection opened by a client that uses Network.framework presented it to any server that asked for a client certificate, including the target of a redirect to a different host. Apple's own URLSession (and browsers) choose the certificate per challenge/origin instead. Add `tlsLocalIdentityProviderNetworkFramework`, a closure that receives the host and port of the origin a connection is opened to and returns the identity to present (or nil for none). Connections are per origin, so a redirect to another host asks the provider again with that host and an identity meant for the original host is never sent to it. The provider takes precedence over the unscoped property, which is kept for source compatibility and documented as not origin-scoped. The tests build the SecIdentity from an in-memory PKCS#12 bundle (kSecImportToMemoryOnly) rather than a Keychain round-trip, which failed to find the key it had just added and made every identity test skip, and configure the client not to verify the self-signed test server so the handshake can complete. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Setting `certificateChain`/`privateKey` on `tlsConfiguration` (or on a request's own TLS configuration, which redirects preserve) presents that identity to every server the client connects to, including the target of a redirect to a different host. URLSession and browsers choose the certificate per challenge/origin. Add `tlsLocalIdentityProviderNIOSSL`, a closure that receives the host and port of the origin a connection is opened to and returns the identity to present (or nil for none). When it is set, it is the only source of the client identity: its answer replaces the certificate chain and private key of the TLS configuration used for the connection, for both direct and proxy-tunnelled connections. Without a provider behaviour is unchanged. Share the origin computation with the Network.framework provider through `ConnectionPool.Key.origin`. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The proxy-tunnel TLS setup is a separate call site from the direct-connection one. Cover that the provider is asked for the destination origin (not the proxy) and that the identity it chooses is, or is not, presented through the tunnel. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…y-per-origin-release # Conflicts: # Sources/AsyncHTTPClient/ConnectionPool.swift # Sources/AsyncHTTPClient/ConnectionPool/HTTPConnectionPool+Factory.swift # Sources/AsyncHTTPClient/NIOTransportServices/TLSConfiguration.swift # Tests/AsyncHTTPClientTests/LocalIdentityNetworkFrameworkTests.swift
…OSSL's doc comment TLSConfiguration is NIOSSL's type, so DocC can't resolve it as a symbol link of this module. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Same change as #20 (draft against
main), applied torelease: a per-origintlsLocalIdentityProviderNIOSSLso an mTLS identity is not presented to every server the client connects to, including redirect targets. See #20 for the problem statement and design.Summary
tlsLocalIdentityProviderNIOSSL: (@Sendable (_ host: String, _ port: Int) -> NIOSSLClientIdentity?)?. When set it is the only source of the client identity: its answer replacescertificateChain/privateKeyof the TLS configuration used for the connection (client-level or request-level), at both NIOSSL sites (direct and proxy tunnel). Without a provider nothing changes, so existing users of the 1.38.x/1.39.x tags are unaffected; adopting it is a caller-side opt-in.ConnectionPool.Key.originwith the Network.framework provider from Scope the Network.framework mTLS identity to its origin #19; that helper now takes the origin.Dependencies
Stacked on #19 (the Network.framework counterpart): this branch is that one plus the single cherry-picked commit. Land #19 first. Only conflict on the cherry-pick was the factory call site, where
releasealso passescustomVerification; both arguments kept.Tests
LocalIdentityNIOSSLTests(11) +LocalIdentityNetworkFrameworkTests(7) +TrustCustomVerificationTests(6): 24 tests pass. Redirect to another host does not receive the identity; anilanswer beats an identity intlsConfigurationand in a request's own TLS configuration; behaviour without a provider is unchanged. Full suite on this branch: the only failures are the twotestConnectTimeout, which also fail on a cleanmain(see #18).Proxy tunnel: three tests go through a simulated
CONNECTproxy that terminates TLS and demands a client certificate: the provider is asked for the destination origin (not the proxy), and the identity is presented or withheld accordingly. Removing the tunnel call site makes two of them fail.🤖 Generated with Claude Code