Repository: google/go-containerregistry (go)

Issue:
Multiple scope generation with a base image got from an openshift registry fails
Hi,

I am using [kaniko](https://github.com/GoogleContainerTools/kaniko) and ended on [an issue with openshift registries](https://github.com/GoogleContainerTools/kaniko/issues/808).

Going deeper, I spotted this was due to the fact I use a internal docker proxy

Here is my `Dockerfile`

```
FROM docker-internal-proxy/busybox:1.31.0

....
```

The `push` fails when `kaniko` does the bearer request with the scopes it deduced from the `Layer` of the image in the [Write function](https://github.com/google/go-containerregistry/blob/50b26ee28691d22901fa3f55c52bdedf6c6a0be1/pkg/v1/remote/write.go#L55)


Indeed, given the above `Dockerfile`, it tries to authenticate with the given scopes:

- `repository:test-kaniko/test-kaniko:push,pull`
- `repository:busybox:pull` (unauthorized as it should have format `<repo>/<image>`)

If I use the following `Dockerfile` (without using the internal proxy

```
FROM busybox:1.31.0

....

```

It gives the scopes

- `repository:test-kaniko/test-kaniko:push,pull` 
- `repository:library/busybox:pull` (given image `busybox` url is resolved as `index.docker.io/library/busybox`)

I removed the sending of all `pull` scope (the one for the base image) and kaniko push works well 

My question: why are we sending also `pull` scope? If necessary, could we add for the write operation a fallback **without** the `pull` scopes deduced from the layers of the image ? Or even uniformizing the scopes to match the required format?

Thanks


Pull request:
Prevent asking pull scope for cross-repo mounting
@jonjohnsonjr As promised, I implemented the fix we discussed. I also added a test to enforce the implementation.

See #600 

Patch:
diff --git a/pkg/v1/remote/write.go b/pkg/v1/remote/write.go
index 6f84e54d..382d5ee3 100644
--- a/pkg/v1/remote/write.go
+++ b/pkg/v1/remote/write.go
@@ -412,9 +412,10 @@ func scopesForUploadingImage(ref name.Reference, layers []v1.Layer) []string {
 
 	for _, l := range layers {
 		if ml, ok := l.(*MountableLayer); ok {
-			// we add push scope for ref.Context() after the loop
-			if ml.Reference.Context() != ref.Context() {
-				scopeSet[ml.Reference.Context().Scope(transport.PullScope)] = struct{}{}
+			// we will add push scope for ref.Context() after the loop.
+			// for now we ask pull scope for references of the same registry
+			if ml.Reference.Context() != ref.Context() && ml.Reference.Context().Registry == ref.Context().Registry {
+				scopeSet[ml.Reference.Scope(transport.PullScope)] = struct{}{}
 			}
 		}
 	}


Test patch:
diff --git a/pkg/v1/remote/write_test.go b/pkg/v1/remote/write_test.go
index 09b82300..8ca72a37 100644
--- a/pkg/v1/remote/write_test.go
+++ b/pkg/v1/remote/write_test.go
@@ -907,6 +907,11 @@ func TestScopesForUploadingImage(t *testing.T) {
 		t.Fatalf("name.NewTag() = %v", err)
 	}
 
+	sameReference, err := name.NewTag("example.com/sample/sample:previous", name.WeakValidation)
+	if err != nil {
+		t.Fatalf("name.NewTag() = %v", err)
+	}
+
 	anotherRepo1, err := name.NewTag("example.com/sample/another_repo1:latest", name.WeakValidation)
 	if err != nil {
 		t.Fatalf("name.NewTag() = %v", err)
@@ -917,6 +922,11 @@ func TestScopesForUploadingImage(t *testing.T) {
 		t.Fatalf("name.NewTag() = %v", err)
 	}
 
+	repoOnOtherRegistry, err := name.NewTag("other-domain.com/sample/any_repo:latest", name.WeakValidation)
+	if err != nil {
+		t.Fatalf("name.NewTag() = %v", err)
+	}
+
 	img := setupImage(t)
 	layers, err := img.Layers()
 	if err != nil {
@@ -938,6 +948,19 @@ func TestScopesForUploadingImage(t *testing.T) {
 				referenceToUpload.Scope(transport.PushScope),
 			},
 		},
+		{
+			name:      "mountable layers with same reference",
+			reference: referenceToUpload,
+			layers:    []v1.Layer{
+				&MountableLayer{
+					Layer:     dummyLayer,
+					Reference: sameReference,
+				},
+			},
+			expected: []string{
+				referenceToUpload.Scope(transport.PushScope),
+			},
+		},
 		{
 			name:      "mountable layers with single reference with no-duplicate",
 			reference: referenceToUpload,
@@ -1016,6 +1039,19 @@ func TestScopesForUploadingImage(t *testing.T) {
 				anotherRepo2.Scope(transport.PullScope),
 			},
 		},
+		{
+			name:      "cross repository mountable layer",
+			reference: referenceToUpload,
+			layers: []v1.Layer{
+				&MountableLayer{
+					Layer:     dummyLayer,
+					Reference: repoOnOtherRegistry,
+				},
+			},
+			expected: []string{
+				referenceToUpload.Scope(transport.PushScope),
+			},
+		},
 	}
 
 	for _, tc := range testCases {