Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docker scan - map vulnerabilities to Dockerfile commands #975

Merged
merged 68 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from 63 commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
32c823a
Refactor scan to allow the reuse of docker scan
EyalDelarea Aug 29, 2023
da9bd27
stash
EyalDelarea Aug 31, 2023
1a617cf
pull dev
EyalDelarea Sep 3, 2023
5e891d7
stash
EyalDelarea Sep 3, 2023
0011ffa
Init refactor, change calls with crashing tests
EyalDelarea Sep 3, 2023
947f07b
pull dev
EyalDelarea Sep 4, 2023
59a2513
pull dev
EyalDelarea Sep 4, 2023
a3152b8
fix static analysis and change order
EyalDelarea Sep 4, 2023
ffa9481
refactor
EyalDelarea Sep 4, 2023
6f4ab1a
Merge branch 'dev' of https://github.com/jfrog/jfrog-cli-core into re…
EyalDelarea Sep 4, 2023
08373b4
pull refactor table branch
EyalDelarea Sep 4, 2023
4c57a72
add new table
EyalDelarea Sep 4, 2023
db07a5f
add set scan type
EyalDelarea Sep 4, 2023
3fa6ee4
pull refactor
EyalDelarea Sep 4, 2023
1d5cf13
customize docker table output
EyalDelarea Sep 5, 2023
4d4fbf8
pull dev
EyalDelarea Sep 5, 2023
3edbbe0
fix static check
EyalDelarea Sep 5, 2023
0ae9afa
fix static check
EyalDelarea Sep 5, 2023
343398b
pull dev
EyalDelarea Sep 5, 2023
eb06af3
replace to dev
EyalDelarea Sep 5, 2023
87a30b3
remove predefined binary scan
EyalDelarea Sep 5, 2023
38881b1
pull refactor branch
EyalDelarea Sep 5, 2023
f632481
change name
EyalDelarea Sep 5, 2023
8575602
stash progress
EyalDelarea Sep 6, 2023
455055d
Merge branch 'dev' of https://github.com/jfrog/jfrog-cli-core into re…
EyalDelarea Sep 6, 2023
113d9e6
Merge branch 'dev' of https://github.com/jfrog/jfrog-cli-core into im…
EyalDelarea Sep 6, 2023
7537a30
map commands to line number
EyalDelarea Sep 6, 2023
391f666
handle more than one FROM command
EyalDelarea Sep 6, 2023
6ba2220
stash docker progress
EyalDelarea Sep 6, 2023
32f61cd
Merge branch 'dev' of https://github.com/jfrog/jfrog-cli-core into re…
EyalDelarea Sep 7, 2023
f33c559
pull dev
EyalDelarea Sep 10, 2023
54da48c
Merge dev
EyalDelarea Sep 14, 2023
e03fbf6
Fix static check
EyalDelarea Sep 14, 2023
b316e92
Merge branch 'dev' of https://github.com/jfrog/jfrog-cli-core into re…
EyalDelarea Sep 18, 2023
4f26435
pull refactor table
EyalDelarea Sep 18, 2023
fc61273
Add test
EyalDelarea Sep 18, 2023
1b30588
change replacce
EyalDelarea Sep 18, 2023
16e7d30
fix static check
EyalDelarea Sep 18, 2023
0d61c59
remove unneeded field
EyalDelarea Sep 18, 2023
3758764
pull dev
EyalDelarea Sep 20, 2023
3c278e9
line numbers in table are optional
EyalDelarea Sep 20, 2023
30c51f9
set dockerfile scanned bool
EyalDelarea Sep 20, 2023
3d065bb
Don't show extended CVEs on dockerscan
EyalDelarea Sep 20, 2023
8f2091f
Merge branch 'dev' of https://github.com/jfrog/jfrog-cli-core into im…
EyalDelarea Sep 20, 2023
250c14c
pull dev
EyalDelarea Sep 27, 2023
ed804f6
Add error info to docker scan
EyalDelarea Sep 27, 2023
08562fc
renames
EyalDelarea Sep 27, 2023
bc53591
remove dockerfile scan and scan only images
EyalDelarea Sep 27, 2023
daec5d9
remove dockerfile scanning code
EyalDelarea Sep 27, 2023
3df21ac
Remove unused code
EyalDelarea Sep 27, 2023
a412623
Add some comments
EyalDelarea Sep 27, 2023
93617a4
Change table order and remove duplicate print
EyalDelarea Sep 27, 2023
29b22ca
CR
EyalDelarea Sep 27, 2023
4be8aff
pull dev
EyalDelarea Sep 28, 2023
adb401d
pull dev
EyalDelarea Oct 1, 2023
7b29288
Merge branch 'dev' of https://github.com/jfrog/jfrog-cli-core into do…
EyalDelarea Oct 2, 2023
5cd11bf
Add comments
EyalDelarea Oct 2, 2023
7c82022
pull dev
EyalDelarea Oct 5, 2023
64438c7
update client go
EyalDelarea Oct 5, 2023
ee53c82
cr
EyalDelarea Oct 5, 2023
576e872
CR
EyalDelarea Oct 5, 2023
1b73d3a
CR
EyalDelarea Oct 5, 2023
ee337f4
Fix rename and remove docker scan type
EyalDelarea Oct 5, 2023
fb7b69c
fix static check
EyalDelarea Oct 5, 2023
777ec51
cleanUp NPE
EyalDelarea Oct 5, 2023
c0de205
Fix table order
EyalDelarea Oct 5, 2023
2c76d3f
Fix test
EyalDelarea Oct 5, 2023
2d05a5e
Change struct to map of strings
EyalDelarea Oct 5, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ require (
github.com/stretchr/testify v1.8.4
github.com/urfave/cli v1.22.14
github.com/vbauerster/mpb/v7 v7.5.3
github.com/wagoodman/dive v0.11.0
golang.org/x/exp v0.0.0-20230905200255-921286631fa9
golang.org/x/mod v0.12.0
golang.org/x/sync v0.3.0
Expand All @@ -42,16 +43,28 @@ require (
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
github.com/acomagu/bufpipe v1.0.4 // indirect
github.com/andybalholm/brotli v1.0.1 // indirect
github.com/awesome-gocui/gocui v1.1.0 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cloudflare/circl v1.3.3 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/cli v24.0.5+incompatible // indirect
github.com/docker/distribution v2.8.2+incompatible // indirect
github.com/docker/docker v24.0.2+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gdamore/encoding v1.0.0 // indirect
github.com/gdamore/tcell/v2 v2.4.0 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.5.0 // indirect
github.com/go-git/go-git/v5 v5.9.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/snappy v0.0.2 // indirect
Expand All @@ -61,6 +74,8 @@ require (
github.com/klauspost/compress v1.11.4 // indirect
github.com/klauspost/cpuid/v2 v2.2.3 // indirect
github.com/klauspost/pgzip v1.2.5 // indirect
github.com/logrusorgru/aurora v0.0.0-20190803045625-94edacc10f9b // indirect
github.com/lucasb-eyer/go-colorful v1.0.3 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
Expand All @@ -69,14 +84,19 @@ require (
github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/nwaples/rardecode v1.1.0 // indirect
github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/phayes/permbits v0.0.0-20190612203442-39d7c581d2ee // indirect
github.com/pierrec/lz4/v4 v4.1.2 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pkg/term v1.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.4.3 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sergi/go-diff v1.1.0 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/skeema/knownhosts v1.2.0 // indirect
github.com/spf13/afero v1.9.5 // indirect
github.com/spf13/cast v1.5.1 // indirect
Expand All @@ -98,3 +118,5 @@ require (
// replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20231003120621-90e9d7ea05e9

// replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20231003094520-3a09931ceaa8

replace github.com/jfrog/jfrog-client-go => github.com/eyaldelarea/jfrog-client-go v1.28.1-0.20231005095104-8f7d79561336
190 changes: 188 additions & 2 deletions go.sum

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions xray/commands/scan/buildscan.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"errors"
rtutils "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils"
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
"github.com/jfrog/jfrog-cli-core/v2/xray/utils"
xrutils "github.com/jfrog/jfrog-cli-core/v2/xray/utils"
clientutils "github.com/jfrog/jfrog-client-go/utils"
"github.com/jfrog/jfrog-client-go/utils/log"
Expand Down Expand Up @@ -72,7 +71,7 @@ func (bsc *BuildScanCommand) SetRescan(rescan bool) *BuildScanCommand {

// Scan published builds with Xray
func (bsc *BuildScanCommand) Run() (err error) {
xrayManager, xrayVersion, err := utils.CreateXrayServiceManagerAndGetVersion(bsc.serverDetails)
xrayManager, xrayVersion, err := xrutils.CreateXrayServiceManagerAndGetVersion(bsc.serverDetails)
if err != nil {
return err
}
Expand Down
73 changes: 66 additions & 7 deletions xray/commands/scan/dockerscan.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"github.com/jfrog/jfrog-client-go/utils/errorutils"
"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
"github.com/jfrog/jfrog-client-go/utils/log"
"github.com/jfrog/jfrog-client-go/xray/services"
"github.com/wagoodman/dive/dive"
"os"
"os/exec"
"path/filepath"
Expand All @@ -18,12 +20,16 @@ import (
const (
indexerEnvPrefix = "JFROG_INDEXER_"
DockerScanMinXrayVersion = "3.40.0"
layerDigestPrefix = "sha256:"
// Suffix added while analyzing docker layers, remove it for better readability.
buildKitSuffix = " # buildkit"
)

type DockerScanCommand struct {
ScanCommand
imageTag string
targetRepoPath string
imageTag string
targetRepoPath string
dockerCommandsMapping map[string]services.DockerCommandDetails
}

func NewDockerScanCommand() *DockerScanCommand {
Expand All @@ -40,6 +46,7 @@ func (dsc *DockerScanCommand) SetTargetRepoPath(repoPath string) *DockerScanComm
return dsc
}

// DockerScan scan will save a docker image as .tar file and will prefore binary scan on it.
func (dsc *DockerScanCommand) Run() (err error) {
// Validate Xray minimum version
_, xrayVersion, err := xrayutils.CreateXrayServiceManagerAndGetVersion(dsc.ScanCommand.serverDetails)
Expand Down Expand Up @@ -68,21 +75,26 @@ func (dsc *DockerScanCommand) Run() (err error) {
}
log.Info("Creating image archive...")
imageTarPath := filepath.Join(tempDirPath, "image.tar")

dockerSaveCmd := exec.Command("docker", "save", dsc.imageTag, "-o", imageTarPath)
var stderr bytes.Buffer
dockerSaveCmd.Stderr = &stderr
err = dockerSaveCmd.Run()
if err != nil {
if err = dockerSaveCmd.Run(); err != nil {
return fmt.Errorf("failed running command: '%s' with error: %s - %s", strings.Join(dockerSaveCmd.Args, " "), err.Error(), stderr.String())
}

// Map layers sha256 checksum names to dockerfile line commands
if err = dsc.mapDockerLayerToCommand(); err != nil {
return
}

// Perform scan on image.tar
dsc.SetSpec(spec.NewBuilder().
Pattern(imageTarPath).
Target(dsc.targetRepoPath).
BuildSpec()).SetThreads(1)
err = dsc.setCredentialEnvsForIndexerApp()
if err != nil {

if err = dsc.setCredentialEnvsForIndexerApp(); err != nil {
return errorutils.CheckError(err)
}
defer func() {
Expand All @@ -91,7 +103,54 @@ func (dsc *DockerScanCommand) Run() (err error) {
err = errorutils.CheckError(e)
}
}()
return dsc.ScanCommand.Run()
// Preform binary scan.
extendedScanResults, cleanup, scanErrors, err := dsc.ScanCommand.binaryScan()
defer cleanup()
if err != nil {
return
}

// Print results with docker commands mapping.
err = xrayutils.NewResultsWriter(extendedScanResults).
SetOutputFormat(dsc.outputFormat).
SetIncludeVulnerabilities(dsc.includeVulnerabilities).
SetIncludeLicenses(dsc.includeLicenses).
SetPrintExtendedTable(dsc.printExtendedTable).
SetIsMultipleRootProject(true).
SetDockerCommandsMapping(dsc.dockerCommandsMapping).
PrintScanResults()

return dsc.ScanCommand.handlePossibleErrors(extendedScanResults.XrayResults, scanErrors, err)
}

func (dsc *DockerScanCommand) mapDockerLayerToCommand() (err error) {
log.Debug("Mapping docker layers into commands...")
resolver, err := dive.GetImageResolver(dive.SourceDockerEngine)
if err != nil {
return errorutils.CheckErrorf("failed to map docker layers, is docker running on your machine? error message: %s", err.Error())
}
dockerImage, err := resolver.Fetch(dsc.imageTag)
if err != nil {
return
}
// Create mapping between sha256 hash to dockerfile Command.
layersMapping := make(map[string]services.DockerCommandDetails)
for _, layer := range dockerImage.Layers {
layerHash := strings.TrimPrefix(layer.Digest, layerDigestPrefix)
layersMapping[layerHash] = services.DockerCommandDetails{LayerHash: layer.Digest, Command: cleanDockerfileCommand(layer.Command)}
}
dsc.dockerCommandsMapping = layersMapping
return
}

// DockerScan command could potentiality have double spaces,
// Reconstruct the command with only one space between arguments.
// Example: command from dive: "RUN apt-get install && apt-get install #builtkit".
// Will resolve to a cleaner command RUN apt-get install && apt-get install
func cleanDockerfileCommand(rawCommand string) string {
fields := strings.Fields(rawCommand)
command := strings.Join(fields, " ")
return strings.TrimSuffix(command, buildKitSuffix)
}

// When indexing RPM files inside the docker container, the indexer-app needs to connect to the Xray Server.
Expand Down
Loading
Loading