diff --git a/Sources/tart/Credentials/HelperProgramCredentialsProvider.swift b/Sources/tart/Credentials/DockerConfigCredentialsProvider.swift similarity index 72% rename from Sources/tart/Credentials/HelperProgramCredentialsProvider.swift rename to Sources/tart/Credentials/DockerConfigCredentialsProvider.swift index 1a58b46..e32ed34 100644 --- a/Sources/tart/Credentials/HelperProgramCredentialsProvider.swift +++ b/Sources/tart/Credentials/DockerConfigCredentialsProvider.swift @@ -1,6 +1,6 @@ import Foundation -class HelperProgramCredentialsProvider: CredentialsProvider { +class DockerConfigCredentialsProvider: CredentialsProvider { func retrieve(host: String) throws -> (String, String)? { let dockerConfigURL = FileManager.default.homeDirectoryForCurrentUser.appendingPathComponent(".docker").appendingPathComponent("config.json") if !FileManager.default.fileExists(atPath: dockerConfigURL.path) { @@ -8,6 +8,9 @@ class HelperProgramCredentialsProvider: CredentialsProvider { } let config = try JSONDecoder().decode(DockerConfig.self, from: Data(contentsOf: dockerConfigURL)) + if let credentialsFromAuth = config.auths?[host]?.decodeCredentials() { + return credentialsFromAuth + } if let helperProgram = config.credHelpers?[host] { return try executeHelper(binaryName: "docker-credential-\(helperProgram)", host: host) } @@ -54,9 +57,31 @@ class HelperProgramCredentialsProvider: CredentialsProvider { } struct DockerConfig: Codable { + var auths: Dictionary? = Dictionary() var credHelpers: Dictionary? = Dictionary() } +struct DockerAuthConfig: Codable { + var auth: String? = nil + + func decodeCredentials() -> (String, String)? { + // auth is a base64("username:password") + guard let authBase64 = auth else { + return nil + } + guard let data = Data(base64Encoded: authBase64) else { + return nil + } + guard let components = String(data: data, encoding: .utf8)?.components(separatedBy: ":") else { + return nil + } + if components.count != 2 { + return nil + } + return (components[0], components[1]) + } +} + struct DockerGetOutput: Codable { var Username: String var Secret: String diff --git a/Sources/tart/OCI/Registry.swift b/Sources/tart/OCI/Registry.swift index 812bf55..ca359b4 100644 --- a/Sources/tart/OCI/Registry.swift +++ b/Sources/tart/OCI/Registry.swift @@ -94,7 +94,7 @@ class Registry { init(urlComponents: URLComponents, namespace: String, - credentialsProviders: [CredentialsProvider] = [HelperProgramCredentialsProvider(), KeychainCredentialsProvider()] + credentialsProviders: [CredentialsProvider] = [DockerConfigCredentialsProvider(), KeychainCredentialsProvider()] ) throws { baseURL = urlComponents.url! self.namespace = namespace @@ -105,7 +105,7 @@ class Registry { host: String, namespace: String, insecure: Bool = false, - credentialsProviders: [CredentialsProvider] = [HelperProgramCredentialsProvider(), KeychainCredentialsProvider()] + credentialsProviders: [CredentialsProvider] = [DockerConfigCredentialsProvider(), KeychainCredentialsProvider()] ) throws { let proto = insecure ? "http" : "https" let baseURLComponents = URLComponents(string: proto + "://" + host + "/v2/")!