| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- /*
- * Copyright 2025, gRPC Authors All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- internal import GRPCCore
- package import GRPCNIOTransportCore
- internal import NIOCertificateReloading
- internal import NIOSSL
- @available(gRPCSwiftNIOTransport 2.0, *)
- extension NIOSSLSerializationFormats {
- fileprivate init(_ format: TLSConfig.SerializationFormat) {
- switch format.wrapped {
- case .pem:
- self = .pem
- case .der:
- self = .der
- }
- }
- }
- @available(gRPCSwiftNIOTransport 2.0, *)
- extension Sequence<TLSConfig.CertificateSource> {
- func sslCertificateSources() throws -> [NIOSSLCertificateSource] {
- var certificateSources: [NIOSSLCertificateSource] = []
- for source in self {
- switch source.wrapped {
- case .bytes(let bytes, let serializationFormat):
- switch serializationFormat.wrapped {
- case .der:
- certificateSources.append(
- .certificate(try NIOSSLCertificate(bytes: bytes, format: .der))
- )
- case .pem:
- let certificates = try NIOSSLCertificate.fromPEMBytes(bytes).map {
- NIOSSLCertificateSource.certificate($0)
- }
- certificateSources.append(contentsOf: certificates)
- }
- case .file(let path, let serializationFormat):
- switch serializationFormat.wrapped {
- case .der:
- try certificateSources.append(.certificate(NIOSSLCertificate.fromDERFile(path)))
- case .pem:
- let certificates = try NIOSSLCertificate.fromPEMFile(path).map {
- NIOSSLCertificateSource.certificate($0)
- }
- certificateSources.append(contentsOf: certificates)
- }
- case .transportSpecific(let specific):
- if let source = specific.wrapped as? NIOSSLCertificateSource {
- certificateSources.append(source)
- } else {
- fatalError("Invalid certificate source of type \(type(of: specific.wrapped))")
- }
- }
- }
- return certificateSources
- }
- }
- @available(gRPCSwiftNIOTransport 2.0, *)
- extension TLSConfig.PrivateKeySource {
- enum _NIOSSLPrivateKeySource: TransportSpecific {
- case customPrivateKey(any (NIOSSLCustomPrivateKey & Hashable))
- case privateKey(NIOSSLPrivateKeySource)
- }
- static func nioSSLSpecific(_ source: _NIOSSLPrivateKeySource) -> Self {
- .transportSpecific(source)
- }
- }
- @available(gRPCSwiftNIOTransport 2.0, *)
- extension NIOSSLPrivateKey {
- fileprivate static func makePrivateKey(
- from source: TLSConfig.PrivateKeySource
- ) throws -> NIOSSLPrivateKey {
- switch source.wrapped {
- case .file(let path, let serializationFormat):
- return try self.init(
- file: path,
- format: NIOSSLSerializationFormats(serializationFormat)
- )
- case .bytes(let bytes, let serializationFormat):
- return try self.init(
- bytes: bytes,
- format: NIOSSLSerializationFormats(serializationFormat)
- )
- case .transportSpecific(let extraSource):
- guard let source = extraSource as? TLSConfig.PrivateKeySource._NIOSSLPrivateKeySource else {
- fatalError("Invalid private key source of type \(type(of: extraSource))")
- }
- switch source {
- case .customPrivateKey(let privateKey):
- return self.init(customPrivateKey: privateKey)
- case .privateKey(.privateKey(let key)):
- return key
- case .privateKey(.file(let path)):
- switch path.split(separator: ".").last {
- case "pem":
- return try NIOSSLPrivateKey(file: path, format: .pem)
- case "der", "key":
- return try NIOSSLPrivateKey(file: path, format: .der)
- default:
- throw RPCError(
- code: .invalidArgument,
- message: "Couldn't load private key from \(path)."
- )
- }
- }
- }
- }
- }
- @available(gRPCSwiftNIOTransport 2.0, *)
- extension NIOSSLTrustRoots {
- fileprivate init(_ trustRoots: TLSConfig.TrustRootsSource) throws {
- switch trustRoots.wrapped {
- case .certificates(let certificateSources):
- var certificates: [NIOSSLCertificate] = []
- for source in certificateSources {
- switch source.wrapped {
- case .bytes(let bytes, let serializationFormat):
- switch serializationFormat.wrapped {
- case .pem:
- certificates.append(contentsOf: try NIOSSLCertificate.fromPEMBytes(bytes))
- case .der:
- certificates.append(try NIOSSLCertificate(bytes: bytes, format: .der))
- }
- case .file(let path, let serializationFormat):
- switch serializationFormat.wrapped {
- case .pem:
- certificates.append(contentsOf: try NIOSSLCertificate.fromPEMFile(path))
- case .der:
- certificates.append(try NIOSSLCertificate.fromDERFile(path))
- }
- case .transportSpecific(let specific):
- guard let source = specific.wrapped as? NIOSSLCertificateSource else {
- fatalError("Invalid certificate source of type \(type(of: specific.wrapped))")
- }
- switch source {
- case .certificate(let certificate):
- certificates.append(certificate)
- case .file(let path):
- switch path.split(separator: ".").last {
- case "pem":
- certificates.append(contentsOf: try NIOSSLCertificate.fromPEMFile(path))
- case "der":
- certificates.append(try NIOSSLCertificate.fromDERFile(path))
- default:
- throw RPCError(
- code: .invalidArgument,
- message: "Couldn't load certificate from \(path)."
- )
- }
- }
- }
- }
- self = .certificates(certificates)
- case .systemDefault:
- self = .default
- }
- }
- }
- @available(gRPCSwiftNIOTransport 2.0, *)
- extension CertificateVerification {
- fileprivate init(
- _ verificationMode: TLSConfig.CertificateVerification
- ) {
- switch verificationMode.wrapped {
- case .doNotVerify:
- self = .none
- case .fullVerification:
- self = .fullVerification
- case .noHostnameVerification:
- self = .noHostnameVerification
- }
- }
- }
- @available(gRPCSwiftNIOTransport 2.0, *)
- extension TLSConfiguration {
- package init(_ tlsConfig: HTTP2ServerTransport.Posix.TransportSecurity.TLS) throws {
- let certificateChain = try tlsConfig.certificateChain.sslCertificateSources()
- let privateKey = try NIOSSLPrivateKey.makePrivateKey(from: tlsConfig.privateKey)
- self = TLSConfiguration.makeServerConfiguration(
- certificateChain: certificateChain,
- privateKey: .privateKey(privateKey)
- )
- self.minimumTLSVersion = .tlsv12
- self.certificateVerification = CertificateVerification(tlsConfig.clientCertificateVerification)
- self.trustRoots = try NIOSSLTrustRoots(tlsConfig.trustRoots)
- self.applicationProtocols = ["grpc-exp", "h2"]
- if let reloader = tlsConfig.certificateReloader {
- self.setCertificateReloader(reloader)
- }
- }
- package init(_ tlsConfig: HTTP2ClientTransport.Posix.TransportSecurity.TLS) throws {
- self = TLSConfiguration.makeClientConfiguration()
- self.certificateChain = try tlsConfig.certificateChain.sslCertificateSources()
- if let privateKey = tlsConfig.privateKey {
- let privateKeySource = try NIOSSLPrivateKey.makePrivateKey(from: privateKey)
- self.privateKey = .privateKey(privateKeySource)
- }
- self.minimumTLSVersion = .tlsv12
- self.certificateVerification = CertificateVerification(tlsConfig.serverCertificateVerification)
- self.trustRoots = try NIOSSLTrustRoots(tlsConfig.trustRoots)
- self.applicationProtocols = ["grpc-exp", "h2"]
- if let reloader = tlsConfig.certificateReloader {
- self.setCertificateReloader(reloader)
- }
- }
- }
|