Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for CI that cannot load p12 files #409

Merged
merged 1 commit into from Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion Sources/Hummingbird/Server/RequestID.swift
Expand Up @@ -15,7 +15,7 @@
import Atomics

/// Generate Unique ID for each request
public struct RequestID: CustomStringConvertible {
public struct RequestID: CustomStringConvertible, Sendable {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't know why but the compiler only just started complaining about this now, but it is a valid complaint

let low: UInt64

public init() {
Expand Down
30 changes: 23 additions & 7 deletions Sources/HummingbirdCore/Server/TSTLSOptions.swift
Expand Up @@ -15,21 +15,28 @@
#if canImport(Network)
import Foundation
import Network
import Security

/// Wrapper for NIO transport services TLS options
public struct TSTLSOptions: Sendable {
struct Error: Swift.Error, Equatable {
public struct Error: Swift.Error, Equatable {
enum _Internal: Equatable {
case invalidFormat
case interactionNotAllowed
case verificationFailed
}

private let value: _Internal
init(_ value: _Internal) {
self.value = value
}

// static invalid conversion
static var invalidFormat: Self { .init(.invalidFormat) }
// invalid format
public static var invalidFormat: Self { .init(.invalidFormat) }
// unable to import p12 as no interaction is allowed
public static var interactionNotAllowed: Self { .init(.interactionNotAllowed) }
// MAC verification failed during PKCS12 import (wrong password?)
public static var verificationFailed: Self { .init(.verificationFailed) }
}

public struct Identity {
Expand All @@ -40,16 +47,25 @@ public struct TSTLSOptions: Sendable {
}

public static func p12(filename: String, password: String) throws -> Self {
guard let secIdentity = Self.loadP12(filename: filename, password: password) else { throw Error.invalidFormat }
guard let secIdentity = try Self.loadP12(filename: filename, password: password) else { throw Error.invalidFormat }
return .init(secIdentity: secIdentity)
}

private static func loadP12(filename: String, password: String) -> SecIdentity? {
guard let data = try? Data(contentsOf: URL(fileURLWithPath: filename)) else { return nil }
private static func loadP12(filename: String, password: String) throws -> SecIdentity? {
let data = try Data(contentsOf: URL(fileURLWithPath: filename))
let options: [String: String] = [kSecImportExportPassphrase as String: password]
var rawItems: CFArray?
let result = SecPKCS12Import(data as CFData, options as CFDictionary, &rawItems)
guard result == errSecSuccess else { return nil }
switch result {
case errSecSuccess:
break
case errSecInteractionNotAllowed:
throw Error.interactionNotAllowed
case errSecPkcs12VerifyFailure:
throw Error.verificationFailed
default:
throw Error.invalidFormat
}
let items = rawItems! as! [[String: Any]]
let firstItem = items[0]
return firstItem[kSecImportItemIdentity as String] as! SecIdentity?
Expand Down
10 changes: 7 additions & 3 deletions Tests/HummingbirdCoreTests/TSTests.swift
Expand Up @@ -48,9 +48,13 @@ class TransportServicesTests: XCTestCase {
func testTLS() async throws {
let eventLoopGroup = NIOTSEventLoopGroup()
let p12Path = Bundle.module.path(forResource: "server", ofType: "p12")!
let tlsOptions = try XCTUnwrap(TSTLSOptions.options(
serverIdentity: .p12(filename: p12Path, password: "HBTests")
))
let tlsOptions: TSTLSOptions
do {
let identity = try TSTLSOptions.Identity.p12(filename: p12Path, password: "HBTests")
tlsOptions = try XCTUnwrap(TSTLSOptions.options(serverIdentity: identity))
} catch let error as TSTLSOptions.Error where error == .interactionNotAllowed {
throw XCTSkip("Unable to import PKCS12 bundle: no interaction allowed")
}
try await testServer(
responder: helloResponder,
configuration: .init(address: .hostname(port: 0), serverName: testServerName, tlsOptions: tlsOptions),
Expand Down