@@ -25,7 +25,6 @@ import (
2525 "github.com/wolfi-dev/wolfictl/pkg/configs"
2626 v2 "github.com/wolfi-dev/wolfictl/pkg/configs/advisory/v2"
2727 rwos "github.com/wolfi-dev/wolfictl/pkg/configs/rwfs/os"
28- "github.com/wolfi-dev/wolfictl/pkg/index"
2928 "github.com/wolfi-dev/wolfictl/pkg/sbom"
3029 "github.com/wolfi-dev/wolfictl/pkg/scan"
3130 "github.com/wolfi-dev/wolfictl/pkg/versions"
@@ -357,6 +356,7 @@ type scanParams struct {
357356 disableSBOMCache bool
358357 triageWithGoVulnCheck bool
359358 remoteScanning bool
359+ remoteRepository string
360360 useCPEMatching bool
361361 verbosity int
362362}
@@ -374,6 +374,7 @@ func (p *scanParams) addFlagsTo(cmd *cobra.Command) {
374374 cmd .Flags ().BoolVar (& p .triageWithGoVulnCheck , "govulncheck" , false , "EXPERIMENTAL: triage vulnerabilities in Go binaries using govulncheck" )
375375 _ = cmd .Flags ().MarkHidden ("govulncheck" ) //nolint:errcheck
376376 cmd .Flags ().BoolVarP (& p .remoteScanning , "remote" , "r" , false , "treat input(s) as the name(s) of package(s) in the Wolfi package repository to download and scan the latest versions of" )
377+ cmd .Flags ().StringVar (& p .remoteRepository , "repository" , "https://packages.wolfi.dev/os" , "URL of the Wolfi package repository" )
377378 cmd .Flags ().BoolVar (& p .useCPEMatching , "use-cpes" , false , "turn on all CPE matching in Grype" )
378379 addVerboseFlag (& p .verbosity , cmd )
379380}
@@ -403,7 +404,7 @@ func (p *scanParams) resolveInputsToScan(ctx context.Context, args []string) (in
403404 }
404405
405406 for _ , arg := range args {
406- targetPaths , cleanup , err := resolveInputForRemoteTarget (ctx , arg )
407+ targetPaths , cleanup , err := resolveInputForRemoteTarget (ctx , arg , p . remoteRepository )
407408 if err != nil {
408409 return nil , nil , fmt .Errorf ("failed to resolve input %q for remote scanning: %w" , arg , err )
409410 }
@@ -606,6 +607,18 @@ func resolveInputFileFromArg(inputFilePath string) (*os.File, error) {
606607 }
607608}
608609
610+ // getRepositoryURL returns the URL of the APKINDEX.tar.gz file for the given
611+ // repository and architecture. If the repository URL already points to an
612+ // APKINDEX.tar.gz file, it will be returned as-is. User input may or may not
613+ // have included the architecture or the APKINDEX.tar.gz suffix, so construct
614+ // the full URL to provide better UX.
615+ func getRepositoryURL (repository , arch string ) string {
616+ if strings .HasSuffix (repository , "/x86_64/APKINDEX.tar.gz" ) || strings .HasSuffix (repository , "/aarch64/APKINDEX.tar.gz" ) {
617+ return repository
618+ }
619+ return fmt .Sprintf ("%s/%s/APKINDEX.tar.gz" , repository , arch )
620+ }
621+
609622// resolveInputForRemoteTarget takes the given input string, which is expected
610623// to be the name of a Wolfi package (or subpackage), and it queries the Wolfi
611624// APK repository to find the latest version of the package for each
@@ -615,13 +628,15 @@ func resolveInputFileFromArg(inputFilePath string) (*os.File, error) {
615628// For example, given the input value "calico", this function will find the
616629// latest version of the package (e.g. "calico-3.26.3-r3.apk") and download it
617630// for each architecture.
618- func resolveInputForRemoteTarget (ctx context.Context , input string ) (downloadedAPKFilePaths []string , cleanup func () error , err error ) {
631+ func resolveInputForRemoteTarget (ctx context.Context , input , repository string ) (downloadedAPKFilePaths []string , cleanup func () error , err error ) {
619632 logger := clog .FromContext (ctx )
620633
621634 archesFound := 0
622635 for _ , arch := range []string {"x86_64" , "aarch64" } {
623- const apkRepositoryURL = "https://packages.wolfi.dev/os"
624- apkindex , err := index .Index (arch , apkRepositoryURL )
636+
637+ // Since index.Index function doesn't respect the `$HTTP_AUTH`, use
638+ // fetchAPKIndex function instead.
639+ apkindex , _ , err := fetchAPKIndex (ctx , getRepositoryURL (repository , arch ))
625640 if err != nil {
626641 return nil , nil , fmt .Errorf ("getting APKINDEX: %w" , err )
627642 }
@@ -651,7 +666,7 @@ func resolveInputForRemoteTarget(ctx context.Context, input string) (downloadedA
651666 break
652667 }
653668 }
654- downloadURL := fmt .Sprintf ("%s/%s/%s" , apkRepositoryURL , arch , latestPkg .Filename ())
669+ downloadURL := fmt .Sprintf ("%s/%s/%s" , repository , arch , latestPkg .Filename ())
655670
656671 apkTempFileName := fmt .Sprintf ("%s-%s-%s-*.apk" , arch , input , latestVersion )
657672 tmpFile , err := os .CreateTemp ("" , apkTempFileName )
@@ -665,6 +680,7 @@ func resolveInputForRemoteTarget(ctx context.Context, input string) (downloadedA
665680 return nil , nil , fmt .Errorf ("creating request for %q: %w" , downloadURL , err )
666681 }
667682
683+ addAuth (req )
668684 logger .Debug ("downloading APK" , "url" , downloadURL )
669685 resp , err := http .DefaultClient .Do (req )
670686 if err != nil {
0 commit comments