From 4a196b6dc26f1ef25f0165fe36cd1693481bcd77 Mon Sep 17 00:00:00 2001 From: Alexey Makhov Date: Tue, 17 Jun 2025 18:26:46 +0300 Subject: [PATCH] Adds some context to fetchToken errors (#129) Fixes https://github.com/apple/container/issues/182 and https://github.com/apple/container/issues/183 Signed-off-by: Alexey --- .../Client/RegistryClient.swift | 25 ++++++++++++++----- .../RegistryClientTests.swift | 7 +++--- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/Sources/ContainerizationOCI/Client/RegistryClient.swift b/Sources/ContainerizationOCI/Client/RegistryClient.swift index 6c897e23..679155cb 100644 --- a/Sources/ContainerizationOCI/Client/RegistryClient.swift +++ b/Sources/ContainerizationOCI/Client/RegistryClient.swift @@ -184,13 +184,26 @@ public final class RegistryClient: ContentClient { if let ct = currentToken, ct.isValid(scope: tokenRequest.scope) { break } - let _currentToken = try await fetchToken(request: tokenRequest) - guard let token = _currentToken.getToken() else { - throw ContainerizationError(.internalError, message: "Failed to fetch Bearer token") + + do { + let _currentToken = try await fetchToken(request: tokenRequest) + guard let token = _currentToken.getToken() else { + throw ContainerizationError(.internalError, message: "Failed to fetch Bearer token") + } + currentToken = _currentToken + request.headers.replaceOrAdd(name: "Authorization", value: token) + retryCount += 1 + } catch let err as RegistryClient.Error { + guard case .invalidStatus(_, let status, _) = err else { + throw err + } + if status == .unauthorized || status == .forbidden { + throw RegistryClient.Error.invalidStatus(url: path, _response.status, reason: "Access denied or wrong credentials") + } + + throw err } - currentToken = _currentToken - request.headers.replaceOrAdd(name: "Authorization", value: token) - retryCount += 1 + continue } guard let retryOptions = self.retryOptions else { diff --git a/Tests/ContainerizationOCITests/RegistryClientTests.swift b/Tests/ContainerizationOCITests/RegistryClientTests.swift index a9ebf19d..401ce701 100644 --- a/Tests/ContainerizationOCITests/RegistryClientTests.swift +++ b/Tests/ContainerizationOCITests/RegistryClientTests.swift @@ -81,10 +81,11 @@ struct OCIClientTests: ~Copyable { let authentication = BasicAuthentication(username: "foo", password: "bar") let client = RegistryClient(host: "ghcr.io", authentication: authentication) let error = await #expect(throws: RegistryClient.Error.self) { try await client.ping() } - if case .invalidStatus = error { - } else { - Issue.record("encountered unexpected error \(error)") + guard case .invalidStatus(_, let status, let reason) = error else { + throw error! } + #expect(status == .unauthorized) + #expect(reason == "Access denied or wrong credentials") } @Test(.enabled(if: hasRegistryCredentials))