diff --git a/cmd/hub/main.go b/cmd/hub/main.go index aacaeee9..14b0fbae 100644 --- a/cmd/hub/main.go +++ b/cmd/hub/main.go @@ -72,7 +72,7 @@ func main() { ImageStore: pg.NewImageStore(cfg, db, hc), Authorizer: az, HTTPClient: hc, - OCIPuller: &oci.Puller{}, + OCIPuller: oci.NewPuller(cfg), ViewsTracker: vt, } h, err := handlers.Setup(ctx, cfg, hSvc) diff --git a/cmd/tracker/main.go b/cmd/tracker/main.go index 379da98a..4bbbb80c 100644 --- a/cmd/tracker/main.go +++ b/cmd/tracker/main.go @@ -82,7 +82,7 @@ func main() { Oe: &repo.OLMOCIExporter{}, Ec: ec, Hc: hc, - Op: &oci.Puller{}, + Op: oci.NewPuller(cfg), Is: is, SetupTrackerSource: tracker.SetupSource, } diff --git a/internal/oci/oci.go b/internal/oci/oci.go index 98f497cb..4250ac9c 100644 --- a/internal/oci/oci.go +++ b/internal/oci/oci.go @@ -15,6 +15,7 @@ import ( ocispec "github.com/opencontainers/image-spec/specs-go/v1" csremote "github.com/sigstore/cosign/pkg/oci/remote" "github.com/sigstore/cosign/pkg/types" + "github.com/spf13/viper" "oras.land/oras-go/pkg/content" ctxo "oras.land/oras-go/pkg/context" "oras.land/oras-go/pkg/oras" @@ -31,18 +32,31 @@ var ( ) // Puller is a hub.OCIPuller implementation. -type Puller struct{} +type Puller struct { + cfg *viper.Viper +} + +// NewPuller creates a new Puller instance. +func NewPuller(cfg *viper.Viper) *Puller { + return &Puller{ + cfg: cfg, + } +} // PullLayer pulls the first layer of the media type provided from the OCI // artifact at the given reference. func (p *Puller) PullLayer( ctx context.Context, - ref, + imageRef, mediaType, username, password string, ) (ocispec.Descriptor, []byte, error) { // Pull layers available at the ref provided + ref, err := name.ParseReference(imageRef) + if err != nil { + return ocispec.Descriptor{}, nil, err + } resolverOptions := docker.ResolverOptions{} if username != "" || password != "" { resolverOptions.Authorizer = docker.NewDockerAuthorizer( @@ -50,14 +64,20 @@ func (p *Puller) PullLayer( return username, password, nil }), ) + } else if p.cfg != nil && strings.HasSuffix(ref.Context().Registry.Name(), "docker.io") { + resolverOptions.Authorizer = docker.NewDockerAuthorizer( + docker.WithAuthCreds(func(string) (string, string, error) { + return p.cfg.GetString("creds.dockerUsername"), p.cfg.GetString("creds.dockerPassword"), nil + }), + ) } registryStore := content.Registry{Resolver: docker.NewResolver(resolverOptions)} memoryStore := content.NewMemory() var layers []ocispec.Descriptor - _, err := oras.Copy( + _, err = oras.Copy( ctxo.WithLoggerDiscarded(ctx), registryStore, - ref, + ref.String(), memoryStore, "", oras.WithPullEmptyNameAllowed(), @@ -84,7 +104,16 @@ func (p *Puller) PullLayer( } // SignatureChecker is a hub.OCISignatureChecker implementation. -type SignatureChecker struct{} +type SignatureChecker struct { + op hub.OCIPuller +} + +// NewSignatureChecker creates a new Puller instance. +func NewSignatureChecker(op hub.OCIPuller) *SignatureChecker { + return &SignatureChecker{ + op: op, + } +} // HasCosignSignature checks if the OCI artifact identified by the reference // provided has a cosign (sigstore) signature. @@ -105,8 +134,7 @@ func (c *SignatureChecker) HasCosignSignature( } // Check if the OCI artifact exists and contains a signature layer - p := &Puller{} - _, _, err = p.PullLayer(ctx, signatureRef.String(), types.SimpleSigningMediaType, username, password) + _, _, err = c.op.PullLayer(ctx, signatureRef.String(), types.SimpleSigningMediaType, username, password) if err != nil { if errors.Is(err, ErrArtifactNotFound) || errors.Is(err, ErrLayerNotFound) { return false, nil diff --git a/internal/repo/manager.go b/internal/repo/manager.go index 87ab63aa..f2c6b451 100644 --- a/internal/repo/manager.go +++ b/internal/repo/manager.go @@ -120,7 +120,7 @@ func NewManager( db: db, il: &HelmIndexLoader{}, tg: &oci.TagsGetter{}, - op: &oci.Puller{}, + op: oci.NewPuller(cfg), az: az, hc: hc, } diff --git a/internal/tracker/helpers_test.go b/internal/tracker/helpers_test.go index 4b037589..4b36d89e 100644 --- a/internal/tracker/helpers_test.go +++ b/internal/tracker/helpers_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/artifacthub/hub/internal/hub" + "github.com/artifacthub/hub/internal/oci" "github.com/artifacthub/hub/internal/repo" "github.com/artifacthub/hub/internal/tests" "github.com/spf13/viper" @@ -235,6 +236,9 @@ func TestSetupSource(t *testing.T) { i := &hub.TrackerSourceInput{ Repository: tc.r, + Svc: &hub.TrackerSourceServices{ + Op: &oci.PullerMock{}, + }, } source := SetupSource(i) assert.Equal(t, tc.expectedType, reflect.TypeOf(source).String()) diff --git a/internal/tracker/source/container/container.go b/internal/tracker/source/container/container.go index f38ffb7e..50cb43a3 100644 --- a/internal/tracker/source/container/container.go +++ b/internal/tracker/source/container/container.go @@ -91,7 +91,7 @@ func NewTrackerSource(i *hub.TrackerSourceInput, opts ...func(s *TrackerSource)) o(s) } if s.sc == nil { - s.sc = &oci.SignatureChecker{} + s.sc = oci.NewSignatureChecker(i.Svc.Op) } return s } diff --git a/internal/tracker/source/helm/helm.go b/internal/tracker/source/helm/helm.go index 432f4578..615f7367 100644 --- a/internal/tracker/source/helm/helm.go +++ b/internal/tracker/source/helm/helm.go @@ -102,7 +102,7 @@ func NewTrackerSource(i *hub.TrackerSourceInput, opts ...func(s *TrackerSource)) s.il = &repo.HelmIndexLoader{} } if s.sc == nil { - s.sc = &oci.SignatureChecker{} + s.sc = oci.NewSignatureChecker(i.Svc.Op) } if s.tg == nil { s.tg = &oci.TagsGetter{} @@ -426,7 +426,7 @@ func LoadChartArchive(ctx context.Context, u *url.URL, o *LoadChartArchiveOption case "oci": op := o.Op if op == nil { - op = &oci.Puller{} + op = oci.NewPuller(nil) } ref := strings.TrimPrefix(u.String(), hub.RepositoryOCIPrefix) _, data, err := op.PullLayer(ctx, ref, ChartContentLayerMediaType, o.Username, o.Password)