Skip to content

Commit b0d3ba0

Browse files
authored
Add E2E tests with TLS enabled (#12)
This PR adds E2E tests for `NIOPosix`'s transport implementation with TLS enabled. It also adds some additional API to create TLS configs.
1 parent 4d5d6fe commit b0d3ba0

File tree

4 files changed

+533
-13
lines changed

4 files changed

+533
-13
lines changed

Package.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ let dependencies: [Package.Dependency] = [
5757
url: "https://github.com/apple/swift-nio-extras.git",
5858
from: "1.4.0"
5959
),
60+
.package(
61+
url: "https://github.com/apple/swift-certificates.git",
62+
from: "1.5.0"
63+
),
6064
]
6165

6266
let defaultSwiftSettings: [SwiftSetting] = [
@@ -104,6 +108,7 @@ let targets: [Target] = [
104108
.target(name: "GRPCNIOTransportCore"),
105109
.product(name: "GRPCCore", package: "grpc-swift"),
106110
.product(name: "NIOPosix", package: "swift-nio"),
111+
.product(name: "NIOSSL", package: "swift-nio-ssl"),
107112
],
108113
swiftSettings: defaultSwiftSettings
109114
),
@@ -132,6 +137,8 @@ let targets: [Target] = [
132137
name: "GRPCNIOTransportHTTP2Tests",
133138
dependencies: [
134139
.target(name: "GRPCNIOTransportHTTP2"),
140+
.product(name: "X509", package: "swift-certificates"),
141+
.product(name: "NIOSSL", package: "swift-nio-ssl"),
135142
]
136143
)
137144
]

Sources/GRPCNIOTransportHTTP2Posix/TLSConfig.swift

Lines changed: 81 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,27 @@ extension HTTP2ServerTransport.Posix.Config {
172172
/// If this is set to `true` but the client does not support ALPN, then the connection will be rejected.
173173
public var requireALPN: Bool
174174

175+
/// Create a new HTTP2 NIO Posix server transport TLS config.
176+
/// - Parameters:
177+
/// - certificateChain: The certificates the server will offer during negotiation.
178+
/// - privateKey: The private key associated with the leaf certificate.
179+
/// - clientCertificateVerification: How to verify the client certificate, if one is presented.
180+
/// - trustRoots: The trust roots to be used when verifying client certificates.
181+
/// - requireALPN: Whether ALPN is required.
182+
public init(
183+
certificateChain: [TLSConfig.CertificateSource],
184+
privateKey: TLSConfig.PrivateKeySource,
185+
clientCertificateVerification: TLSConfig.CertificateVerification,
186+
trustRoots: TLSConfig.TrustRootsSource,
187+
requireALPN: Bool
188+
) {
189+
self.certificateChain = certificateChain
190+
self.privateKey = privateKey
191+
self.clientCertificateVerification = clientCertificateVerification
192+
self.trustRoots = trustRoots
193+
self.requireALPN = requireALPN
194+
}
195+
175196
/// Create a new HTTP2 NIO Posix transport TLS config, with some values defaulted:
176197
/// - `clientCertificateVerificationMode` equals `doNotVerify`
177198
/// - `trustRoots` equals `systemDefault`
@@ -180,18 +201,22 @@ extension HTTP2ServerTransport.Posix.Config {
180201
/// - Parameters:
181202
/// - certificateChain: The certificates the server will offer during negotiation.
182203
/// - privateKey: The private key associated with the leaf certificate.
204+
/// - configure: A closure which allows you to modify the defaults before returning them.
183205
/// - Returns: A new HTTP2 NIO Posix transport TLS config.
184206
public static func defaults(
185207
certificateChain: [TLSConfig.CertificateSource],
186-
privateKey: TLSConfig.PrivateKeySource
208+
privateKey: TLSConfig.PrivateKeySource,
209+
configure: (_ config: inout Self) -> Void = { _ in }
187210
) -> Self {
188-
Self(
211+
var config = Self(
189212
certificateChain: certificateChain,
190213
privateKey: privateKey,
191214
clientCertificateVerification: .noVerification,
192215
trustRoots: .systemDefault,
193216
requireALPN: false
194217
)
218+
configure(&config)
219+
return config
195220
}
196221

197222
/// Create a new HTTP2 NIO Posix transport TLS config, with some values defaulted to match
@@ -203,18 +228,22 @@ extension HTTP2ServerTransport.Posix.Config {
203228
/// - Parameters:
204229
/// - certificateChain: The certificates the server will offer during negotiation.
205230
/// - privateKey: The private key associated with the leaf certificate.
231+
/// - configure: A closure which allows you to modify the defaults before returning them.
206232
/// - Returns: A new HTTP2 NIO Posix transport TLS config.
207233
public static func mTLS(
208234
certificateChain: [TLSConfig.CertificateSource],
209-
privateKey: TLSConfig.PrivateKeySource
235+
privateKey: TLSConfig.PrivateKeySource,
236+
configure: (_ config: inout Self) -> Void = { _ in }
210237
) -> Self {
211-
Self(
238+
var config = Self(
212239
certificateChain: certificateChain,
213240
privateKey: privateKey,
214241
clientCertificateVerification: .noHostnameVerification,
215242
trustRoots: .systemDefault,
216243
requireALPN: false
217244
)
245+
configure(&config)
246+
return config
218247
}
219248
}
220249
}
@@ -256,42 +285,85 @@ extension HTTP2ClientTransport.Posix.Config {
256285
/// An optional server hostname to use when verifying certificates.
257286
public var serverHostname: String?
258287

288+
/// Create a new HTTP2 NIO Posix client transport TLS config.
289+
/// - Parameters:
290+
/// - certificateChain: The certificates the client will offer during negotiation.
291+
/// - privateKey: The private key associated with the leaf certificate.
292+
/// - serverCertificateVerification: How to verify the server certificate, if one is presented.
293+
/// - trustRoots: The trust roots to be used when verifying server certificates.
294+
/// - serverHostname: An optional server hostname to use when verifying certificates.
295+
public init(
296+
certificateChain: [TLSConfig.CertificateSource],
297+
privateKey: TLSConfig.PrivateKeySource?,
298+
serverCertificateVerification: TLSConfig.CertificateVerification,
299+
trustRoots: TLSConfig.TrustRootsSource,
300+
serverHostname: String?
301+
) {
302+
self.certificateChain = certificateChain
303+
self.privateKey = privateKey
304+
self.serverCertificateVerification = serverCertificateVerification
305+
self.trustRoots = trustRoots
306+
self.serverHostname = serverHostname
307+
}
308+
259309
/// Create a new HTTP2 NIO Posix transport TLS config, with some values defaulted:
260310
/// - `certificateChain` equals `[]`
261311
/// - `privateKey` equals `nil`
262312
/// - `serverCertificateVerification` equals `fullVerification`
263313
/// - `trustRoots` equals `systemDefault`
264314
/// - `serverHostname` equals `nil`
265315
///
316+
/// - Parameters:
317+
/// - configure: A closure which allows you to modify the defaults before returning them.
266318
/// - Returns: A new HTTP2 NIO Posix transport TLS config.
267-
public static var defaults: Self {
268-
Self(
319+
public static func defaults(
320+
configure: (_ config: inout Self) -> Void = { _ in }
321+
) -> Self {
322+
var config = Self(
269323
certificateChain: [],
270324
privateKey: nil,
271325
serverCertificateVerification: .fullVerification,
272326
trustRoots: .systemDefault,
273327
serverHostname: nil
274328
)
329+
configure(&config)
330+
return config
331+
}
332+
333+
/// Create a new HTTP2 NIO Posix transport TLS config, with some values defaulted:
334+
/// - `certificateChain` equals `[]`
335+
/// - `privateKey` equals `nil`
336+
/// - `serverCertificateVerification` equals `fullVerification`
337+
/// - `trustRoots` equals `systemDefault`
338+
/// - `serverHostname` equals `nil`
339+
public static var defaults: Self {
340+
Self.defaults()
275341
}
276342

277343
/// Create a new HTTP2 NIO Posix transport TLS config, with some values defaulted to match
278344
/// the requirements of mTLS:
279345
/// - `trustRoots` equals `systemDefault`
346+
/// - `serverCertificateVerification` equals `fullVerification`
280347
///
281348
/// - Parameters:
282349
/// - certificateChain: The certificates the client will offer during negotiation.
283350
/// - privateKey: The private key associated with the leaf certificate.
351+
/// - configure: A closure which allows you to modify the defaults before returning them.
284352
/// - Returns: A new HTTP2 NIO Posix transport TLS config.
285353
public static func mTLS(
286354
certificateChain: [TLSConfig.CertificateSource],
287-
privateKey: TLSConfig.PrivateKeySource
355+
privateKey: TLSConfig.PrivateKeySource,
356+
configure: (_ config: inout Self) -> Void = { _ in }
288357
) -> Self {
289-
Self(
358+
var config = Self(
290359
certificateChain: certificateChain,
291360
privateKey: privateKey,
292361
serverCertificateVerification: .fullVerification,
293-
trustRoots: .systemDefault
362+
trustRoots: .systemDefault,
363+
serverHostname: nil
294364
)
365+
configure(&config)
366+
return config
295367
}
296368
}
297369
}

Sources/GRPCNIOTransportHTTP2TransportServices/TLSConfig.swift

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,26 @@ extension HTTP2ServerTransport.TransportServices.Config {
4545
/// If this is set to `true` but the client does not support ALPN, then the connection will be rejected.
4646
public var requireALPN: Bool
4747

48+
/// Create a new HTTP2 NIO Transport Services transport TLS config.
49+
/// - Parameters:
50+
/// - requireALPN: Whether ALPN is required.
51+
/// - identityProvider: A provider for the `SecIdentity` to be used when setting up TLS.
52+
public init(
53+
requireALPN: Bool,
54+
identityProvider: @Sendable @escaping () throws -> SecIdentity
55+
) {
56+
self.requireALPN = requireALPN
57+
self.identityProvider = identityProvider
58+
}
59+
4860
/// Create a new HTTP2 NIO Transport Services transport TLS config, with some values defaulted:
4961
/// - `requireALPN` equals `false`
5062
///
5163
/// - Returns: A new HTTP2 NIO Transport Services transport TLS config.
5264
public static func defaults(
5365
identityProvider: @Sendable @escaping () throws -> SecIdentity
5466
) -> Self {
55-
Self(
56-
identityProvider: identityProvider,
57-
requireALPN: false
58-
)
67+
Self(requireALPN: false, identityProvider: identityProvider)
5968
}
6069
}
6170
}

0 commit comments

Comments
 (0)