From 8fb78a2f4cf0b5ff7e0c7b0ae7bf7c905e297e6e Mon Sep 17 00:00:00 2001 From: Gus Cairo Date: Wed, 28 Aug 2024 13:11:23 +0100 Subject: [PATCH 01/10] Add TLS support for NIOPosix H2 client --- Examples/v2/echo/Subcommands/Collect.swift | 2 +- Examples/v2/echo/Subcommands/Expand.swift | 2 +- Examples/v2/echo/Subcommands/Get.swift | 2 +- Examples/v2/echo/Subcommands/Update.swift | 2 +- .../v2/hello-world/Subcommands/Greet.swift | 2 +- .../HTTP2ClientTransport+Posix.swift | 72 ++++++++++++++--- .../HTTP2ServerTransport+Posix.swift | 49 ++++++++++-- .../NIOSSL+GRPC.swift | 22 +++++- .../TLSConfig.swift | 51 ++++++++++++ .../InteroperabilityTestsExecutable.swift | 2 +- .../performance-worker/WorkerService.swift | 2 +- .../HTTP2TransportNIOPosixTests.swift | 78 ++++++++++++++++++- .../HTTP2TransportTests.swift | 2 +- 13 files changed, 256 insertions(+), 32 deletions(-) diff --git a/Examples/v2/echo/Subcommands/Collect.swift b/Examples/v2/echo/Subcommands/Collect.swift index 63402e0c6..3a61915df 100644 --- a/Examples/v2/echo/Subcommands/Collect.swift +++ b/Examples/v2/echo/Subcommands/Collect.swift @@ -32,7 +32,7 @@ struct Collect: AsyncParsableCommand { let client = GRPCClient( transport: try .http2NIOPosix( target: self.arguments.target, - config: .defaults() + config: .defaults(transportSecurity: .plaintext) ) ) diff --git a/Examples/v2/echo/Subcommands/Expand.swift b/Examples/v2/echo/Subcommands/Expand.swift index 33f89895d..1d06bdd99 100644 --- a/Examples/v2/echo/Subcommands/Expand.swift +++ b/Examples/v2/echo/Subcommands/Expand.swift @@ -32,7 +32,7 @@ struct Expand: AsyncParsableCommand { let client = GRPCClient( transport: try .http2NIOPosix( target: self.arguments.target, - config: .defaults() + config: .defaults(transportSecurity: .plaintext) ) ) diff --git a/Examples/v2/echo/Subcommands/Get.swift b/Examples/v2/echo/Subcommands/Get.swift index 400ba24a8..0dd551002 100644 --- a/Examples/v2/echo/Subcommands/Get.swift +++ b/Examples/v2/echo/Subcommands/Get.swift @@ -30,7 +30,7 @@ struct Get: AsyncParsableCommand { let client = GRPCClient( transport: try .http2NIOPosix( target: self.arguments.target, - config: .defaults() + config: .defaults(transportSecurity: .plaintext) ) ) diff --git a/Examples/v2/echo/Subcommands/Update.swift b/Examples/v2/echo/Subcommands/Update.swift index 04fdc1335..1c189caa8 100644 --- a/Examples/v2/echo/Subcommands/Update.swift +++ b/Examples/v2/echo/Subcommands/Update.swift @@ -32,7 +32,7 @@ struct Update: AsyncParsableCommand { let client = GRPCClient( transport: try .http2NIOPosix( target: self.arguments.target, - config: .defaults() + config: .defaults(transportSecurity: .plaintext) ) ) diff --git a/Examples/v2/hello-world/Subcommands/Greet.swift b/Examples/v2/hello-world/Subcommands/Greet.swift index aca973814..069b8faee 100644 --- a/Examples/v2/hello-world/Subcommands/Greet.swift +++ b/Examples/v2/hello-world/Subcommands/Greet.swift @@ -33,7 +33,7 @@ struct Greet: AsyncParsableCommand { let client = GRPCClient( transport: try .http2NIOPosix( target: .ipv4(host: "127.0.0.1", port: self.port), - config: .defaults() + config: .defaults(transportSecurity: .plaintext) ) ) diff --git a/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ClientTransport+Posix.swift b/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ClientTransport+Posix.swift index 995f8948f..50e0fff66 100644 --- a/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ClientTransport+Posix.swift +++ b/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ClientTransport+Posix.swift @@ -19,14 +19,18 @@ public import GRPCHTTP2Core // should be @usableFromInline public import NIOCore public import NIOPosix // has to be public because of default argument value in init +#if canImport(NIOSSL) +import NIOSSL +#endif + @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) extension HTTP2ClientTransport { - /// A `ClientTransport` using HTTP/2 built on top of `NIOPosix`. + /// A ``GRPCCore/ClientTransport`` using HTTP/2 built on top of `NIOPosix`. /// /// This transport builds on top of SwiftNIO's Posix networking layer and is suitable for use /// on Linux and Darwin based platform (macOS, iOS, etc.) However, it's *strongly* recommended /// that if you are targeting Darwin platforms then you should use the `NIOTS` variant of - /// the `HTTP2ClientTransport`. + /// the ``GRPCHTTP2Core/HTTP2ClientTransport``. /// /// To use this transport you need to provide a 'target' to connect to which will be resolved /// by an appropriate resolver from the resolver registry. By default the resolver registry can @@ -34,16 +38,19 @@ extension HTTP2ClientTransport { /// targets. If you use a custom target you must also provide an appropriately configured /// registry. /// - /// You can control various aspects of connection creation, management and RPC behavior via the - /// ``Config``. Load balancing policies and other RPC specific behavior can be configured via + /// You can control various aspects of connection creation, management, security and RPC behavior via + /// the ``Config``. Load balancing policies and other RPC specific behavior can be configured via /// the ``ServiceConfig`` (if it isn't provided by a resolver). /// /// Beyond creating the transport you don't need to interact with it directly, instead, pass it /// to a `GRPCClient`: /// /// ```swift - /// try await withThrowingDiscardingTaskGroup { - /// let transport = try HTTP2ClientTransport.Posix(target: .dns(host: "example.com")) + /// try await withThrowingDiscardingTaskGroup { group in + /// let transport = try HTTP2ClientTransport.Posix( + /// target: .ipv4(host: "example.com"), + /// config: .defaults(transportSecurity: someTransportSecurity) + /// ) /// let client = GRPCClient(transport: transport) /// group.addTask { /// try await client.run() @@ -133,11 +140,37 @@ extension HTTP2ClientTransport.Posix { func establishConnection( to address: GRPCHTTP2Core.SocketAddress ) async throws -> HTTP2Connection { + #if canImport(NIOSSL) + let nioSSLContext: NIOSSLContext? + switch self.config.transportSecurity.wrapped { + case .plaintext: + nioSSLContext = nil + case .tls(let tlsConfig): + do { + nioSSLContext = try NIOSSLContext(configuration: TLSConfiguration(tlsConfig)) + } catch { + throw RuntimeError( + code: .transportError, + message: "Couldn't create SSL context, check your TLS configuration.", + cause: error + ) + } + } + #endif + let (channel, multiplexer) = try await ClientBootstrap( group: self.eventLoopGroup ).connect(to: address) { channel in channel.eventLoop.makeCompletedFuture { - try channel.pipeline.syncOperations.configureGRPCClientPipeline( + #if canImport(NIOSSL) + if let nioSSLContext { + try channel.pipeline.syncOperations.addHandler( + NIOSSLServerHandler(context: nioSSLContext) + ) + } + #endif + + return try channel.pipeline.syncOperations.configureGRPCClientPipeline( channel: channel, config: GRPCChannel.Config(posix: self.config) ) @@ -164,31 +197,48 @@ extension HTTP2ClientTransport.Posix { /// Compression configuration. public var compression: HTTP2ClientTransport.Config.Compression + /// The transport's security. + public var transportSecurity: TransportSecurity + /// Creates a new connection configuration. /// - /// See also ``defaults``. + /// - Parameters: + /// - http2: HTTP2 configuration. + /// - backoff: Backoff configuration. + /// - connection: Connection configuration. + /// - compression: Compression configuration. + /// - transportSecurity: The transport's security configuration. + /// + /// - SeeAlso: ``defaults(_:)``. public init( http2: HTTP2ClientTransport.Config.HTTP2, backoff: HTTP2ClientTransport.Config.Backoff, connection: HTTP2ClientTransport.Config.Connection, - compression: HTTP2ClientTransport.Config.Compression + compression: HTTP2ClientTransport.Config.Compression, + transportSecurity: TransportSecurity ) { self.http2 = http2 self.connection = connection self.backoff = backoff self.compression = compression + self.transportSecurity = transportSecurity } /// Default values. /// /// - Parameters: + /// - transportSecurity: The security settings applied to the transport. /// - configure: A closure which allows you to modify the defaults before returning them. - public static func defaults(_ configure: (_ config: inout Self) -> Void = { _ in }) -> Self { + public static func defaults( + transportSecurity: TransportSecurity, + configure: (_ config: inout Self) -> Void = { _ in } + ) -> Self { var config = Self( http2: .defaults, backoff: .defaults, connection: .defaults, - compression: .defaults + compression: .defaults, + transportSecurity: transportSecurity ) configure(&config) return config diff --git a/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ServerTransport+Posix.swift b/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ServerTransport+Posix.swift index 49d15c2d5..d73e859b1 100644 --- a/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ServerTransport+Posix.swift +++ b/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ServerTransport+Posix.swift @@ -15,7 +15,7 @@ */ public import GRPCCore -public import GRPCHTTP2Core +public import GRPCHTTP2Core // should be @usableFromInline internal import NIOCore internal import NIOExtras internal import NIOHTTP2 @@ -27,7 +27,33 @@ import NIOSSL #endif extension HTTP2ServerTransport { - /// A NIOPosix-backed implementation of a server transport. + /// A ``GRPCCore/ServerTransport`` using HTTP/2 built on top of `NIOPosix`. + /// + /// This transport builds on top of SwiftNIO's Posix networking layer and is suitable for use + /// on Linux and Darwin based platform (macOS, iOS, etc.) However, it's *strongly* recommended + /// that if you are targeting Darwin platforms then you should use the `NIOTS` variant of + /// the ``GRPCHTTP2Core/HTTP2ServerTransport``. + /// + /// You can control various aspects of connection creation, management, security and RPC behavior via + /// the ``Config``. + /// + /// Beyond creating the transport you don't need to interact with it directly, instead, pass it + /// to a `GRPCServer`: + /// + /// ```swift + /// try await withThrowingDiscardingTaskGroup { group in + /// let transport = HTTP2ServerTransport.Posix( + /// address: .ipv4(.init(host: "127.0.0.1", port: 0)), + /// config: .defaults(transportSecurity: someTransportSecurity) + /// ) + /// let server = GRPCServer(transport: transport, services: someServices) + /// group.addTask { + /// try await server.run() + /// } + /// + /// // ... + /// } + /// ``` @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) public final class Posix: ServerTransport, ListeningServerTransport { private let address: GRPCHTTP2Core.SocketAddress @@ -340,27 +366,34 @@ extension HTTP2ServerTransport.Posix { public struct Config: Sendable { /// Compression configuration. public var compression: HTTP2ServerTransport.Config.Compression + /// Connection configuration. public var connection: HTTP2ServerTransport.Config.Connection + /// HTTP2 configuration. public var http2: HTTP2ServerTransport.Config.HTTP2 + /// RPC configuration. public var rpc: HTTP2ServerTransport.Config.RPC + /// The transport's security. public var transportSecurity: TransportSecurity /// Construct a new `Config`. + /// /// - Parameters: - /// - compression: Compression configuration. - /// - connection: Connection configuration. /// - http2: HTTP2 configuration. /// - rpc: RPC configuration. + /// - connection: Connection configuration. + /// - compression: Compression configuration. /// - transportSecurity: The transport's security configuration. + /// + /// - SeeAlso: ``defaults(transportSecurity:configure:)`` public init( - compression: HTTP2ServerTransport.Config.Compression, - connection: HTTP2ServerTransport.Config.Connection, http2: HTTP2ServerTransport.Config.HTTP2, rpc: HTTP2ServerTransport.Config.RPC, + connection: HTTP2ServerTransport.Config.Connection, + compression: HTTP2ServerTransport.Config.Compression, transportSecurity: TransportSecurity ) { self.compression = compression @@ -380,10 +413,10 @@ extension HTTP2ServerTransport.Posix { configure: (_ config: inout Self) -> Void = { _ in } ) -> Self { var config = Self( - compression: .defaults, - connection: .defaults, http2: .defaults, rpc: .defaults, + connection: .defaults, + compression: .defaults, transportSecurity: transportSecurity ) configure(&config) diff --git a/Sources/GRPCHTTP2TransportNIOPosix/NIOSSL+GRPC.swift b/Sources/GRPCHTTP2TransportNIOPosix/NIOSSL+GRPC.swift index 4bc3f143e..f4ac92e4e 100644 --- a/Sources/GRPCHTTP2TransportNIOPosix/NIOSSL+GRPC.swift +++ b/Sources/GRPCHTTP2TransportNIOPosix/NIOSSL+GRPC.swift @@ -127,7 +127,7 @@ extension CertificateVerification { extension TLSConfiguration { @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) - package init(_ tlsConfig: HTTP2ServerTransport.Posix.Config.TLS) throws { + init(_ tlsConfig: HTTP2ServerTransport.Posix.Config.TLS) throws { let certificateChain = try tlsConfig.certificateChain.sslCertificateSources() let privateKey = try NIOSSLPrivateKey(privateKey: tlsConfig.privateKey) @@ -144,5 +144,25 @@ extension TLSConfiguration { self = tlsConfiguration } + + @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) + init(_ tlsConfig: HTTP2ClientTransport.Posix.Config.TLS) throws { + var tlsConfiguration = TLSConfiguration.makeClientConfiguration() + tlsConfiguration.certificateChain = try tlsConfig.certificateChain.sslCertificateSources() + + if let privateKey = tlsConfig.privateKey { + let privateKeySource = try NIOSSLPrivateKey(privateKey: privateKey) + tlsConfiguration.privateKey = .privateKey(privateKeySource) + } + + tlsConfiguration.minimumTLSVersion = .tlsv12 + tlsConfiguration.certificateVerification = CertificateVerification( + tlsConfig.serverCertificateVerification + ) + tlsConfiguration.trustRoots = try NIOSSLTrustRoots(tlsConfig.trustRoots) + tlsConfiguration.applicationProtocols = ["grpc-exp", "h2"] + + self = tlsConfiguration + } } #endif diff --git a/Sources/GRPCHTTP2TransportNIOPosix/TLSConfig.swift b/Sources/GRPCHTTP2TransportNIOPosix/TLSConfig.swift index 591bafbe7..453346533 100644 --- a/Sources/GRPCHTTP2TransportNIOPosix/TLSConfig.swift +++ b/Sources/GRPCHTTP2TransportNIOPosix/TLSConfig.swift @@ -217,3 +217,54 @@ extension HTTP2ServerTransport.Posix.Config { } } } + +@available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) +extension HTTP2ClientTransport.Posix.Config { + /// The security configuration for this connection. + public struct TransportSecurity: Sendable { + package enum Wrapped: Sendable { + case plaintext + case tls(TLS) + } + + package let wrapped: Wrapped + + /// This connection is plaintext: no encryption will take place. + public static let plaintext = Self(wrapped: .plaintext) + + /// This connection will use TLS. + public static func tls(_ tls: TLS) -> Self { + Self(wrapped: .tls(tls)) + } + } + + public struct TLS: Sendable { + /// The certificates the client will offer during negotiation. + public var certificateChain: [TLSConfig.CertificateSource] + + /// The private key associated with the leaf certificate. + public var privateKey: TLSConfig.PrivateKeySource? + + /// How to verify the server certificate, if one is presented. + public var serverCertificateVerification: TLSConfig.CertificateVerification + + /// The trust roots to be used when verifying server certificates. + public var trustRoots: TLSConfig.TrustRootsSource + + /// Create a new HTTP2 NIO Posix transport TLS config, with some values defaulted: + /// - `certificateChain` is `[]` + /// - `privateKey` is `nil` + /// - `serverCertificateVerification` equals `fullVerification` + /// - `trustRoots` equals `systemDefault` + /// + /// - Returns: A new HTTP2 NIO Posix transport TLS config. + public static func defaults() -> Self { + Self.init( + certificateChain: [], + privateKey: nil, + serverCertificateVerification: .fullVerification, + trustRoots: .systemDefault + ) + } + } +} diff --git a/Sources/interoperability-tests/InteroperabilityTestsExecutable.swift b/Sources/interoperability-tests/InteroperabilityTestsExecutable.swift index 9b60f6031..15e1ba0fa 100644 --- a/Sources/interoperability-tests/InteroperabilityTestsExecutable.swift +++ b/Sources/interoperability-tests/InteroperabilityTestsExecutable.swift @@ -106,7 +106,7 @@ struct InteroperabilityTestsExecutable: AsyncParsableCommand { return GRPCClient( transport: try .http2NIOPosix( target: .ipv4(host: host, port: port), - config: .defaults { + config: .defaults(transportSecurity: .plaintext) { $0.compression.enabledAlgorithms = .all }, serviceConfig: serviceConfig diff --git a/Sources/performance-worker/WorkerService.swift b/Sources/performance-worker/WorkerService.swift index f029e146b..2864fc405 100644 --- a/Sources/performance-worker/WorkerService.swift +++ b/Sources/performance-worker/WorkerService.swift @@ -457,7 +457,7 @@ extension WorkerService { client: GRPCClient( transport: try .http2NIOPosix( target: target, - config: .defaults() + config: .defaults(transportSecurity: .plaintext) ) ), concurrentRPCs: Int(config.outstandingRpcsPerChannel), diff --git a/Tests/GRPCHTTP2TransportTests/HTTP2TransportNIOPosixTests.swift b/Tests/GRPCHTTP2TransportTests/HTTP2TransportNIOPosixTests.swift index 4f6993dde..c49b4cffc 100644 --- a/Tests/GRPCHTTP2TransportTests/HTTP2TransportNIOPosixTests.swift +++ b/Tests/GRPCHTTP2TransportTests/HTTP2TransportNIOPosixTests.swift @@ -263,7 +263,7 @@ final class HTTP2TransportNIOPosixTests: XCTestCase { -----END RSA PRIVATE KEY----- """ - func testTLSConfig_Defaults() throws { + func testServerTLSConfig_Defaults() throws { let grpcTLSConfig = HTTP2ServerTransport.Posix.Config.TLS.defaults( certificateChain: [ .bytes(Array(Self.samplePemCert.utf8), format: .pem) @@ -293,7 +293,7 @@ final class HTTP2TransportNIOPosixTests: XCTestCase { XCTAssertEqual(nioSSLTLSConfig.applicationProtocols, ["grpc-exp", "h2"]) } - func testTLSConfig_mTLS() throws { + func testServerTLSConfig_mTLS() throws { let grpcTLSConfig = HTTP2ServerTransport.Posix.Config.TLS.mTLS( certificateChain: [ .bytes(Array(Self.samplePemCert.utf8), format: .pem) @@ -323,7 +323,7 @@ final class HTTP2TransportNIOPosixTests: XCTestCase { XCTAssertEqual(nioSSLTLSConfig.applicationProtocols, ["grpc-exp", "h2"]) } - func testTLSConfig_FullVerifyClient() throws { + func testServerTLSConfig_FullVerifyClient() throws { var grpcTLSConfig = HTTP2ServerTransport.Posix.Config.TLS.defaults( certificateChain: [ .bytes(Array(Self.samplePemCert.utf8), format: .pem) @@ -354,7 +354,7 @@ final class HTTP2TransportNIOPosixTests: XCTestCase { XCTAssertEqual(nioSSLTLSConfig.applicationProtocols, ["grpc-exp", "h2"]) } - func testTLSConfig_CustomTrustRoots() throws { + func testServerTLSConfig_CustomTrustRoots() throws { var grpcTLSConfig = HTTP2ServerTransport.Posix.Config.TLS.defaults( certificateChain: [ .bytes(Array(Self.samplePemCert.utf8), format: .pem) @@ -387,5 +387,75 @@ final class HTTP2TransportNIOPosixTests: XCTestCase { ) XCTAssertEqual(nioSSLTLSConfig.applicationProtocols, ["grpc-exp", "h2"]) } + + func testClientTLSConfig_Defaults() throws { + let grpcTLSConfig = HTTP2ClientTransport.Posix.Config.TLS.defaults() + let nioSSLTLSConfig = try TLSConfiguration(grpcTLSConfig) + + XCTAssertEqual(nioSSLTLSConfig.certificateChain, []) + XCTAssertNil(nioSSLTLSConfig.privateKey) + XCTAssertEqual(nioSSLTLSConfig.minimumTLSVersion, .tlsv12) + XCTAssertEqual(nioSSLTLSConfig.certificateVerification, .fullVerification) + XCTAssertEqual(nioSSLTLSConfig.trustRoots, .default) + XCTAssertEqual(nioSSLTLSConfig.applicationProtocols, ["grpc-exp", "h2"]) + } + + func testClientTLSConfig_CustomCertificateChainAndPrivateKey() throws { + var grpcTLSConfig = HTTP2ClientTransport.Posix.Config.TLS.defaults() + grpcTLSConfig.certificateChain = [ + .bytes(Array(Self.samplePemCert.utf8), format: .pem) + ] + grpcTLSConfig.privateKey = .bytes(Array(Self.samplePemKey.utf8), format: .pem) + let nioSSLTLSConfig = try TLSConfiguration(grpcTLSConfig) + + XCTAssertEqual( + nioSSLTLSConfig.certificateChain, + [ + .certificate( + try NIOSSLCertificate( + bytes: Array(Self.samplePemCert.utf8), + format: .pem + ) + ) + ] + ) + XCTAssertEqual( + nioSSLTLSConfig.privateKey, + .privateKey(try NIOSSLPrivateKey(bytes: Array(Self.samplePemKey.utf8), format: .pem)) + ) + XCTAssertEqual(nioSSLTLSConfig.minimumTLSVersion, .tlsv12) + XCTAssertEqual(nioSSLTLSConfig.certificateVerification, .fullVerification) + XCTAssertEqual(nioSSLTLSConfig.trustRoots, .default) + XCTAssertEqual(nioSSLTLSConfig.applicationProtocols, ["grpc-exp", "h2"]) + } + + func testClientTLSConfig_CustomTrustRoots() throws { + var grpcTLSConfig = HTTP2ClientTransport.Posix.Config.TLS.defaults() + grpcTLSConfig.trustRoots = .certificates([.bytes(Array(Self.samplePemCert.utf8), format: .pem)]) + let nioSSLTLSConfig = try TLSConfiguration(grpcTLSConfig) + + XCTAssertEqual(nioSSLTLSConfig.certificateChain, []) + XCTAssertNil(nioSSLTLSConfig.privateKey) + XCTAssertEqual(nioSSLTLSConfig.minimumTLSVersion, .tlsv12) + XCTAssertEqual(nioSSLTLSConfig.certificateVerification, .fullVerification) + XCTAssertEqual( + nioSSLTLSConfig.trustRoots, + .certificates(try NIOSSLCertificate.fromPEMBytes(Array(Self.samplePemCert.utf8))) + ) + XCTAssertEqual(nioSSLTLSConfig.applicationProtocols, ["grpc-exp", "h2"]) + } + + func testClientTLSConfig_CustomCertificateVerification() throws { + var grpcTLSConfig = HTTP2ClientTransport.Posix.Config.TLS.defaults() + grpcTLSConfig.serverCertificateVerification = .noHostnameVerification + let nioSSLTLSConfig = try TLSConfiguration(grpcTLSConfig) + + XCTAssertEqual(nioSSLTLSConfig.certificateChain, []) + XCTAssertNil(nioSSLTLSConfig.privateKey) + XCTAssertEqual(nioSSLTLSConfig.minimumTLSVersion, .tlsv12) + XCTAssertEqual(nioSSLTLSConfig.certificateVerification, .noHostnameVerification) + XCTAssertEqual(nioSSLTLSConfig.trustRoots, .default) + XCTAssertEqual(nioSSLTLSConfig.applicationProtocols, ["grpc-exp", "h2"]) + } #endif } diff --git a/Tests/GRPCHTTP2TransportTests/HTTP2TransportTests.swift b/Tests/GRPCHTTP2TransportTests/HTTP2TransportTests.swift index 2de224ffc..a78751874 100644 --- a/Tests/GRPCHTTP2TransportTests/HTTP2TransportTests.swift +++ b/Tests/GRPCHTTP2TransportTests/HTTP2TransportTests.swift @@ -199,7 +199,7 @@ final class HTTP2TransportTests: XCTestCase { serviceConfig.loadBalancingConfig = [.roundRobin] transport = try HTTP2ClientTransport.Posix( target: target, - config: .defaults { + config: .defaults(transportSecurity: .plaintext) { $0.compression.algorithm = compression $0.compression.enabledAlgorithms = enabledCompression }, From e2ec93ebefdc838e386111e3363a4f4956775113 Mon Sep 17 00:00:00 2001 From: Gus Cairo Date: Wed, 28 Aug 2024 13:23:09 +0100 Subject: [PATCH 02/10] Formatting --- .../HTTP2ServerTransport+Posix.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ServerTransport+Posix.swift b/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ServerTransport+Posix.swift index d73e859b1..bbbb2217a 100644 --- a/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ServerTransport+Posix.swift +++ b/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ServerTransport+Posix.swift @@ -15,7 +15,7 @@ */ public import GRPCCore -public import GRPCHTTP2Core // should be @usableFromInline +public import GRPCHTTP2Core // should be @usableFromInline internal import NIOCore internal import NIOExtras internal import NIOHTTP2 @@ -380,7 +380,7 @@ extension HTTP2ServerTransport.Posix { public var transportSecurity: TransportSecurity /// Construct a new `Config`. - /// + /// /// - Parameters: /// - http2: HTTP2 configuration. /// - rpc: RPC configuration. From 8f288127079c5f0dbd2fcfe05ea488597ca9b0ed Mon Sep 17 00:00:00 2001 From: Gus Cairo Date: Thu, 5 Sep 2024 14:44:49 +0100 Subject: [PATCH 03/10] PR fixes --- .../HTTP2ClientTransport+Posix.swift | 10 +++++-- .../HTTP2ServerTransport+Posix.swift | 2 +- .../NIOSSL+GRPC.swift | 28 ++++++++----------- .../TLSConfig.swift | 19 ++++++++----- 4 files changed, 33 insertions(+), 26 deletions(-) diff --git a/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ClientTransport+Posix.swift b/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ClientTransport+Posix.swift index 50e0fff66..4d28c2431 100644 --- a/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ClientTransport+Posix.swift +++ b/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ClientTransport+Posix.swift @@ -49,7 +49,7 @@ extension HTTP2ClientTransport { /// try await withThrowingDiscardingTaskGroup { group in /// let transport = try HTTP2ClientTransport.Posix( /// target: .ipv4(host: "example.com"), - /// config: .defaults(transportSecurity: someTransportSecurity) + /// config: .defaults(transportSecurity: .plaintext) /// ) /// let client = GRPCClient(transport: transport) /// group.addTask { @@ -142,12 +142,15 @@ extension HTTP2ClientTransport.Posix { ) async throws -> HTTP2Connection { #if canImport(NIOSSL) let nioSSLContext: NIOSSLContext? + let serverHostname: String? switch self.config.transportSecurity.wrapped { case .plaintext: nioSSLContext = nil + serverHostname = nil case .tls(let tlsConfig): do { nioSSLContext = try NIOSSLContext(configuration: TLSConfiguration(tlsConfig)) + serverHostname = tlsConfig.serverHostname } catch { throw RuntimeError( code: .transportError, @@ -165,7 +168,10 @@ extension HTTP2ClientTransport.Posix { #if canImport(NIOSSL) if let nioSSLContext { try channel.pipeline.syncOperations.addHandler( - NIOSSLServerHandler(context: nioSSLContext) + NIOSSLClientHandler( + context: nioSSLContext, + serverHostname: serverHostname + ) ) } #endif diff --git a/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ServerTransport+Posix.swift b/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ServerTransport+Posix.swift index bbbb2217a..fe43f0dc7 100644 --- a/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ServerTransport+Posix.swift +++ b/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ServerTransport+Posix.swift @@ -44,7 +44,7 @@ extension HTTP2ServerTransport { /// try await withThrowingDiscardingTaskGroup { group in /// let transport = HTTP2ServerTransport.Posix( /// address: .ipv4(.init(host: "127.0.0.1", port: 0)), - /// config: .defaults(transportSecurity: someTransportSecurity) + /// config: .defaults(transportSecurity: .plaintext) /// ) /// let server = GRPCServer(transport: transport, services: someServices) /// group.addTask { diff --git a/Sources/GRPCHTTP2TransportNIOPosix/NIOSSL+GRPC.swift b/Sources/GRPCHTTP2TransportNIOPosix/NIOSSL+GRPC.swift index f4ac92e4e..5c3a72e79 100644 --- a/Sources/GRPCHTTP2TransportNIOPosix/NIOSSL+GRPC.swift +++ b/Sources/GRPCHTTP2TransportNIOPosix/NIOSSL+GRPC.swift @@ -131,38 +131,34 @@ extension TLSConfiguration { let certificateChain = try tlsConfig.certificateChain.sslCertificateSources() let privateKey = try NIOSSLPrivateKey(privateKey: tlsConfig.privateKey) - var tlsConfiguration = TLSConfiguration.makeServerConfiguration( + self = TLSConfiguration.makeServerConfiguration( certificateChain: certificateChain, privateKey: .privateKey(privateKey) ) - tlsConfiguration.minimumTLSVersion = .tlsv12 - tlsConfiguration.certificateVerification = CertificateVerification( + self.minimumTLSVersion = .tlsv12 + self.certificateVerification = CertificateVerification( tlsConfig.clientCertificateVerification ) - tlsConfiguration.trustRoots = try NIOSSLTrustRoots(tlsConfig.trustRoots) - tlsConfiguration.applicationProtocols = ["grpc-exp", "h2"] - - self = tlsConfiguration + self.trustRoots = try NIOSSLTrustRoots(tlsConfig.trustRoots) + self.applicationProtocols = ["grpc-exp", "h2"] } @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) init(_ tlsConfig: HTTP2ClientTransport.Posix.Config.TLS) throws { - var tlsConfiguration = TLSConfiguration.makeClientConfiguration() - tlsConfiguration.certificateChain = try tlsConfig.certificateChain.sslCertificateSources() + self = TLSConfiguration.makeClientConfiguration() + self.certificateChain = try tlsConfig.certificateChain.sslCertificateSources() if let privateKey = tlsConfig.privateKey { let privateKeySource = try NIOSSLPrivateKey(privateKey: privateKey) - tlsConfiguration.privateKey = .privateKey(privateKeySource) + self.privateKey = .privateKey(privateKeySource) } - tlsConfiguration.minimumTLSVersion = .tlsv12 - tlsConfiguration.certificateVerification = CertificateVerification( + self.minimumTLSVersion = .tlsv12 + self.certificateVerification = CertificateVerification( tlsConfig.serverCertificateVerification ) - tlsConfiguration.trustRoots = try NIOSSLTrustRoots(tlsConfig.trustRoots) - tlsConfiguration.applicationProtocols = ["grpc-exp", "h2"] - - self = tlsConfiguration + self.trustRoots = try NIOSSLTrustRoots(tlsConfig.trustRoots) + self.applicationProtocols = ["grpc-exp", "h2"] } } #endif diff --git a/Sources/GRPCHTTP2TransportNIOPosix/TLSConfig.swift b/Sources/GRPCHTTP2TransportNIOPosix/TLSConfig.swift index 453346533..a57469e8b 100644 --- a/Sources/GRPCHTTP2TransportNIOPosix/TLSConfig.swift +++ b/Sources/GRPCHTTP2TransportNIOPosix/TLSConfig.swift @@ -184,7 +184,7 @@ extension HTTP2ServerTransport.Posix.Config { certificateChain: [TLSConfig.CertificateSource], privateKey: TLSConfig.PrivateKeySource ) -> Self { - Self.init( + Self( certificateChain: certificateChain, privateKey: privateKey, clientCertificateVerification: .noVerification, @@ -207,7 +207,7 @@ extension HTTP2ServerTransport.Posix.Config { certificateChain: [TLSConfig.CertificateSource], privateKey: TLSConfig.PrivateKeySource ) -> Self { - Self.init( + Self( certificateChain: certificateChain, privateKey: privateKey, clientCertificateVerification: .noHostnameVerification, @@ -251,19 +251,24 @@ extension HTTP2ClientTransport.Posix.Config { /// The trust roots to be used when verifying server certificates. public var trustRoots: TLSConfig.TrustRootsSource + /// An optional server hostname to use when verifying certificates. + public var serverHostname: String? + /// Create a new HTTP2 NIO Posix transport TLS config, with some values defaulted: - /// - `certificateChain` is `[]` - /// - `privateKey` is `nil` + /// - `certificateChain` equals `[]` + /// - `privateKey` equals `nil` /// - `serverCertificateVerification` equals `fullVerification` /// - `trustRoots` equals `systemDefault` + /// - `serverHostname` equals `nil` /// /// - Returns: A new HTTP2 NIO Posix transport TLS config. - public static func defaults() -> Self { - Self.init( + public static var defaults: Self { + Self( certificateChain: [], privateKey: nil, serverCertificateVerification: .fullVerification, - trustRoots: .systemDefault + trustRoots: .systemDefault, + serverHostname: nil ) } } From 5076827ac0e7d052ce18eaf9d2768a84ed31b010 Mon Sep 17 00:00:00 2001 From: Gus Cairo Date: Fri, 6 Sep 2024 17:07:40 +0100 Subject: [PATCH 04/10] Add mTLS TLSConfig for client --- .../TLSConfig.swift | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Sources/GRPCHTTP2TransportNIOPosix/TLSConfig.swift b/Sources/GRPCHTTP2TransportNIOPosix/TLSConfig.swift index a57469e8b..a3dcaffb7 100644 --- a/Sources/GRPCHTTP2TransportNIOPosix/TLSConfig.swift +++ b/Sources/GRPCHTTP2TransportNIOPosix/TLSConfig.swift @@ -271,5 +271,25 @@ extension HTTP2ClientTransport.Posix.Config { serverHostname: nil ) } + + /// Create a new HTTP2 NIO Posix transport TLS config, with some values defaulted to match + /// the requirements of mTLS: + /// - `trustRoots` equals `systemDefault` + /// + /// - Parameters: + /// - certificateChain: The certificates the client will offer during negotiation. + /// - privateKey: The private key associated with the leaf certificate. + /// - Returns: A new HTTP2 NIO Posix transport TLS config. + public static func mTLS( + certificateChain: [TLSConfig.CertificateSource], + privateKey: TLSConfig.PrivateKeySource + ) -> Self { + Self( + certificateChain: certificateChain, + privateKey: privateKey, + serverCertificateVerification: .fullVerification, + trustRoots: .systemDefault + ) + } } } From ca209947c934b5ba70b9bedfb6fb585ed063ef71 Mon Sep 17 00:00:00 2001 From: Gus Cairo Date: Mon, 9 Sep 2024 13:50:22 +0100 Subject: [PATCH 05/10] Fix broken tests/examples --- Examples/v2/route-guide/Subcommands/GetFeature.swift | 2 +- Examples/v2/route-guide/Subcommands/ListFeatures.swift | 2 +- Examples/v2/route-guide/Subcommands/RecordRoute.swift | 2 +- Examples/v2/route-guide/Subcommands/RouteChat.swift | 2 +- .../HTTP2TransportNIOPosixTests.swift | 8 ++++---- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Examples/v2/route-guide/Subcommands/GetFeature.swift b/Examples/v2/route-guide/Subcommands/GetFeature.swift index 6e51f2427..1c42ec6da 100644 --- a/Examples/v2/route-guide/Subcommands/GetFeature.swift +++ b/Examples/v2/route-guide/Subcommands/GetFeature.swift @@ -39,7 +39,7 @@ struct GetFeature: AsyncParsableCommand { func run() async throws { let transport = try HTTP2ClientTransport.Posix( target: .ipv4(host: "127.0.0.1", port: self.port), - config: .defaults() + config: .defaults(transportSecurity: .plaintext) ) let client = GRPCClient(transport: transport) diff --git a/Examples/v2/route-guide/Subcommands/ListFeatures.swift b/Examples/v2/route-guide/Subcommands/ListFeatures.swift index ea95cb593..887a944e2 100644 --- a/Examples/v2/route-guide/Subcommands/ListFeatures.swift +++ b/Examples/v2/route-guide/Subcommands/ListFeatures.swift @@ -53,7 +53,7 @@ struct ListFeatures: AsyncParsableCommand { func run() async throws { let transport = try HTTP2ClientTransport.Posix( target: .ipv4(host: "127.0.0.1", port: self.port), - config: .defaults() + config: .defaults(transportSecurity: .plaintext) ) let client = GRPCClient(transport: transport) diff --git a/Examples/v2/route-guide/Subcommands/RecordRoute.swift b/Examples/v2/route-guide/Subcommands/RecordRoute.swift index 829f5ee06..cd443230b 100644 --- a/Examples/v2/route-guide/Subcommands/RecordRoute.swift +++ b/Examples/v2/route-guide/Subcommands/RecordRoute.swift @@ -32,7 +32,7 @@ struct RecordRoute: AsyncParsableCommand { func run() async throws { let transport = try HTTP2ClientTransport.Posix( target: .ipv4(host: "127.0.0.1", port: self.port), - config: .defaults() + config: .defaults(transportSecurity: .plaintext) ) let client = GRPCClient(transport: transport) diff --git a/Examples/v2/route-guide/Subcommands/RouteChat.swift b/Examples/v2/route-guide/Subcommands/RouteChat.swift index 7fbf673c2..81cb5c3e2 100644 --- a/Examples/v2/route-guide/Subcommands/RouteChat.swift +++ b/Examples/v2/route-guide/Subcommands/RouteChat.swift @@ -32,7 +32,7 @@ struct RouteChat: AsyncParsableCommand { func run() async throws { let transport = try HTTP2ClientTransport.Posix( target: .ipv4(host: "127.0.0.1", port: self.port), - config: .defaults() + config: .defaults(transportSecurity: .plaintext) ) let client = GRPCClient(transport: transport) diff --git a/Tests/GRPCHTTP2TransportTests/HTTP2TransportNIOPosixTests.swift b/Tests/GRPCHTTP2TransportTests/HTTP2TransportNIOPosixTests.swift index c49b4cffc..aa6af81c9 100644 --- a/Tests/GRPCHTTP2TransportTests/HTTP2TransportNIOPosixTests.swift +++ b/Tests/GRPCHTTP2TransportTests/HTTP2TransportNIOPosixTests.swift @@ -389,7 +389,7 @@ final class HTTP2TransportNIOPosixTests: XCTestCase { } func testClientTLSConfig_Defaults() throws { - let grpcTLSConfig = HTTP2ClientTransport.Posix.Config.TLS.defaults() + let grpcTLSConfig = HTTP2ClientTransport.Posix.Config.TLS.defaults let nioSSLTLSConfig = try TLSConfiguration(grpcTLSConfig) XCTAssertEqual(nioSSLTLSConfig.certificateChain, []) @@ -401,7 +401,7 @@ final class HTTP2TransportNIOPosixTests: XCTestCase { } func testClientTLSConfig_CustomCertificateChainAndPrivateKey() throws { - var grpcTLSConfig = HTTP2ClientTransport.Posix.Config.TLS.defaults() + var grpcTLSConfig = HTTP2ClientTransport.Posix.Config.TLS.defaults grpcTLSConfig.certificateChain = [ .bytes(Array(Self.samplePemCert.utf8), format: .pem) ] @@ -430,7 +430,7 @@ final class HTTP2TransportNIOPosixTests: XCTestCase { } func testClientTLSConfig_CustomTrustRoots() throws { - var grpcTLSConfig = HTTP2ClientTransport.Posix.Config.TLS.defaults() + var grpcTLSConfig = HTTP2ClientTransport.Posix.Config.TLS.defaults grpcTLSConfig.trustRoots = .certificates([.bytes(Array(Self.samplePemCert.utf8), format: .pem)]) let nioSSLTLSConfig = try TLSConfiguration(grpcTLSConfig) @@ -446,7 +446,7 @@ final class HTTP2TransportNIOPosixTests: XCTestCase { } func testClientTLSConfig_CustomCertificateVerification() throws { - var grpcTLSConfig = HTTP2ClientTransport.Posix.Config.TLS.defaults() + var grpcTLSConfig = HTTP2ClientTransport.Posix.Config.TLS.defaults grpcTLSConfig.serverCertificateVerification = .noHostnameVerification let nioSSLTLSConfig = try TLSConfiguration(grpcTLSConfig) From 3479346e552fa478ced071241e1ac950df743d7d Mon Sep 17 00:00:00 2001 From: Gus Cairo Date: Mon, 9 Sep 2024 13:50:40 +0100 Subject: [PATCH 06/10] Hide tls security option if cannot import NIOSSL --- Sources/GRPCHTTP2TransportNIOPosix/TLSConfig.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Sources/GRPCHTTP2TransportNIOPosix/TLSConfig.swift b/Sources/GRPCHTTP2TransportNIOPosix/TLSConfig.swift index a3dcaffb7..9711cc33b 100644 --- a/Sources/GRPCHTTP2TransportNIOPosix/TLSConfig.swift +++ b/Sources/GRPCHTTP2TransportNIOPosix/TLSConfig.swift @@ -147,10 +147,12 @@ extension HTTP2ServerTransport.Posix.Config { /// This connection is plaintext: no encryption will take place. public static let plaintext = Self(wrapped: .plaintext) + #if canImport(NIOSSL) /// This connection will use TLS. public static func tls(_ tls: TLS) -> Self { Self(wrapped: .tls(tls)) } + #endif } public struct TLS: Sendable { @@ -232,10 +234,12 @@ extension HTTP2ClientTransport.Posix.Config { /// This connection is plaintext: no encryption will take place. public static let plaintext = Self(wrapped: .plaintext) + #if canImport(NIOSSL) /// This connection will use TLS. public static func tls(_ tls: TLS) -> Self { Self(wrapped: .tls(tls)) } + #endif } public struct TLS: Sendable { From 58db8c40f4fbe0102670777eacc000bdb1313992 Mon Sep 17 00:00:00 2001 From: Gus Cairo Date: Mon, 9 Sep 2024 13:50:47 +0100 Subject: [PATCH 07/10] Fix docs --- .../HTTP2ServerTransport+Posix.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ServerTransport+Posix.swift b/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ServerTransport+Posix.swift index fe43f0dc7..0717f0f35 100644 --- a/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ServerTransport+Posix.swift +++ b/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ServerTransport+Posix.swift @@ -43,12 +43,12 @@ extension HTTP2ServerTransport { /// ```swift /// try await withThrowingDiscardingTaskGroup { group in /// let transport = HTTP2ServerTransport.Posix( - /// address: .ipv4(.init(host: "127.0.0.1", port: 0)), + /// address: .ipv4(host: "127.0.0.1", port: 0), /// config: .defaults(transportSecurity: .plaintext) /// ) /// let server = GRPCServer(transport: transport, services: someServices) /// group.addTask { - /// try await server.run() + /// try await server.serve() /// } /// /// // ... From 8b401f1778b7ad93162799ad1c90d2992e04fb00 Mon Sep 17 00:00:00 2001 From: Gus Cairo Date: Mon, 9 Sep 2024 13:50:56 +0100 Subject: [PATCH 08/10] Only create NIOSSLContext once --- .../HTTP2ClientTransport+Posix.swift | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ClientTransport+Posix.swift b/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ClientTransport+Posix.swift index 4d28c2431..02665c369 100644 --- a/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ClientTransport+Posix.swift +++ b/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ClientTransport+Posix.swift @@ -94,7 +94,7 @@ extension HTTP2ClientTransport { // Configure a connector. self.channel = GRPCChannel( resolver: resolver, - connector: Connector(eventLoopGroup: eventLoopGroup, config: config), + connector: try Connector(eventLoopGroup: eventLoopGroup, config: config), config: GRPCChannel.Config(posix: config), defaultServiceConfig: serviceConfig ) @@ -132,25 +132,24 @@ extension HTTP2ClientTransport.Posix { private let config: HTTP2ClientTransport.Posix.Config private let eventLoopGroup: any EventLoopGroup - init(eventLoopGroup: any EventLoopGroup, config: HTTP2ClientTransport.Posix.Config) { + #if canImport(NIOSSL) + private let nioSSLContext: NIOSSLContext? + private let serverHostname: String? + #endif + + init(eventLoopGroup: any EventLoopGroup, config: HTTP2ClientTransport.Posix.Config) throws { self.eventLoopGroup = eventLoopGroup self.config = config - } - func establishConnection( - to address: GRPCHTTP2Core.SocketAddress - ) async throws -> HTTP2Connection { #if canImport(NIOSSL) - let nioSSLContext: NIOSSLContext? - let serverHostname: String? switch self.config.transportSecurity.wrapped { case .plaintext: - nioSSLContext = nil - serverHostname = nil + self.nioSSLContext = nil + self.serverHostname = nil case .tls(let tlsConfig): do { - nioSSLContext = try NIOSSLContext(configuration: TLSConfiguration(tlsConfig)) - serverHostname = tlsConfig.serverHostname + self.nioSSLContext = try NIOSSLContext(configuration: TLSConfiguration(tlsConfig)) + self.serverHostname = tlsConfig.serverHostname } catch { throw RuntimeError( code: .transportError, @@ -159,18 +158,22 @@ extension HTTP2ClientTransport.Posix { ) } } - #endif + #endif + } + func establishConnection( + to address: GRPCHTTP2Core.SocketAddress + ) async throws -> HTTP2Connection { let (channel, multiplexer) = try await ClientBootstrap( group: self.eventLoopGroup ).connect(to: address) { channel in channel.eventLoop.makeCompletedFuture { #if canImport(NIOSSL) - if let nioSSLContext { + if let nioSSLContext = self.nioSSLContext { try channel.pipeline.syncOperations.addHandler( NIOSSLClientHandler( context: nioSSLContext, - serverHostname: serverHostname + serverHostname: self.serverHostname ) ) } From 6393970d15c4763874b8639d63f0a8dfb261dd5c Mon Sep 17 00:00:00 2001 From: Gus Cairo Date: Mon, 9 Sep 2024 13:51:26 +0100 Subject: [PATCH 09/10] Formatting --- .../GRPCHTTP2TransportNIOPosix/HTTP2ClientTransport+Posix.swift | 2 +- Sources/GRPCHTTP2TransportNIOPosix/TLSConfig.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ClientTransport+Posix.swift b/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ClientTransport+Posix.swift index 02665c369..57e969e3a 100644 --- a/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ClientTransport+Posix.swift +++ b/Sources/GRPCHTTP2TransportNIOPosix/HTTP2ClientTransport+Posix.swift @@ -158,7 +158,7 @@ extension HTTP2ClientTransport.Posix { ) } } - #endif + #endif } func establishConnection( diff --git a/Sources/GRPCHTTP2TransportNIOPosix/TLSConfig.swift b/Sources/GRPCHTTP2TransportNIOPosix/TLSConfig.swift index 9711cc33b..2e42d58c1 100644 --- a/Sources/GRPCHTTP2TransportNIOPosix/TLSConfig.swift +++ b/Sources/GRPCHTTP2TransportNIOPosix/TLSConfig.swift @@ -152,7 +152,7 @@ extension HTTP2ServerTransport.Posix.Config { public static func tls(_ tls: TLS) -> Self { Self(wrapped: .tls(tls)) } - #endif + #endif } public struct TLS: Sendable { From 8853b7e9a1b86e26be88ea3fb4f3a992969fd6c3 Mon Sep 17 00:00:00 2001 From: Gus Cairo Date: Mon, 9 Sep 2024 13:56:06 +0100 Subject: [PATCH 10/10] Change extension visibility --- Sources/GRPCHTTP2TransportNIOPosix/NIOSSL+GRPC.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/GRPCHTTP2TransportNIOPosix/NIOSSL+GRPC.swift b/Sources/GRPCHTTP2TransportNIOPosix/NIOSSL+GRPC.swift index 5c3a72e79..94436f56e 100644 --- a/Sources/GRPCHTTP2TransportNIOPosix/NIOSSL+GRPC.swift +++ b/Sources/GRPCHTTP2TransportNIOPosix/NIOSSL+GRPC.swift @@ -127,7 +127,7 @@ extension CertificateVerification { extension TLSConfiguration { @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) - init(_ tlsConfig: HTTP2ServerTransport.Posix.Config.TLS) throws { + package init(_ tlsConfig: HTTP2ServerTransport.Posix.Config.TLS) throws { let certificateChain = try tlsConfig.certificateChain.sslCertificateSources() let privateKey = try NIOSSLPrivateKey(privateKey: tlsConfig.privateKey) @@ -144,7 +144,7 @@ extension TLSConfiguration { } @available(macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0, *) - init(_ tlsConfig: HTTP2ClientTransport.Posix.Config.TLS) throws { + package init(_ tlsConfig: HTTP2ClientTransport.Posix.Config.TLS) throws { self = TLSConfiguration.makeClientConfiguration() self.certificateChain = try tlsConfig.certificateChain.sslCertificateSources()