Config+TLS.swift 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /*
  2. * Copyright 2024, gRPC Authors All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. public import NIOSSL
  17. extension HTTP2ServerTransport.Posix {
  18. /// The security configuration for this connection.
  19. public struct TransportSecurity: Sendable {
  20. package enum Wrapped: Sendable {
  21. case plaintext
  22. case tls(TLS)
  23. }
  24. package let wrapped: Wrapped
  25. /// This connection is plaintext: no encryption will take place.
  26. public static let plaintext = Self(wrapped: .plaintext)
  27. /// Secure connections with the given TLS configuration.
  28. public static func tls(_ tls: TLS) -> Self {
  29. Self(wrapped: .tls(tls))
  30. }
  31. /// Secure connections with TLS.
  32. ///
  33. /// - Parameters:
  34. /// - certificateChain: The certificates the server will offer during negotiation.
  35. /// - privateKey: The private key associated with the leaf certificate.
  36. /// - configure: A closure which allows you to modify the defaults before returning them.
  37. public static func tls(
  38. certificateChain: [TLSConfig.CertificateSource],
  39. privateKey: TLSConfig.PrivateKeySource,
  40. configure: (_ config: inout TLS) -> Void = { _ in }
  41. ) -> Self {
  42. let tlsConfig: TLS = .defaults(
  43. certificateChain: certificateChain,
  44. privateKey: privateKey,
  45. configure: configure
  46. )
  47. return .tls(tlsConfig)
  48. }
  49. /// Secure the connection with mutual TLS.
  50. ///
  51. /// - Parameters:
  52. /// - certificateChain: The certificates the client will offer during negotiation.
  53. /// - privateKey: The private key associated with the leaf certificate.
  54. /// - configure: A closure which allows you to modify the defaults before returning them.
  55. public static func mTLS(
  56. certificateChain: [TLSConfig.CertificateSource],
  57. privateKey: TLSConfig.PrivateKeySource,
  58. configure: (_ config: inout TLS) -> Void = { _ in }
  59. ) -> Self {
  60. let tlsConfig: TLS = .mTLS(
  61. certificateChain: certificateChain,
  62. privateKey: privateKey,
  63. configure: configure
  64. )
  65. return .tls(tlsConfig)
  66. }
  67. }
  68. }
  69. extension HTTP2ServerTransport.Posix.TransportSecurity {
  70. public struct TLS: Sendable {
  71. /// The certificates the server will offer during negotiation.
  72. public var certificateChain: [TLSConfig.CertificateSource]
  73. /// The private key associated with the leaf certificate.
  74. public var privateKey: TLSConfig.PrivateKeySource
  75. /// How to verify the client certificate, if one is presented.
  76. public var clientCertificateVerification: TLSConfig.CertificateVerification
  77. /// The trust roots to be used when verifying client certificates.
  78. public var trustRoots: TLSConfig.TrustRootsSource
  79. /// Whether ALPN is required.
  80. ///
  81. /// If this is set to `true` but the client does not support ALPN, then the connection will be rejected.
  82. public var requireALPN: Bool
  83. /// Create a new HTTP2 NIO Posix server transport TLS config.
  84. /// - Parameters:
  85. /// - certificateChain: The certificates the server will offer during negotiation.
  86. /// - privateKey: The private key associated with the leaf certificate.
  87. /// - clientCertificateVerification: How to verify the client certificate, if one is presented.
  88. /// - trustRoots: The trust roots to be used when verifying client certificates.
  89. /// - requireALPN: Whether ALPN is required.
  90. public init(
  91. certificateChain: [TLSConfig.CertificateSource],
  92. privateKey: TLSConfig.PrivateKeySource,
  93. clientCertificateVerification: TLSConfig.CertificateVerification,
  94. trustRoots: TLSConfig.TrustRootsSource,
  95. requireALPN: Bool
  96. ) {
  97. self.certificateChain = certificateChain
  98. self.privateKey = privateKey
  99. self.clientCertificateVerification = clientCertificateVerification
  100. self.trustRoots = trustRoots
  101. self.requireALPN = requireALPN
  102. }
  103. /// Create a new HTTP2 NIO Posix transport TLS config, with some values defaulted:
  104. /// - `clientCertificateVerificationMode` equals `doNotVerify`
  105. /// - `trustRoots` equals `systemDefault`
  106. /// - `requireALPN` equals `false`
  107. ///
  108. /// - Parameters:
  109. /// - certificateChain: The certificates the server will offer during negotiation.
  110. /// - privateKey: The private key associated with the leaf certificate.
  111. /// - configure: A closure which allows you to modify the defaults before returning them.
  112. /// - Returns: A new HTTP2 NIO Posix transport TLS config.
  113. public static func defaults(
  114. certificateChain: [TLSConfig.CertificateSource],
  115. privateKey: TLSConfig.PrivateKeySource,
  116. configure: (_ config: inout Self) -> Void = { _ in }
  117. ) -> Self {
  118. var config = Self(
  119. certificateChain: certificateChain,
  120. privateKey: privateKey,
  121. clientCertificateVerification: .noVerification,
  122. trustRoots: .systemDefault,
  123. requireALPN: false
  124. )
  125. configure(&config)
  126. return config
  127. }
  128. /// Create a new HTTP2 NIO Posix transport TLS config, with some values defaulted to match
  129. /// the requirements of mTLS:
  130. /// - `clientCertificateVerificationMode` equals `noHostnameVerification`
  131. /// - `trustRoots` equals `systemDefault`
  132. /// - `requireALPN` equals `false`
  133. ///
  134. /// - Parameters:
  135. /// - certificateChain: The certificates the server will offer during negotiation.
  136. /// - privateKey: The private key associated with the leaf certificate.
  137. /// - configure: A closure which allows you to modify the defaults before returning them.
  138. /// - Returns: A new HTTP2 NIO Posix transport TLS config.
  139. public static func mTLS(
  140. certificateChain: [TLSConfig.CertificateSource],
  141. privateKey: TLSConfig.PrivateKeySource,
  142. configure: (_ config: inout Self) -> Void = { _ in }
  143. ) -> Self {
  144. var config = Self(
  145. certificateChain: certificateChain,
  146. privateKey: privateKey,
  147. clientCertificateVerification: .noHostnameVerification,
  148. trustRoots: .systemDefault,
  149. requireALPN: false
  150. )
  151. configure(&config)
  152. return config
  153. }
  154. }
  155. }
  156. extension HTTP2ClientTransport.Posix {
  157. /// The security configuration for this connection.
  158. public struct TransportSecurity: Sendable {
  159. package enum Wrapped: Sendable {
  160. case plaintext
  161. case tls(TLS)
  162. }
  163. package let wrapped: Wrapped
  164. /// This connection is plaintext: no encryption will take place.
  165. public static let plaintext = Self(wrapped: .plaintext)
  166. /// Secure the connection with the given TLS configuration.
  167. public static func tls(_ tls: TLS) -> Self {
  168. Self(wrapped: .tls(tls))
  169. }
  170. /// Secure the connection with TLS using the default configuration.
  171. ///
  172. /// - Parameters:
  173. /// - configure: A closure which allows you to modify the defaults before returning them.
  174. public static func tls(
  175. configure: (_ config: inout TLS) -> Void = { _ in }
  176. ) -> Self {
  177. Self.tls(.defaults(configure: configure))
  178. }
  179. /// Secure the connection with TLS using the default configuration.
  180. public static var tls: Self {
  181. Self.tls(.defaults())
  182. }
  183. /// Secure the connection with mutual TLS.
  184. ///
  185. /// - Parameters:
  186. /// - certificateChain: The certificates the client will offer during negotiation.
  187. /// - privateKey: The private key associated with the leaf certificate.
  188. /// - configure: A closure which allows you to modify the defaults before returning them.
  189. public static func mTLS(
  190. certificateChain: [TLSConfig.CertificateSource],
  191. privateKey: TLSConfig.PrivateKeySource,
  192. configure: (_ config: inout TLS) -> Void = { _ in }
  193. ) -> Self {
  194. let tlsConfig: TLS = .mTLS(
  195. certificateChain: certificateChain,
  196. privateKey: privateKey,
  197. configure: configure
  198. )
  199. return .tls(tlsConfig)
  200. }
  201. }
  202. }
  203. extension HTTP2ClientTransport.Posix.TransportSecurity {
  204. public struct TLS: Sendable {
  205. /// The certificates the client will offer during negotiation.
  206. public var certificateChain: [TLSConfig.CertificateSource]
  207. /// The private key associated with the leaf certificate.
  208. public var privateKey: TLSConfig.PrivateKeySource?
  209. /// How to verify the server certificate, if one is presented.
  210. public var serverCertificateVerification: TLSConfig.CertificateVerification
  211. /// The trust roots to be used when verifying server certificates.
  212. public var trustRoots: TLSConfig.TrustRootsSource
  213. /// Create a new HTTP2 NIO Posix client transport TLS config.
  214. /// - Parameters:
  215. /// - certificateChain: The certificates the client will offer during negotiation.
  216. /// - privateKey: The private key associated with the leaf certificate.
  217. /// - serverCertificateVerification: How to verify the server certificate, if one is presented.
  218. /// - trustRoots: The trust roots to be used when verifying server certificates.
  219. public init(
  220. certificateChain: [TLSConfig.CertificateSource],
  221. privateKey: TLSConfig.PrivateKeySource?,
  222. serverCertificateVerification: TLSConfig.CertificateVerification,
  223. trustRoots: TLSConfig.TrustRootsSource
  224. ) {
  225. self.certificateChain = certificateChain
  226. self.privateKey = privateKey
  227. self.serverCertificateVerification = serverCertificateVerification
  228. self.trustRoots = trustRoots
  229. }
  230. /// Create a new HTTP2 NIO Posix transport TLS config, with some values defaulted:
  231. /// - `certificateChain` equals `[]`
  232. /// - `privateKey` equals `nil`
  233. /// - `serverCertificateVerification` equals `fullVerification`
  234. /// - `trustRoots` equals `systemDefault`
  235. ///
  236. /// - Parameters:
  237. /// - configure: A closure which allows you to modify the defaults before returning them.
  238. /// - Returns: A new HTTP2 NIO Posix transport TLS config.
  239. public static func defaults(
  240. configure: (_ config: inout Self) -> Void = { _ in }
  241. ) -> Self {
  242. var config = Self(
  243. certificateChain: [],
  244. privateKey: nil,
  245. serverCertificateVerification: .fullVerification,
  246. trustRoots: .systemDefault
  247. )
  248. configure(&config)
  249. return config
  250. }
  251. /// Create a new HTTP2 NIO Posix transport TLS config, with some values defaulted:
  252. /// - `certificateChain` equals `[]`
  253. /// - `privateKey` equals `nil`
  254. /// - `serverCertificateVerification` equals `fullVerification`
  255. /// - `trustRoots` equals `systemDefault`
  256. public static var defaults: Self { .defaults() }
  257. /// Create a new HTTP2 NIO Posix transport TLS config, with some values defaulted to match
  258. /// the requirements of mTLS:
  259. /// - `trustRoots` equals `systemDefault`
  260. /// - `serverCertificateVerification` equals `fullVerification`
  261. ///
  262. /// - Parameters:
  263. /// - certificateChain: The certificates the client will offer during negotiation.
  264. /// - privateKey: The private key associated with the leaf certificate.
  265. /// - configure: A closure which allows you to modify the defaults before returning them.
  266. /// - Returns: A new HTTP2 NIO Posix transport TLS config.
  267. public static func mTLS(
  268. certificateChain: [TLSConfig.CertificateSource],
  269. privateKey: TLSConfig.PrivateKeySource,
  270. configure: (_ config: inout Self) -> Void = { _ in }
  271. ) -> Self {
  272. var config = Self(
  273. certificateChain: certificateChain,
  274. privateKey: privateKey,
  275. serverCertificateVerification: .fullVerification,
  276. trustRoots: .systemDefault
  277. )
  278. configure(&config)
  279. return config
  280. }
  281. }
  282. }
  283. extension TLSConfig.PrivateKeySource {
  284. /// Creates a key source from a `NIOSSLCustomPrivateKey`.
  285. ///
  286. /// This private key source is only applicable to the NIOPosix based transports. Using one
  287. /// with a NIOTransportServices based transport is a programmer error.
  288. ///
  289. /// - Parameter key: The custom private key.
  290. /// - Returns: A private key source wrapping the custom private key.
  291. public static func customPrivateKey(_ key: any (NIOSSLCustomPrivateKey & Hashable)) -> Self {
  292. .nioSSLSpecific(.customPrivateKey(key))
  293. }
  294. }