Skip to content

Expose the peerCertificate from mTLS to ServerContext #97

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 13, 2025

Conversation

jtdavey
Copy link
Contributor

@jtdavey jtdavey commented May 9, 2025

Motivation:

When using gRPC, it's useful to pull the peerCertificate from a successful mTLS connection for authn and/or authz.

Modifications:

These changes make use of the new transportSpecific field in the ServerContext. After a successful hanshake has completed, it uses the provided handler to retrieve the verified peer certificate and populate the Server Context.

There's also a simple happy path test that's been added for validation purposes.

Temporarily, this commit also references specific updates in swift-nio-ssl and grpc-swift.

Result:

This commit allows access to the swift Certificate object in an interceptor for the Posix HTTP2 transport. It also adds a mechanism for other transports to allow their own transport specific data.

Motivation:

When using gRPC, it's useful to pull the peerCertificate from a
successful mTLS connection for authn and/or authz.

Modifications:

These changes make use of the new transportSpecific field in the
ServerContext. After a successful hanshake has completed, it uses the
provided handler to retrieve the verified peer certificate and populate
the Server Context.

There's also a simple happy path test that's been added for validation
purposes.

Temporarily, this commit also references specific updates in
swift-nio-ssl and grpc-swift.

Result:

This commit allows access to the swift Certificate object in an
interceptor for the Posix HTTP2 transport. It also adds a mechanism for
other transports to allow their own transport specific data.
@glbrntt glbrntt added the 🆕 semver/minor Adds new public API. label May 12, 2025

@Test(
"Using the mTLS defaults, and with Posix transport, validate we get the peer cert on the server",
arguments: TransportKind.supported
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
arguments: TransportKind.supported
arguments: [TransportKind.posix]

arguments: TransportKind.supported
)
func testRPC_mTLS_TransportContext_OK(supportedTransport: TransportKind) async throws {
if TransportKind.posix == supportedTransport {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can remove this if we change arguments

Comment on lines 75 to 76
#expect(transportSpecific != nil)
#expect(transportSpecific is HTTP2ServerTransport.Posix.Context)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need these as they're covered by the #require below

transportSpecific as? HTTP2ServerTransport.Posix.Context
)
let peerCertificate = try #require(transportSpecificAsPosixContext.peerCertificate)
#expect(transportSpecificAsPosixContext.peerCertificate != nil)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't need this one: it's covered by the #require just above

Package.swift Outdated
@@ -51,7 +51,7 @@ let dependencies: [Package.Dependency] = [
),
.package(
url: "https://github.com/apple/swift-nio-ssl.git",
from: "2.29.0"
revision: "874ad69"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -186,6 +199,15 @@ extension HTTP2ServerTransport {
}

extension HTTP2ServerTransport.Posix {
/// Context for Posix TransportSpecific
public struct Context: ServerContext.TransportSpecific {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this compose overall? Shouldn't this be something that really every transport can vend optionally so code that has to do authn/z doesn't have to become transport specific @glbrntt?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The longer term move is to have mixin protocols (e.g. HasPeerCertificate) which contexts would conform to. Any common code would then use these rather than relying on a concrete transport specific type.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess my meta question is why do we consider that peer certificate needs to be a mix-in protocol and we can't make it part of the ServerContext right away. It seems in line with remotePeer: String to have a remotePeerCertificate: Certificate?. Since it has to be optional anyways.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It isn't really in line with it, you can't compute on remotePeer beyond using it as an identifier. remotePeer is also available to all transports, whereas the peer cert is only available here.

Adding it to the context brings in three more dependencies which would only be used by the NIO transport.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why only the NIO transport? Can't we provide a Certificate based peer identity on the NIOTS transport as well?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIO transport includes NIOTS. The NIOTS transport work hasn't been done yet (I'm not sure if the right APIs currently exist to do it.)

Package.swift Outdated
@@ -35,7 +35,7 @@ let products: [Product] = [
let dependencies: [Package.Dependency] = [
.package(
url: "https://github.com/grpc/grpc-swift.git",
from: "2.0.0"
revision: "0d850d6"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@glbrntt glbrntt enabled auto-merge (squash) May 13, 2025 09:29
@glbrntt glbrntt merged commit 5d0c90b into grpc:main May 13, 2025
27 of 29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🆕 semver/minor Adds new public API.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants