mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-21 06:43:05 -08:00
Support for scanning of an OCI image given a tag. (fanal#130)
Condition:- Specify an image name and tag ":" separated. If correct image name and tag is specified ":" separated, image with given tag will be return otherwise first one will be return
This commit is contained in:
2
go.mod
2
go.mod
@@ -21,7 +21,7 @@ require (
|
|||||||
github.com/knqyf263/nested v0.0.1
|
github.com/knqyf263/nested v0.0.1
|
||||||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348
|
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348
|
||||||
github.com/opencontainers/go-digest v1.0.0-rc1
|
github.com/opencontainers/go-digest v1.0.0-rc1
|
||||||
github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6 // indirect
|
github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6
|
||||||
github.com/saracen/walker v0.0.0-20191201085201-324a081bae7e
|
github.com/saracen/walker v0.0.0-20191201085201-324a081bae7e
|
||||||
github.com/sosedoff/gitkit v0.2.0
|
github.com/sosedoff/gitkit v0.2.0
|
||||||
github.com/stretchr/testify v1.5.1
|
github.com/stretchr/testify v1.5.1
|
||||||
|
|||||||
@@ -9,12 +9,14 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/aquasecurity/fanal/image/token"
|
"github.com/aquasecurity/fanal/image/token"
|
||||||
|
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
|
||||||
"github.com/google/go-containerregistry/pkg/authn"
|
"github.com/google/go-containerregistry/pkg/authn"
|
||||||
"github.com/google/go-containerregistry/pkg/name"
|
"github.com/google/go-containerregistry/pkg/name"
|
||||||
"github.com/google/go-containerregistry/pkg/v1"
|
v1 "github.com/google/go-containerregistry/pkg/v1"
|
||||||
"github.com/google/go-containerregistry/pkg/v1/layout"
|
"github.com/google/go-containerregistry/pkg/v1/layout"
|
||||||
"github.com/google/go-containerregistry/pkg/v1/remote"
|
"github.com/google/go-containerregistry/pkg/v1/remote"
|
||||||
"github.com/google/go-containerregistry/pkg/v1/tarball"
|
"github.com/google/go-containerregistry/pkg/v1/tarball"
|
||||||
@@ -186,7 +188,19 @@ func fileOpener(fileName string) func() (io.ReadCloser, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func tryOCI(fileName string) (v1.Image, error) {
|
func tryOCI(fileName string) (v1.Image, error) {
|
||||||
lp, err := layout.FromPath(fileName)
|
var inputTag, inputFileName string
|
||||||
|
|
||||||
|
// Check if tag is specified in input
|
||||||
|
if strings.Contains(fileName, ":") {
|
||||||
|
splitFileName := strings.Split(fileName, ":")
|
||||||
|
inputFileName = splitFileName[0]
|
||||||
|
inputTag = splitFileName[1]
|
||||||
|
} else {
|
||||||
|
inputFileName = fileName
|
||||||
|
inputTag = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
lp, err := layout.FromPath(inputFileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("unable to open %s as an OCI Image: %w", fileName, err)
|
return nil, xerrors.Errorf("unable to open %s as an OCI Image: %w", fileName, err)
|
||||||
}
|
}
|
||||||
@@ -205,12 +219,38 @@ func tryOCI(fileName string) (v1.Image, error) {
|
|||||||
return nil, xerrors.New("no valid manifest")
|
return nil, xerrors.New("no valid manifest")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Support only first image
|
// Support image having tag separated by : , otherwise support first image
|
||||||
h := m.Manifests[0].Digest
|
|
||||||
img, err := index.Image(h)
|
if inputTag != "" {
|
||||||
if err != nil {
|
return getOCIImage(m, index, inputTag)
|
||||||
return nil, xerrors.New("invalid OCI image")
|
} else {
|
||||||
|
h := m.Manifests[0].Digest
|
||||||
|
|
||||||
|
img, err := index.Image(h)
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.New("invalid OCI image")
|
||||||
|
}
|
||||||
|
|
||||||
|
return img, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getOCIImage(m *v1.IndexManifest, index v1.ImageIndex, inputTag string) (v1.Image, error) {
|
||||||
|
for _, manifest := range m.Manifests {
|
||||||
|
annotation := manifest.Annotations
|
||||||
|
|
||||||
|
tag := annotation[ispec.AnnotationRefName]
|
||||||
|
if tag == inputTag {
|
||||||
|
h := manifest.Digest
|
||||||
|
|
||||||
|
img, err := index.Image(h)
|
||||||
|
if err != nil {
|
||||||
|
return nil, xerrors.New("invalid OCI image")
|
||||||
|
}
|
||||||
|
|
||||||
|
return img, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return img, nil
|
return nil, xerrors.New("invalid OCI image tag")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -226,6 +226,25 @@ func TestNewArchiveImage(t *testing.T) {
|
|||||||
fileName: "../test/testdata/test.oci",
|
fileName: "../test/testdata/test.oci",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "happy path with OCI Image and tag Format",
|
||||||
|
args: args{
|
||||||
|
fileName: "../test/testdata/test_image_tag.oci:0.0.1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "happy path with OCI Image only",
|
||||||
|
args: args{
|
||||||
|
fileName: "../test/testdata/test_image_tag.oci",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "sad path with OCI Image and invalid tagFormat",
|
||||||
|
args: args{
|
||||||
|
fileName: "../test/testdata/test_image_tag.oci:0.0.0",
|
||||||
|
},
|
||||||
|
wantErr: "invalid OCI image tag",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "sad path, oci image not found",
|
name: "sad path, oci image not found",
|
||||||
args: args{
|
args: args{
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
{"schemaVersion":2,"config":{"mediaType":"application/vnd.oci.image.config.v1+json","digest":"sha256:b23a8f6569ae9ae331226205fa72f480ce5310707d0bc97e611f83fbbbde4604","size":584},"layers":[{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:cdd16bd695eda2819e7637648f573c2ca64896c4f7bff9732ac9db734ca3bc2c","size":2610}]}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"created":"2020-01-03T01:21:37.263809283Z","architecture":"amd64","os":"linux","config":{"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],"Cmd":["/hello"]},"rootfs":{"type":"layers","diff_ids":["sha256:9c27e219663c25e0f28493790cc0b88bc973ba3b1686355f221c38a36978ac63"]},"history":[{"created":"2020-01-03T01:21:37.132606296Z","created_by":"/bin/sh -c #(nop) COPY file:7bf12aab75c3867a023fe3b8bd6d113d43a4fcc415f3cc27cbcf0fff37b65a02 in / "},{"created":"2020-01-03T01:21:37.263809283Z","created_by":"/bin/sh -c #(nop) CMD [\"/hello\"]","empty_layer":true}]}
|
||||||
Binary file not shown.
13
test/testdata/test_image_tag.oci/index.json
vendored
Normal file
13
test/testdata/test_image_tag.oci/index.json
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"schemaVersion": 2,
|
||||||
|
"manifests": [
|
||||||
|
{
|
||||||
|
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||||
|
"digest": "sha256:afb744871f99e0ff8e6f253244836ed34c5d805fdb096d3a205ffaf5e9073cab",
|
||||||
|
"size": 345,
|
||||||
|
"annotations": {
|
||||||
|
"org.opencontainers.image.ref.name": "0.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
1
test/testdata/test_image_tag.oci/oci-layout
vendored
Normal file
1
test/testdata/test_image_tag.oci/oci-layout
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"imageLayoutVersion": "1.0.0"}
|
||||||
Reference in New Issue
Block a user