Skip to content

Commit 24cb15c

Browse files
authored
Support certificate chains from single PEM in TimedCertificateReloader (#273)
## Motivation The new `TimedCertificateReloader` currently only supports loading PEM files with a single cert. It is often the case that a single PEM file contains an entire certificate chain. ## Modification Modifies the code to support loading an entire certificate chain from a single PEM file. ## Result PEM based certificate chain support in our new `TimedCertificateReloader`
1 parent 72a23ea commit 24cb15c

File tree

2 files changed

+177
-39
lines changed

2 files changed

+177
-39
lines changed

Sources/NIOCertificateReloading/TimedCertificateReloader.swift

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ public struct TimedCertificateReloader: CertificateReloader {
247247
}
248248

249249
private struct CertificateKeyPair {
250-
var certificate: NIOSSLCertificateSource
250+
var certificates: [NIOSSLCertificateSource]
251251
var privateKey: NIOSSLPrivateKeySource
252252
}
253253

@@ -270,7 +270,7 @@ public struct TimedCertificateReloader: CertificateReloader {
270270
return .noChanges
271271
}
272272
var override = NIOSSLContextConfigurationOverride()
273-
override.certificateChain = [certificateKeyPair.certificate]
273+
override.certificateChain = certificateKeyPair.certificates
274274
override.privateKey = certificateKeyPair.privateKey
275275
return override
276276
}
@@ -350,11 +350,12 @@ public struct TimedCertificateReloader: CertificateReloader {
350350
public func reload() throws {
351351
let certificateBytes = try self.loadCertificate()
352352
let keyBytes = try self.loadPrivateKey()
353-
if let certificate = try self.parseCertificate(from: certificateBytes),
353+
if let certificates = try self.parseCertificates(from: certificateBytes),
354354
let key = try self.parsePrivateKey(from: keyBytes),
355-
key.publicKey.isValidSignature(certificate.signature, for: certificate)
355+
let firstCertificate = certificates.first,
356+
key.publicKey.isValidSignature(firstCertificate.signature, for: firstCertificate)
356357
{
357-
try self.attemptToUpdatePair(certificate: certificate, key: key)
358+
try self.attemptToUpdatePair(certificates: certificates, key: key)
358359
}
359360
}
360361

@@ -388,17 +389,17 @@ public struct TimedCertificateReloader: CertificateReloader {
388389
return keyBytes
389390
}
390391

391-
private func parseCertificate(from certificateBytes: [UInt8]) throws -> Certificate? {
392-
let certificate: Certificate?
392+
private func parseCertificates(from certificateBytes: [UInt8]) throws -> [Certificate]? {
393+
let certificates: [Certificate]?
393394
switch self.certificateSource.format._backing {
394395
case .der:
395-
certificate = try Certificate(derEncoded: certificateBytes)
396+
certificates = [try Certificate(derEncoded: certificateBytes)]
396397

397398
case .pem:
398-
certificate = try String(bytes: certificateBytes, encoding: .utf8)
399-
.flatMap { try Certificate(pemEncoded: $0) }
399+
certificates = try String(bytes: certificateBytes, encoding: .utf8)
400+
.flatMap { try PEMDocument.parseMultiple(pemString: $0).map { try Certificate(pemDocument: $0) } }
400401
}
401-
return certificate
402+
return certificates
402403
}
403404

404405
private func parsePrivateKey(from keyBytes: [UInt8]) throws -> Certificate.PrivateKey? {
@@ -414,18 +415,22 @@ public struct TimedCertificateReloader: CertificateReloader {
414415
return key
415416
}
416417

417-
private func attemptToUpdatePair(certificate: Certificate, key: Certificate.PrivateKey) throws {
418-
let nioSSLCertificate = try NIOSSLCertificate(
419-
bytes: certificate.serializeAsPEM().derBytes,
420-
format: .der
421-
)
418+
private func attemptToUpdatePair(certificates: [Certificate], key: Certificate.PrivateKey) throws {
419+
let nioSSLCertificates =
420+
try certificates
421+
.map {
422+
try NIOSSLCertificate(
423+
bytes: $0.serializeAsPEM().derBytes,
424+
format: .der
425+
)
426+
}
422427
let nioSSLPrivateKey = try NIOSSLPrivateKey(
423428
bytes: key.serializeAsPEM().derBytes,
424429
format: .der
425430
)
426431
self.state.withLockedValue {
427432
$0 = CertificateKeyPair(
428-
certificate: .certificate(nioSSLCertificate),
433+
certificates: nioSSLCertificates.map { .certificate($0) },
429434
privateKey: .privateKey(nioSSLPrivateKey)
430435
)
431436
}

0 commit comments

Comments
 (0)