@@ -18,7 +18,7 @@ import Foundation
18
18
import GRPCCore
19
19
import GRPCNIOTransportHTTP2Posix
20
20
import GRPCNIOTransportHTTP2TransportServices
21
- import NIO
21
+ import NIOCore
22
22
import NIOSSL
23
23
import SwiftASN1
24
24
import Testing
@@ -192,15 +192,18 @@ struct HTTP2TransportTLSEnabledTests {
192
192
func testRPC_mTLS_customVerificationCallback_OK( ) async throws {
193
193
// Create a new certificate chain that has 4 certificate/key pairs: root, intermediate, client, server
194
194
let certificateChain = try CertificateChain ( )
195
+ let certificatesExpectedInCallback = [ certificateChain. client. certificate]
195
196
let filePaths = try certificateChain. writeToTemp ( )
197
+
196
198
let clientConfig = self . makeMTLSClientConfig (
197
199
certificatePath: filePaths. clientCert,
198
200
keyPath: filePaths. clientKey,
199
201
trustRootsPath: filePaths. trustRoots,
200
202
serverHostname: CertificateChain . serverName
201
203
)
202
- let expectedCertificates = [ certificateChain. client. certificate]
203
- try await confirmation { confirmation in
204
+
205
+ // The confirmation lets us check that the callback is used.
206
+ try await confirmation ( expectedCount: 1 ) { confirmation in
204
207
let serverConfig = self . makeMTLSServerConfigWithCallback (
205
208
certificatePath: filePaths. serverCert,
206
209
keyPath: filePaths. serverKey,
@@ -209,12 +212,15 @@ struct HTTP2TransportTLSEnabledTests {
209
212
let presentedCertificates = certificates. map {
210
213
try ! Certificate ( derEncoded: $0. toDERBytes ( ) )
211
214
}
212
- #expect( expectedCertificates == presentedCertificates)
215
+ #expect( certificatesExpectedInCallback == presentedCertificates)
216
+ // "Verify" the chain and set the certificate.
213
217
promise. succeed (
214
218
. certificateVerified( VerificationMetadata ( ValidatedCertificateChain ( certificates) ) )
215
219
)
220
+ // This should be called once.
216
221
confirmation. confirm ( )
217
222
}
223
+
218
224
// Run the test
219
225
try await self . withClientAndServer (
220
226
clientConfig: clientConfig,
@@ -234,14 +240,17 @@ struct HTTP2TransportTLSEnabledTests {
234
240
{
235
241
// Create a new certificate chain that has 4 certificate/key pairs: root, intermediate, client, server
236
242
let certificateChain = try CertificateChain ( )
243
+ let certificatesExpectedInCallback = [ certificateChain. client. certificate]
237
244
let filePaths = try certificateChain. writeToTemp ( )
245
+
238
246
let clientConfig = self . makeMTLSClientConfig (
239
247
certificatePath: filePaths. clientCert,
240
248
keyPath: filePaths. clientKey,
241
249
trustRootsPath: filePaths. trustRoots,
242
250
serverHostname: CertificateChain . serverName
243
251
)
244
- let expectedCertificates = [ certificateChain. client. certificate]
252
+
253
+ // The confirmation lets us check that the callback is not used.
245
254
try await confirmation ( expectedCount: 0 ) { confirmation in
246
255
let serverConfig = self . makeMTLSServerConfigWithCallback (
247
256
certificatePath: filePaths. serverCert,
@@ -252,13 +261,15 @@ struct HTTP2TransportTLSEnabledTests {
252
261
let presentedCertificates = certificates. map {
253
262
try ! Certificate ( derEncoded: $0. toDERBytes ( ) )
254
263
}
255
- #expect( expectedCertificates == presentedCertificates)
264
+ #expect( certificatesExpectedInCallback == presentedCertificates)
265
+ // "Verify" the chain and set the certificate.
256
266
promise. succeed (
257
267
. certificateVerified( VerificationMetadata ( ValidatedCertificateChain ( certificates) ) )
258
268
)
259
- // We expect this never to be called. The call count should stay at 0.
269
+ // We expect this never to be called.
260
270
confirmation ( )
261
271
}
272
+
262
273
// Run the test
263
274
try await self . withClientAndServer (
264
275
clientConfig: clientConfig,
@@ -277,14 +288,17 @@ struct HTTP2TransportTLSEnabledTests {
277
288
func testRPC_mTLS_customVerificationCallback_Failure( ) async throws {
278
289
// Create a new certificate chain that has 4 certificate/key pairs: root, intermediate, client, server
279
290
let certificateChain = try CertificateChain ( )
291
+ let certificatesExpectedInCallback = [ certificateChain. client. certificate]
280
292
let filePaths = try certificateChain. writeToTemp ( )
293
+
281
294
let clientConfig = self . makeMTLSClientConfig (
282
295
certificatePath: filePaths. clientCert,
283
296
keyPath: filePaths. clientKey,
284
297
trustRootsPath: filePaths. trustRoots,
285
298
serverHostname: CertificateChain . serverName
286
299
)
287
- let expectedCertificates = [ certificateChain. client. certificate]
300
+
301
+ // The confirmation lets us check that the callback is used.
288
302
await confirmation { confirmation in
289
303
let serverConfig = self . makeMTLSServerConfigWithCallback (
290
304
certificatePath: filePaths. serverCert,
@@ -294,11 +308,12 @@ struct HTTP2TransportTLSEnabledTests {
294
308
let presentedCertificates = certificates. map {
295
309
try ! Certificate ( derEncoded: $0. toDERBytes ( ) )
296
310
}
297
- #expect( expectedCertificates == presentedCertificates)
311
+ #expect( certificatesExpectedInCallback == presentedCertificates)
298
312
// We are failing the certificate check here by propagating ".failed"!
299
313
promise. succeed ( . failed)
300
314
confirmation. confirm ( )
301
315
}
316
+
302
317
// Run the test
303
318
await #expect {
304
319
try await self . withClientAndServer (
@@ -308,13 +323,15 @@ struct HTTP2TransportTLSEnabledTests {
308
323
try await self . executeUnaryRPC ( control: control)
309
324
}
310
325
} throws: { error in
326
+ // Check root error ...
311
327
let rootError = try #require( error as? RPCError )
312
328
#expect( rootError. code == . unavailable)
313
-
314
329
#expect(
315
330
rootError. message
316
331
== " The server accepted the TCP connection but closed the connection before completing the HTTP/2 connection preface. "
317
332
)
333
+
334
+ // ... and the its cause.
318
335
let sslError = try #require( rootError. cause as? BoringSSLError )
319
336
switch sslError {
320
337
case . sslError:
0 commit comments