Skip to content

Commit 6cf78b3

Browse files
committed
feat(registry): Add custom ca certificate override
1 parent cfe4fd7 commit 6cf78b3

File tree

7 files changed

+49
-12
lines changed

7 files changed

+49
-12
lines changed

Package.resolved

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ let package = Package(
4646
.package(url: "https://github.com/swift-server/async-http-client.git", from: "1.20.1"),
4747
.package(url: "https://github.com/apple/swift-system.git", from: "1.4.0"),
4848
.package(url: "https://github.com/swiftlang/swift-docc-plugin", from: "1.1.0"),
49+
.package(url: "https://github.com/apple/swift-nio-ssl.git", from: "2.36.0"),
4950
],
5051
targets: [
5152
.target(
@@ -228,6 +229,8 @@ let package = Package(
228229
"ContainerizationError",
229230
.product(name: "Collections", package: "swift-collections"),
230231
.product(name: "Logging", package: "swift-log"),
232+
.product(name: "NIOSSL", package: "swift-nio-ssl"),
233+
231234
]
232235
),
233236
.testTarget(

Sources/Containerization/Image/ImageStore/ImageStore.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ extension ImageStore {
196196
) async throws -> Image {
197197

198198
let matcher = createPlatformMatcher(for: platform)
199-
let client = try RegistryClient(reference: reference, insecure: insecure, auth: auth)
199+
let client = try RegistryClient(reference: reference, insecure: insecure, auth: auth, tlsConfiguration: TLSUtils.makeEnvironmentAwareTLSConfiguration())
200200

201201
let ref = try Reference.parse(reference)
202202
let name = ref.path
@@ -248,7 +248,7 @@ extension ImageStore {
248248
guard let tag = ref.tag ?? ref.digest else {
249249
throw ContainerizationError(.invalidArgument, message: "Invalid tag/digest for image reference \(reference)")
250250
}
251-
let client = try RegistryClient(reference: reference, insecure: insecure, auth: auth)
251+
let client = try RegistryClient(reference: reference, insecure: insecure, auth: auth, tlsConfiguration: TLSUtils.makeEnvironmentAwareTLSConfiguration())
252252
let operation = ExportOperation(name: name, tag: tag, contentStore: self.contentStore, client: client, progress: progress)
253253
try await operation.export(index: img.descriptor, platforms: matcher)
254254
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
import NIO
3+
import NIOSSL
4+
import Foundation
5+
6+
7+
public enum TLSUtils {
8+
9+
public static func makeEnvironmentAwareTLSConfiguration() -> TLSConfiguration {
10+
var tlsConfig = TLSConfiguration.makeClientConfiguration()
11+
12+
// Check standard SSL environment variables in priority order
13+
let customCAPath =
14+
ProcessInfo.processInfo.environment["SSL_CERT_FILE"]
15+
?? ProcessInfo.processInfo.environment["CURL_CA_BUNDLE"]
16+
?? ProcessInfo.processInfo.environment["REQUESTS_CA_BUNDLE"]
17+
18+
if let caPath = customCAPath {
19+
tlsConfig.trustRoots = .file(caPath)
20+
}
21+
// else: use .default
22+
23+
return tlsConfig
24+
}
25+
}

Sources/ContainerizationOCI/Client/RegistryClient.swift

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import Foundation
2222
import Logging
2323
import NIO
2424
import NIOHTTP1
25+
import NIOSSL
2526

2627
#if os(macOS)
2728
import Network
@@ -66,7 +67,8 @@ public final class RegistryClient: ContentClient {
6667
reference: String,
6768
insecure: Bool = false,
6869
auth: Authentication? = nil,
69-
logger: Logger? = nil
70+
logger: Logger? = nil,
71+
tlsConfiguration: TLSConfiguration? = nil,
7072
) throws {
7173
let ref = try Reference.parse(reference)
7274
guard let domain = ref.resolvedDomain else {
@@ -86,7 +88,8 @@ public final class RegistryClient: ContentClient {
8688
scheme: scheme,
8789
port: port,
8890
authentication: auth,
89-
retryOptions: Self.defaultRetryOptions
91+
retryOptions: Self.defaultRetryOptions,
92+
tlsConfiguration: tlsConfiguration,
9093
)
9194
}
9295

@@ -98,7 +101,8 @@ public final class RegistryClient: ContentClient {
98101
clientID: String? = nil,
99102
retryOptions: RetryOptions? = nil,
100103
bufferSize: Int = Int(4.mib()),
101-
logger: Logger? = nil
104+
logger: Logger? = nil,
105+
tlsConfiguration: TLSConfiguration? = nil,
102106
) {
103107
var components = URLComponents()
104108
components.scheme = scheme
@@ -118,6 +122,9 @@ public final class RegistryClient: ContentClient {
118122
let proxyPort = proxyURL.port ?? (proxyURL.scheme == "https" ? 443 : 80)
119123
httpConfiguration.proxy = HTTPClient.Configuration.Proxy.server(host: proxyHost, port: proxyPort)
120124
}
125+
if tlsConfiguration != nil {
126+
httpConfiguration.tlsConfiguration = tlsConfiguration
127+
}
121128

122129
if let logger {
123130
self.client = HTTPClient(eventLoopGroupProvider: .singleton, configuration: httpConfiguration, backgroundActivityLogger: logger)

Sources/cctl/LoginCommand.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import ArgumentParser
1818
import Containerization
1919
import ContainerizationError
2020
import ContainerizationOCI
21+
import ContainerizationExtras
2122
import Foundation
2223

2324
extension Application {
@@ -74,7 +75,8 @@ extension Application {
7475
shouldRetry: ({ response in
7576
response.status.code >= 500
7677
})
77-
)
78+
),
79+
tlsConfiguration: TLSUtils.makeEnvironmentAwareTLSConfiguration(),
7880
)
7981
try await client.ping()
8082
try keychain.save(domain: server, username: username, password: password)

vminitd/Package.resolved

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)