Skip to content

Commit

Permalink
oci/auth: Fix ImageRegistryProvider for repo root
Browse files Browse the repository at this point in the history
When a repository root is provided, ImageRegistryProvider() fails to
identify the registry host. The provided name.Reference for repository
root is a Tag reference.
name.ParseReference(), when parsing a registry root, assumes that that
given string is the name and registry host being empty defaults to
index.docker.io.

ImageRegistryProvider() now takes the full address, in addition to the
name.Reference and uses the full address for analysis if there's no "/"
in the address, which indicates that it's a repository root.

This fixes login with repository root for all the providers, not just
AWS.

Signed-off-by: Sunny <[email protected]>
  • Loading branch information
darkowlzz committed Dec 14, 2022
1 parent 2978355 commit ab7013d
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 11 deletions.
29 changes: 20 additions & 9 deletions oci/auth/login/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package login

import (
"context"
"strings"

"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
Expand All @@ -30,15 +31,25 @@ import (

// ImageRegistryProvider analyzes the provided registry and returns the identified
// container image registry provider.
func ImageRegistryProvider(ref name.Reference) oci.Provider {
_, _, ok := aws.ParseRegistry(ref.Context().RegistryStr())
func ImageRegistryProvider(url string, ref name.Reference) oci.Provider {
// If the url is a registry root address, use it to analyze. Else, derive
// the registry from the name reference.
// NOTE: This is because name.Reference of a registry root assumes that the
// reference is an image name and defaults to using index.docker.io as the
// registry host.
addr := strings.TrimSuffix(url, "/")
if strings.ContainsRune(addr, '/') {
addr = ref.Context().RegistryStr()
}

_, _, ok := aws.ParseRegistry(addr)
if ok {
return oci.ProviderAWS
}
if gcp.ValidHost(ref.Context().RegistryStr()) {
if gcp.ValidHost(addr) {
return oci.ProviderGCP
}
if azure.ValidHost(ref.Context().RegistryStr()) {
if azure.ValidHost(addr) {
return oci.ProviderAzure
}
return oci.ProviderGeneric
Expand Down Expand Up @@ -94,14 +105,14 @@ func (m *Manager) WithACRClient(c *azure.Client) *Manager {

// Login performs authentication against a registry and returns the
// authentication material. For generic registry provider, it is no-op.
func (m *Manager) Login(ctx context.Context, image string, ref name.Reference, opts ProviderOptions) (authn.Authenticator, error) {
switch ImageRegistryProvider(ref) {
func (m *Manager) Login(ctx context.Context, url string, ref name.Reference, opts ProviderOptions) (authn.Authenticator, error) {
switch ImageRegistryProvider(url, ref) {
case oci.ProviderAWS:
return m.ecr.Login(ctx, opts.AwsAutoLogin, image)
return m.ecr.Login(ctx, opts.AwsAutoLogin, url)
case oci.ProviderGCP:
return m.gcr.Login(ctx, opts.GcpAutoLogin, image, ref)
return m.gcr.Login(ctx, opts.GcpAutoLogin, url, ref)
case oci.ProviderAzure:
return m.acr.Login(ctx, opts.AzureAutoLogin, image, ref)
return m.acr.Login(ctx, opts.AzureAutoLogin, url, ref)
}
return nil, nil
}
11 changes: 9 additions & 2 deletions oci/auth/login/login_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"
"net/http"
"net/http/httptest"
"strings"
"testing"

awssdk "github.com/aws/aws-sdk-go-v2/aws"
Expand All @@ -40,18 +41,24 @@ func TestImageRegistryProvider(t *testing.T) {
want oci.Provider
}{
{"ecr", "012345678901.dkr.ecr.us-east-1.amazonaws.com/foo:v1", oci.ProviderAWS},
{"ecr-root", "012345678901.dkr.ecr.us-east-1.amazonaws.com", oci.ProviderAWS},
{"ecr-root with slash", "012345678901.dkr.ecr.us-east-1.amazonaws.com/", oci.ProviderAWS},
{"gcr", "gcr.io/foo/bar:v1", oci.ProviderGCP},
{"gcr-root", "gcr.io", oci.ProviderGCP},
{"acr", "foo.azurecr.io/bar:v1", oci.ProviderAzure},
{"acr-root", "foo.azurecr.io", oci.ProviderAzure},
{"docker.io", "foo/bar:v1", oci.ProviderGeneric},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)

ref, err := name.ParseReference(tt.image)
// Trim suffix to allow parsing it as reference without modifying
// the given image address.
ref, err := name.ParseReference(strings.TrimSuffix(tt.image, "/"))
g.Expect(err).ToNot(HaveOccurred())
g.Expect(ImageRegistryProvider(ref)).To(Equal(tt.want))
g.Expect(ImageRegistryProvider(tt.image, ref)).To(Equal(tt.want))
})
}
}
Expand Down

0 comments on commit ab7013d

Please sign in to comment.