Skip to content

Commit c328b4f

Browse files
authored
Add support for mTLS (#22)
1 parent 94e2d08 commit c328b4f

File tree

3 files changed

+123
-7
lines changed

3 files changed

+123
-7
lines changed

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ let package = Package(
2828
.package(url: "https://github.com/apple/swift-log.git", from: "1.0.0"),
2929
.package(url: "https://github.com/apple/swift-nio.git", from: "2.0.0"),
3030
.package(url: "https://github.com/apple/swift-nio-ssl.git", from: "2.0.0"),
31-
.package(url: "https://github.com/apple/swift-nio-extras.git", from: "1.0.0"),
31+
.package(url: "https://github.com/apple/swift-nio-extras.git", from: "1.30.0"),
3232
.package(url: "https://github.com/apple/swift-nio-http2.git", from: "1.0.0"),
3333
],
3434
targets: [

Sources/HTTPServer/HTTPServer.swift

Lines changed: 87 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,41 @@ public final class Server<RequestHandler: HTTPServerRequestHandler> {
174174
logger: logger
175175
)
176176

177+
case .tls(let certificateChain, let privateKey):
178+
let http2Config = NIOHTTP2Handler.Configuration(
179+
httpServerHTTP2Configuration: configuration.http2
180+
)
181+
182+
let certificateChain = try certificateChain
183+
.map {
184+
try NIOSSLCertificate(
185+
bytes: $0.serializeAsPEM().derBytes,
186+
format: .der
187+
)
188+
}
189+
.map { NIOSSLCertificateSource.certificate($0) }
190+
let privateKey = NIOSSLPrivateKeySource.privateKey(
191+
try NIOSSLPrivateKey(
192+
bytes: privateKey.serializeAsPEM().derBytes,
193+
format: .der
194+
)
195+
)
196+
197+
var tlsConfiguration: TLSConfiguration = .makeServerConfiguration(
198+
certificateChain: certificateChain,
199+
privateKey: privateKey
200+
)
201+
tlsConfiguration.applicationProtocols = ["h2", "http/1.1"]
202+
203+
try await Self.serveSecureUpgrade(
204+
bindTarget: configuration.bindTarget,
205+
tlsConfiguration: tlsConfiguration,
206+
handler: handler,
207+
asyncChannelConfiguration: asyncChannelConfiguration,
208+
http2Configuration: http2Config,
209+
logger: logger
210+
)
211+
177212
case .reloadingTLS(let certificateReloader):
178213
let http2Config = NIOHTTP2Handler.Configuration(
179214
httpServerHTTP2Configuration: configuration.http2
@@ -193,7 +228,7 @@ public final class Server<RequestHandler: HTTPServerRequestHandler> {
193228
logger: logger
194229
)
195230

196-
case .staticTLS(let certificateChain, let privateKey):
231+
case .mTLS(let certificateChain, let privateKey, let trustRoots):
197232
let http2Config = NIOHTTP2Handler.Configuration(
198233
httpServerHTTP2Configuration: configuration.http2
199234
)
@@ -213,9 +248,58 @@ public final class Server<RequestHandler: HTTPServerRequestHandler> {
213248
)
214249
)
215250

216-
var tlsConfiguration: TLSConfiguration = .makeServerConfiguration(
251+
let nioTrustRoots: NIOSSLTrustRoots
252+
if let trustRoots {
253+
nioTrustRoots = .certificates(
254+
try trustRoots.map {
255+
try NIOSSLCertificate(
256+
bytes: $0.serializeAsPEM().derBytes,
257+
format: .der
258+
)
259+
}
260+
)
261+
} else {
262+
nioTrustRoots = .default
263+
}
264+
265+
var tlsConfiguration: TLSConfiguration = .makeServerConfigurationWithMTLS(
217266
certificateChain: certificateChain,
218-
privateKey: privateKey
267+
privateKey: privateKey,
268+
trustRoots: nioTrustRoots
269+
)
270+
tlsConfiguration.applicationProtocols = ["h2", "http/1.1"]
271+
272+
try await Self.serveSecureUpgrade(
273+
bindTarget: configuration.bindTarget,
274+
tlsConfiguration: tlsConfiguration,
275+
handler: handler,
276+
asyncChannelConfiguration: asyncChannelConfiguration,
277+
http2Configuration: http2Config,
278+
logger: logger
279+
)
280+
281+
case .reloadingMTLS(let certificateReloader, let trustRoots):
282+
let http2Config = NIOHTTP2Handler.Configuration(
283+
httpServerHTTP2Configuration: configuration.http2
284+
)
285+
286+
let nioTrustRoots: NIOSSLTrustRoots
287+
if let trustRoots {
288+
nioTrustRoots = .certificates(
289+
try trustRoots.map {
290+
try NIOSSLCertificate(
291+
bytes: $0.serializeAsPEM().derBytes,
292+
format: .der
293+
)
294+
}
295+
)
296+
} else {
297+
nioTrustRoots = .default
298+
}
299+
300+
var tlsConfiguration: TLSConfiguration = try .makeServerConfigurationWithMTLS(
301+
certificateReloader: certificateReloader,
302+
trustRoots: nioTrustRoots
219303
)
220304
tlsConfiguration.applicationProtocols = ["h2", "http/1.1"]
221305

Sources/HTTPServer/HTTPServerConfiguration.swift

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,20 @@ public struct HTTPServerConfiguration: Sendable {
4242
public struct TransportSecurity: Sendable {
4343
enum Backing {
4444
case plaintext
45-
case staticTLS(
45+
case tls(
4646
certificateChain: [Certificate],
4747
privateKey: Certificate.PrivateKey
4848
)
4949
case reloadingTLS(certificateReloader: any CertificateReloader)
50-
50+
case mTLS(
51+
certificateChain: [Certificate],
52+
privateKey: Certificate.PrivateKey,
53+
trustRoots: [Certificate]?
54+
)
55+
case reloadingMTLS(
56+
certificateReloader: any CertificateReloader,
57+
trustRoots: [Certificate]?
58+
)
5159
}
5260

5361
let backing: Backing
@@ -59,7 +67,7 @@ public struct HTTPServerConfiguration: Sendable {
5967
privateKey: Certificate.PrivateKey
6068
) -> Self {
6169
Self(
62-
backing: .staticTLS(
70+
backing: .tls(
6371
certificateChain: certificateChain,
6472
privateKey: privateKey
6573
)
@@ -69,6 +77,30 @@ public struct HTTPServerConfiguration: Sendable {
6977
public static func tls(certificateReloader: any CertificateReloader) throws -> Self {
7078
Self(backing: .reloadingTLS(certificateReloader: certificateReloader))
7179
}
80+
81+
public static func mTLS(
82+
certificateChain: [Certificate],
83+
privateKey: Certificate.PrivateKey,
84+
trustRoots: [Certificate]?
85+
) -> Self {
86+
Self(
87+
backing: .mTLS(
88+
certificateChain: certificateChain,
89+
privateKey: privateKey,
90+
trustRoots: trustRoots
91+
)
92+
)
93+
}
94+
95+
public static func mTLS(
96+
certificateReloader: any CertificateReloader,
97+
trustRoots: [Certificate]?
98+
) throws -> Self {
99+
Self(backing: .reloadingMTLS(
100+
certificateReloader: certificateReloader,
101+
trustRoots: trustRoots
102+
))
103+
}
72104
}
73105

74106
/// HTTP/2 specific configuration.

0 commit comments

Comments
 (0)