@@ -42,32 +42,28 @@ extension KafkaConfiguration {
4242 }
4343 }
4444
45- public struct Root : Sendable , Hashable {
46- internal enum _Root : Sendable , Hashable {
45+ public struct TrustRoots : Sendable , Hashable {
46+ internal enum _TrustRoots : Sendable , Hashable {
4747 case probe
48- case disableBrokerVerification
4948 case file( location: String )
5049 case pem( String )
5150 }
5251
53- let _internal : _Root
52+ let _internal : _TrustRoots
5453
5554 /// A list of standard paths will be probed and the first one found will be used as the default root certificate location path.
56- public static let probe = Root ( _internal: . probe)
57-
58- /// Disable OpenSSL's built-in broker (server) certificate verification.
59- public static let disableBrokerVerification = Root ( _internal: . disableBrokerVerification)
55+ public static let probe = TrustRoots ( _internal: . probe)
6056
6157 /// File or directory path to root certificate(s) for verifying the broker's key.
62- public static func file( location: String ) -> Root {
63- return Root (
58+ public static func file( location: String ) -> TrustRoots {
59+ return TrustRoots (
6460 _internal: . file( location: location)
6561 )
6662 }
6763
68- /// Root certificate String for verifying the broker's key.
69- public static func pem( _ pem: String ) -> Root {
70- return Root (
64+ /// Trust roots certificate String for verifying the broker's key.
65+ public static func pem( _ pem: String ) -> TrustRoots {
66+ return TrustRoots (
7167 _internal: . pem( pem)
7268 )
7369 }
@@ -122,112 +118,134 @@ extension KafkaConfiguration {
122118 }
123119 }
124120
125- internal enum _TLSConfiguration : Sendable , Hashable {
126- case keyPair(
121+ /// Configuration for the TLS identity of the client.
122+ public struct ClientIdentity : Sendable , Hashable {
123+ internal enum _ClientIdentity : Sendable , Hashable {
124+ case keyPair(
125+ privateKey: PrivateKey ,
126+ certificates: LeafAndIntermediates
127+ )
128+ case keyStore( keyStore: KeyStore )
129+ }
130+
131+ let _internal : _ClientIdentity
132+
133+ /// Use TLS client verification with a given private/public key pair.
134+ ///
135+ /// - Parameters:
136+ /// - privateKey: The client's private key (PEM) used for authentication.
137+ /// - certificate: The client's public key (PEM) used for authentication.
138+ public static func keyPair(
127139 privateKey: PrivateKey ,
128- publicKeyCertificate: LeafAndIntermediates ,
129- caCertificate: Root ,
130- crlLocation: String ?
131- )
132- case keyStore(
133- keyStore: KeyStore ,
134- caCertificate: Root ,
135- crlLocation: String ?
136- )
140+ certificates: LeafAndIntermediates
141+ ) -> ClientIdentity {
142+ return . init(
143+ _internal: . keyPair(
144+ privateKey: privateKey,
145+ certificates: certificates
146+ )
147+ )
148+ }
149+
150+ /// Use TLS client verification with a given key store.
151+ ///
152+ /// - Parameters:
153+ /// - keyStore: The client's keystore (PKCS#12) used for authentication.
154+ public static func keyStore( keyStore: KeyStore ) -> ClientIdentity {
155+ return . init( _internal: . keyStore( keyStore: keyStore) )
156+ }
137157 }
138158
139- let _internal : _TLSConfiguration
140-
141- /// Use TLS with a given private/public key pair.
142- ///
143- /// - Parameters:
144- ///
145- /// - privateKey: The client's private key (PEM) used for authentication.
146- /// - publicKeyCertificate: The client's public key (PEM) used for authentication.
147- /// - caCertificate: File or directory path to CA certificate(s) for verifying the broker's key.
148- /// - crLocation: Path to CRL for verifying broker's certificate validity.
149- public static func keyPair(
150- privateKey: PrivateKey ,
151- publicKeyCertificate: LeafAndIntermediates ,
152- caCertificate: Root = . probe,
153- crlLocation: String ?
154- ) -> TLSConfiguration {
155- return TLSConfiguration (
156- _internal: . keyPair(
157- privateKey: privateKey,
158- publicKeyCertificate: publicKeyCertificate,
159- caCertificate: caCertificate,
160- crlLocation: crlLocation
159+ /// Configuration for the TLS verification of the broker.
160+ public struct BrokerVerification : Sendable , Hashable {
161+ internal enum _BrokerVerification : Sendable , Hashable {
162+ case disabled
163+ case verify(
164+ trustRoots: TrustRoots ,
165+ certificateRevocationListPath: String ?
161166 )
162- )
163- }
167+ }
168+
169+ let _internal : _BrokerVerification
170+
171+ /// Do not verify the identity of the broker.
172+ public static let disabled : BrokerVerification = . init( _internal: . disabled)
164173
165- ///
166- /// - Parameters:
167- ///
168- /// - keyStore: The client's keystore (PKCS#12) used for authentication.
169- /// - caCertificate: File or directory path to CA certificate(s) for verifying the broker's key.
170- /// - crlLocation: Path to CRL for verifying broker's certificate validity.
171- public static func keyStore(
172- keyStore: KeyStore ,
173- caCertificate: Root = . probe,
174- crlLocation: String ?
175- ) -> TLSConfiguration {
176- return TLSConfiguration (
177- _internal: . keyStore(
178- keyStore: keyStore,
179- caCertificate: caCertificate,
180- crlLocation: crlLocation
174+ /// Verify the identity of the broker.
175+ ///
176+ /// Parameters:
177+ /// - trustRoots: File or directory path to CA certificate(s) for verifying the broker's key.
178+ /// - certificateRevocationListPath: Path to CRL for verifying broker's certificate validity.
179+ public static func verify(
180+ trustRoots: TrustRoots = . probe,
181+ certificateRevocationListPath: String ? = nil
182+ ) -> BrokerVerification {
183+ return . init(
184+ _internal: . verify(
185+ trustRoots: trustRoots,
186+ certificateRevocationListPath: certificateRevocationListPath
187+ )
181188 )
182- )
189+ }
183190 }
184191
192+ /// Configuration for the TLS verification of the client.
193+ /// Default: `nil`
194+ public var clientIdentity : ClientIdentity ? = nil
195+
196+ /// Configuration for the TLS verification of the broker.
197+ /// Default: `verify(trustRoots: .probe, certificateRevocationListPath: nil)``
198+ public var brokerVerification : BrokerVerification = . verify(
199+ trustRoots: . probe,
200+ certificateRevocationListPath: nil
201+ )
202+
203+ public init ( ) { }
204+
185205 // MARK: TLSConfiguration + Dictionary
186206
187207 internal var dictionary : [ String : String ] {
188208 var resultDict : [ String : String ] = [ : ]
189209
190- switch self . _internal {
191- case . keyPair( let privateKey, let publicKeyCertificate, let caCertificate, let crlLocation) :
210+ // Client TLS Verification
211+ switch self . clientIdentity? . _internal {
212+ case . none:
213+ break
214+ case . keyPair( let privateKey, let certificate) :
192215 switch privateKey. key. _internal {
193216 case . file( location: let location) :
194217 resultDict [ " ssl.key.location " ] = location
195218 case . pem( let pem) :
196219 resultDict [ " ssl.key.pem " ] = pem
197220 }
198221 resultDict [ " ssl.key.password " ] = privateKey. password
199- switch publicKeyCertificate . _internal {
222+ switch certificate . _internal {
200223 case . file( location: let location) :
201224 resultDict [ " ssl.key.location " ] = location
202225 resultDict [ " ssl.certificate.location " ] = location
203226 case . pem( let pem) :
204227 resultDict [ " ssl.certificate.pem " ] = pem
205228 }
206- switch caCertificate. _internal {
207- case . disableBrokerVerification:
208- resultDict [ " enable.ssl.certificate.verification " ] = String ( false )
209- case . probe:
210- resultDict [ " ssl.ca.location " ] = " probe "
211- case . file( location: let location) :
212- resultDict [ " ssl.ca.location " ] = location
213- case . pem( let pem) :
214- resultDict [ " ssl.ca.pem " ] = pem
215- }
216- resultDict [ " ssl.crl.location " ] = crlLocation
217- case . keyStore( let keyStore, let caCertificate, let crlLocation) :
229+ case . keyStore( let keyStore) :
218230 resultDict [ " ssl.keystore.location " ] = keyStore. location
219231 resultDict [ " ssl.keystore.password " ] = keyStore. password
220- switch caCertificate. _internal {
221- case . disableBrokerVerification:
222- resultDict [ " enable.ssl.certificate.verification " ] = String ( false )
232+ }
233+
234+ // Broker TLS Verification
235+ switch self . brokerVerification. _internal {
236+ case . disabled:
237+ resultDict [ " enable.ssl.certificate.verification " ] = String ( false )
238+ case . verify( let trustRoots, let certificateRevocationListPath) :
239+ resultDict [ " enable.ssl.certificate.verification " ] = String ( true )
240+ switch trustRoots. _internal {
223241 case . probe:
224242 resultDict [ " ssl.ca.location " ] = " probe "
225243 case . file( location: let location) :
226244 resultDict [ " ssl.ca.location " ] = location
227245 case . pem( let pem) :
228246 resultDict [ " ssl.ca.pem " ] = pem
229247 }
230- resultDict [ " ssl.crl.location " ] = crlLocation
248+ resultDict [ " ssl.crl.location " ] = certificateRevocationListPath
231249 }
232250
233251 return resultDict
@@ -277,7 +295,7 @@ extension KafkaConfiguration {
277295 }
278296
279297 /// Disable automatic key refresh by setting this property.
280- public static let disable : KeyRefreshAttempts = . init( rawValue: 0 )
298+ public static let disabled : KeyRefreshAttempts = . init( rawValue: 0 )
281299 }
282300
283301 /// Minimum time in between key refresh attempts.
@@ -311,7 +329,6 @@ extension KafkaConfiguration {
311329 /// Default OAuthBearer method.
312330 ///
313331 /// - Parameters:
314- ///
315332 /// - configuration: SASL/OAUTHBEARER configuration.
316333 /// The format is implementation-dependent and must be parsed accordingly.
317334 /// The default unsecured token implementation (see https://tools.ietf.org/html/rfc7515#appendix-A.5) recognizes space-separated name=value pairs with valid names including principalClaimName, principal, scopeClaimName, scope, and lifeSeconds.
@@ -327,7 +344,6 @@ extension KafkaConfiguration {
327344 /// OpenID Connect (OIDC).
328345 ///
329346 /// - Parameters:
330- ///
331347 /// - configuration: SASL/OAUTHBEARER configuration.
332348 /// The format is implementation-dependent and must be parsed accordingly.
333349 /// The default unsecured token implementation (see https://tools.ietf.org/html/rfc7515#appendix-A.5) recognizes space-separated name=value pairs with valid names including principalClaimName, principal, scopeClaimName, scope, and lifeSeconds.
@@ -481,7 +497,7 @@ extension KafkaConfiguration {
481497 )
482498
483499 /// Use the Transport Layer Security (TLS) protocol.
484- public static func tls( configuration: TLSConfiguration ) -> SecurityProtocol {
500+ public static func tls( configuration: TLSConfiguration = TLSConfiguration ( ) ) -> SecurityProtocol {
485501 return SecurityProtocol (
486502 _internal: . tls( configuration: configuration)
487503 )
@@ -497,7 +513,7 @@ extension KafkaConfiguration {
497513 /// Use the Simple Authentication and Security Layer (SASL) with TLS.
498514 public static func saslTLS(
499515 saslMechanism: SASLMechanism ,
500- tlsConfiguaration: TLSConfiguration
516+ tlsConfiguaration: TLSConfiguration = TLSConfiguration ( )
501517 ) -> SecurityProtocol {
502518 return SecurityProtocol (
503519 _internal: . saslTLS( saslMechanism: saslMechanism, tlsConfiguaration: tlsConfiguaration)
0 commit comments