Skip to content

Commit

Permalink
aws distribution scanner
Browse files Browse the repository at this point in the history
  • Loading branch information
ldelossa committed Jan 21, 2020
1 parent 04cb83a commit c80c903
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 0 deletions.
57 changes: 57 additions & 0 deletions aws/distributionscanner_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package aws

import (
"bytes"
"testing"

"github.com/google/go-cmp/cmp"
)

var linux1OSRelease []byte = []byte(`NAME="Amazon Linux AMI"
VERSION="2018.03"
ID="amzn"
ID_LIKE="rhel fedora"
VERSION_ID="2018.03"
PRETTY_NAME="Amazon Linux AMI 2018.03"
ANSI_COLOR="0;33"
CPE_NAME="cpe:/o:amazon:linux:2018.03:ga"
HOME_URL="http://aws.amazon.com/amazon-linux-ami/"`)

var linux2OSRelease []byte = []byte(`NAME="Amazon Linux"
VERSION="2"
ID="amzn"
ID_LIKE="centos rhel fedora"
VERSION_ID="2"
PRETTY_NAME="Amazon Linux 2"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
HOME_URL="https://amazonlinux.com/"`)

func TestDistributionScanner(t *testing.T) {
table := []struct {
name string
release Release
osRelease []byte
}{
{
name: "linux1",
release: Linux1,
osRelease: linux1OSRelease,
},
{
name: "linux2",
release: Linux2,
osRelease: linux2OSRelease,
},
}
for _, tt := range table {
t.Run(tt.name, func(t *testing.T) {
scanner := DistributionScanner{}
dist := scanner.parse(bytes.NewBuffer(tt.osRelease))
cmpDist, _ := releaseToDist(tt.release)
if !cmp.Equal(dist, cmpDist) {
t.Fatalf("%v", cmp.Diff(dist, cmpDist))
}
})
}
}
103 changes: 103 additions & 0 deletions aws/distributionscannner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package aws

import (
"bytes"
"context"
"regexp"
"runtime/trace"

"github.com/quay/claircore"
"github.com/quay/claircore/internal/indexer"
"github.com/rs/zerolog"
)

// AWS Linux keeps a consistent os-release file between
// major releases.
// All tested images on docker hub contained os-release file

const (
scannerName = "aws"
scannerVersion = "v0.0.1"
scannerKind = "distribution"
)

type awsRegex struct {
release Release
regexp *regexp.Regexp
}

var awsRegexes = []awsRegex{
{
release: Linux1,
regexp: regexp.MustCompile(`Amazon Linux AMI 2018.03`),
},
{
release: Linux2,
regexp: regexp.MustCompile(`Amazon Linux 2`),
},
}

const osReleasePath = `etc/os-release`

var _ indexer.DistributionScanner = (*DistributionScanner)(nil)
var _ indexer.VersionedScanner = (*DistributionScanner)(nil)

// DistributionScanner attempts to discover if a layer
// displays characteristics of a AWS distribution
type DistributionScanner struct{}

// Name implements scanner.VersionedScanner.
func (*DistributionScanner) Name() string { return scannerName }

// Version implements scanner.VersionedScanner.
func (*DistributionScanner) Version() string { return scannerVersion }

// Kind implements scanner.VersionedScanner.
func (*DistributionScanner) Kind() string { return scannerKind }

// Scan will inspect the layer for an os-release or lsb-release file
// and perform a regex match for keywords indicating the associated AWS release
//
// If neither file is found a (nil,nil) is returned.
// If the files are found but all regexp fail to match an empty distribution is returned.
func (ds *DistributionScanner) Scan(ctx context.Context, l *claircore.Layer) ([]*claircore.Distribution, error) {
defer trace.StartRegion(ctx, "Scanner.Scan").End()
log := zerolog.Ctx(ctx).With().
Str("component", "aws_dist_scanner").
Str("name", ds.Name()).
Str("version", ds.Version()).
Str("kind", ds.Kind()).
Str("layer", l.Hash).
Logger()
log.Debug().Msg("start")
defer log.Debug().Msg("done")
files, err := l.Files(osReleasePath)
if err != nil {
log.Debug().Msg("didn't find an os-release")
return nil, nil
}
for _, buff := range files {
dist := ds.parse(buff)
if dist != nil {
return []*claircore.Distribution{dist}, nil
}
}
return []*claircore.Distribution{&claircore.Distribution{}}, nil
}

// parse attempts to match all AWS release regexp and returns the associated
// distribution if it exists.
//
// separated to it's own method to aide testing.
func (ds *DistributionScanner) parse(buff *bytes.Buffer) *claircore.Distribution {
for _, ur := range awsRegexes {
if ur.regexp.Match(buff.Bytes()) {
dist, err := releaseToDist(ur.release)
if err != nil {
panic("aws distrubution scanner: awsRegex configured with unknown release")
}
return dist
}
}
return nil
}
2 changes: 2 additions & 0 deletions aws/releases.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ var linux1Dist = &claircore.Distribution{
Version: "2018.03",
VersionID: "2018.03",
PrettyName: "Amazon Linux AMI 2018.03",
CPE: "cpe:/o:amazon:linux:2018.03:ga",
}

var linux2Dist = &claircore.Distribution{
Expand All @@ -29,6 +30,7 @@ var linux2Dist = &claircore.Distribution{
Version: "2",
VersionID: "2",
PrettyName: "Amazon Linux 2",
CPE: "cpe:2.3:o:amazon:amazon_linux:2",
}

func releaseToDist(release Release) (*claircore.Distribution, error) {
Expand Down

0 comments on commit c80c903

Please sign in to comment.