From 483ad69da3e3fb9ac885962d50834ff8619733a2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pawe=C5=82=20Gronowski?= <pawel.gronowski@docker.com>
Date: Thu, 27 Apr 2023 19:31:50 +0200
Subject: [PATCH] registry/errors: Parse http forbidden as denied
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
(cherry picked from commit 5f1df02149bf03f93cd7747ad740a38891fd4b20)
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
---
 registry/client/errors.go      |  2 ++
 registry/client/errors_test.go | 15 +++++++++++++++
 2 files changed, 17 insertions(+)

diff --git a/registry/client/errors.go b/registry/client/errors.go
index 52d49d5d2..024df43dd 100644
--- a/registry/client/errors.go
+++ b/registry/client/errors.go
@@ -55,6 +55,8 @@ func parseHTTPErrorResponse(statusCode int, r io.Reader) error {
 		switch statusCode {
 		case http.StatusUnauthorized:
 			return errcode.ErrorCodeUnauthorized.WithMessage(detailsErr.Details)
+		case http.StatusForbidden:
+			return errcode.ErrorCodeDenied.WithMessage(detailsErr.Details)
 		case http.StatusTooManyRequests:
 			return errcode.ErrorCodeTooManyRequests.WithMessage(detailsErr.Details)
 		default:
diff --git a/registry/client/errors_test.go b/registry/client/errors_test.go
index ca9dddd10..6be399d03 100644
--- a/registry/client/errors_test.go
+++ b/registry/client/errors_test.go
@@ -102,3 +102,18 @@ func TestHandleErrorResponseUnexpectedStatusCode501(t *testing.T) {
 		t.Errorf("Expected \"%s\", got: \"%s\"", expectedMsg, err.Error())
 	}
 }
+
+func TestHandleErrorResponseInsufficientPrivileges403(t *testing.T) {
+	json := `{"details":"requesting higher privileges than access token allows"}`
+	response := &http.Response{
+		Status:     "403 Forbidden",
+		StatusCode: 403,
+		Body:       nopCloser{bytes.NewBufferString(json)},
+	}
+	err := HandleErrorResponse(response)
+
+	expectedMsg := "denied: requesting higher privileges than access token allows"
+	if !strings.Contains(err.Error(), expectedMsg) {
+		t.Errorf("Expected \"%s\", got: \"%s\"", expectedMsg, err.Error())
+	}
+}