Skip to content

Commit 6c99b9e

Browse files
committed
scan: ability to override repository
Signed-off-by: Dentrax <[email protected]>
1 parent 6d7c791 commit 6c99b9e

File tree

4 files changed

+69
-25
lines changed

4 files changed

+69
-25
lines changed

.github/actions/action.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ runs:
88
repository: wolfi-dev/wolfictl
99
path: wolfictl-setup-gha
1010

11-
- uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
11+
- uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
1212
with:
1313
go-version: '1.21'
1414
check-latest: true

docs/cmd/wolfictl_scan.md

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ By default, the command will print all vulnerabilities found in the package(s)
3636
to stdout. You can filter the vulnerabilities shown using existing local
3737
advisory data. To do this, you must first clone the advisory data from the
3838
advisories repository for the distro whose packages you are scanning. You
39-
specify the path to each local advisories repository using the
40-
--advisories-repo-dir flag for each repository. Then, you can use the
39+
specify the path to the local advisories repository using the
40+
--advisories-repo-dir flag for the repository. Then, you can use the
4141
"--advisory-filter" flag to specify which set of advisories to use for
4242
filtering. The following sets of advisories are available:
4343

@@ -113,18 +113,27 @@ wolfictl scan package1 package2 --remote
113113
### Options
114114

115115
```
116-
-a, --advisories-repo-dir strings local directory for advisory data
117-
-f, --advisory-filter string exclude vulnerability matches that are referenced from the specified set of advisories (resolved|all|concluded)
118-
--build-log treat input as a package build log file (or a directory that contains a packages.log file)
119-
--disable-sbom-cache don't use the SBOM cache
120-
--distro string distro to use during vulnerability matching (default "wolfi")
121-
-h, --help help for scan
122-
--local-file-grype-db string import a local grype db file
123-
-o, --output string output format (outline|json), defaults to outline
124-
-r, --remote treat input(s) as the name(s) of package(s) in the Wolfi package repository to download and scan the latest versions of
125-
--require-zero exit 1 if any vulnerabilities are found
126-
-s, --sbom treat input(s) as SBOM(s) of APK(s) instead of as actual APK(s)
127-
--use-cpes turn on all CPE matching in Grype
116+
-a, --advisories-repo-dir string directory containing the advisories repository
117+
-f, --advisory-filter string exclude vulnerability matches that are referenced from the specified set of advisories (resolved|all|concluded)
118+
--build-log treat input as a package build log file (or a directory that contains a packages.log file)
119+
--disable-sbom-cache don't use the SBOM cache
120+
--distro string distro to use during vulnerability matching (default "wolfi")
121+
-h, --help help for scan
122+
--local-file-grype-db string import a local grype db file
123+
-o, --output string output format (outline|json), defaults to outline
124+
-r, --remote treat input(s) as the name(s) of package(s) in the Wolfi package repository to download and scan the latest versions of
125+
--repository string URL of the APK package repository (default "https://packages.wolfi.dev/os")
126+
--require-zero exit 1 if any vulnerabilities are found
127+
-s, --sbom treat input(s) as SBOM(s) of APK(s) instead of as actual APK(s)
128+
--use-cpes turn on all CPE matching in Grype
129+
-v, --verbose count logging verbosity (v = info, vv = debug, default is none)
130+
```
131+
132+
### Options inherited from parent commands
133+
134+
```
135+
--log-level string log level (e.g. debug, info, warn, error) (default "info")
136+
--log-policy strings log policy (e.g. builtin:stderr, /tmp/log/foo) (default [builtin:stderr])
128137
```
129138

130139
### SEE ALSO

docs/man/man1/wolfictl-scan.1

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ By default, the command will print all vulnerabilities found in the package(s)
5353
to stdout. You can filter the vulnerabilities shown using existing local
5454
advisory data. To do this, you must first clone the advisory data from the
5555
advisories repository for the distro whose packages you are scanning. You
56-
specify the path to each local advisories repository using the
57-
\-\-advisories\-repo\-dir flag for each repository. Then, you can use the
56+
specify the path to the local advisories repository using the
57+
\-\-advisories\-repo\-dir flag for the repository. Then, you can use the
5858
"\-\-advisory\-filter" flag to specify which set of advisories to use for
5959
filtering. The following sets of advisories are available:
6060

@@ -130,8 +130,8 @@ found and the \-\-require\-zero flag is specified.
130130

131131
.SH OPTIONS
132132
.PP
133-
\fB\-a\fP, \fB\-\-advisories\-repo\-dir\fP=[]
134-
local directory for advisory data
133+
\fB\-a\fP, \fB\-\-advisories\-repo\-dir\fP=""
134+
directory containing the advisories repository
135135

136136
.PP
137137
\fB\-f\fP, \fB\-\-advisory\-filter\fP=""
@@ -165,6 +165,11 @@ found and the \-\-require\-zero flag is specified.
165165
\fB\-r\fP, \fB\-\-remote\fP[=false]
166166
treat input(s) as the name(s) of package(s) in the Wolfi package repository to download and scan the latest versions of
167167

168+
.PP
169+
\fB\-\-repository\fP="
170+
\[la]https://packages.wolfi.dev/os"\[ra]
171+
URL of the APK package repository
172+
168173
.PP
169174
\fB\-\-require\-zero\fP[=false]
170175
exit 1 if any vulnerabilities are found
@@ -177,6 +182,20 @@ found and the \-\-require\-zero flag is specified.
177182
\fB\-\-use\-cpes\fP[=false]
178183
turn on all CPE matching in Grype
179184

185+
.PP
186+
\fB\-v\fP, \fB\-\-verbose\fP[=0]
187+
logging verbosity (v = info, vv = debug, default is none)
188+
189+
190+
.SH OPTIONS INHERITED FROM PARENT COMMANDS
191+
.PP
192+
\fB\-\-log\-level\fP="info"
193+
log level (e.g. debug, info, warn, error)
194+
195+
.PP
196+
\fB\-\-log\-policy\fP=[builtin:stderr]
197+
log policy (e.g. builtin:stderr, /tmp/log/foo)
198+
180199

181200
.SH EXAMPLE
182201

pkg/cli/scan.go

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"strings"
1515

1616
"chainguard.dev/apko/pkg/apk/apk"
17+
"chainguard.dev/apko/pkg/apk/auth"
1718
sbomSyft "github.com/anchore/syft/syft/sbom"
1819
"github.com/chainguard-dev/clog"
1920
"github.com/charmbracelet/lipgloss"
@@ -25,7 +26,6 @@ import (
2526
"github.com/wolfi-dev/wolfictl/pkg/configs"
2627
v2 "github.com/wolfi-dev/wolfictl/pkg/configs/advisory/v2"
2728
rwos "github.com/wolfi-dev/wolfictl/pkg/configs/rwfs/os"
28-
"github.com/wolfi-dev/wolfictl/pkg/index"
2929
"github.com/wolfi-dev/wolfictl/pkg/sbom"
3030
"github.com/wolfi-dev/wolfictl/pkg/scan"
3131
"github.com/wolfi-dev/wolfictl/pkg/versions"
@@ -357,6 +357,7 @@ type scanParams struct {
357357
disableSBOMCache bool
358358
triageWithGoVulnCheck bool
359359
remoteScanning bool
360+
remoteRepository string
360361
useCPEMatching bool
361362
verbosity int
362363
}
@@ -374,6 +375,7 @@ func (p *scanParams) addFlagsTo(cmd *cobra.Command) {
374375
cmd.Flags().BoolVar(&p.triageWithGoVulnCheck, "govulncheck", false, "EXPERIMENTAL: triage vulnerabilities in Go binaries using govulncheck")
375376
_ = cmd.Flags().MarkHidden("govulncheck") //nolint:errcheck
376377
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")
378+
cmd.Flags().StringVar(&p.remoteRepository, "repository", "https://packages.wolfi.dev/os", "URL of the APK package repository")
377379
cmd.Flags().BoolVar(&p.useCPEMatching, "use-cpes", false, "turn on all CPE matching in Grype")
378380
addVerboseFlag(&p.verbosity, cmd)
379381
}
@@ -403,7 +405,7 @@ func (p *scanParams) resolveInputsToScan(ctx context.Context, args []string) (in
403405
}
404406

405407
for _, arg := range args {
406-
targetPaths, cleanup, err := resolveInputForRemoteTarget(ctx, arg)
408+
targetPaths, cleanup, err := resolveInputForRemoteTarget(ctx, arg, p.remoteRepository)
407409
if err != nil {
408410
return nil, nil, fmt.Errorf("failed to resolve input %q for remote scanning: %w", arg, err)
409411
}
@@ -606,6 +608,18 @@ func resolveInputFileFromArg(inputFilePath string) (*os.File, error) {
606608
}
607609
}
608610

611+
// getAPKIndexURL returns the URL of the APKINDEX.tar.gz file for the given
612+
// repository and architecture. If the repository URL already points to an
613+
// APKINDEX.tar.gz file, it will be returned as-is. User input may or may not
614+
// have included the architecture or the APKINDEX.tar.gz suffix, so construct
615+
// the full URL to provide better UX.
616+
func getAPKIndexURL(repositoryURL, arch string) string {
617+
if strings.HasSuffix(repositoryURL, "/x86_64/APKINDEX.tar.gz") || strings.HasSuffix(repositoryURL, "/aarch64/APKINDEX.tar.gz") {
618+
return repositoryURL
619+
}
620+
return fmt.Sprintf("%s/%s/APKINDEX.tar.gz", repositoryURL, arch)
621+
}
622+
609623
// resolveInputForRemoteTarget takes the given input string, which is expected
610624
// to be the name of a Wolfi package (or subpackage), and it queries the Wolfi
611625
// APK repository to find the latest version of the package for each
@@ -615,13 +629,14 @@ func resolveInputFileFromArg(inputFilePath string) (*os.File, error) {
615629
// For example, given the input value "calico", this function will find the
616630
// latest version of the package (e.g. "calico-3.26.3-r3.apk") and download it
617631
// for each architecture.
618-
func resolveInputForRemoteTarget(ctx context.Context, input string) (downloadedAPKFilePaths []string, cleanup func() error, err error) {
632+
func resolveInputForRemoteTarget(ctx context.Context, input, repository string) (downloadedAPKFilePaths []string, cleanup func() error, err error) {
619633
logger := clog.FromContext(ctx)
620634

621635
archesFound := 0
622636
for _, arch := range []string{"x86_64", "aarch64"} {
623-
const apkRepositoryURL = "https://packages.wolfi.dev/os"
624-
apkindex, err := index.Index(arch, apkRepositoryURL)
637+
// Since index.Index function doesn't respect the `$HTTP_AUTH`, use
638+
// fetchAPKIndex function instead.
639+
apkindex, _, err := fetchAPKIndex(ctx, getAPKIndexURL(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+
auth.DefaultAuthenticators.AddAuth(ctx, req)
668684
logger.Debug("downloading APK", "url", downloadURL)
669685
resp, err := http.DefaultClient.Do(req)
670686
if err != nil {

0 commit comments

Comments
 (0)