Skip to content

Commit

Permalink
feat(config): add external scanner (aquasecurity#206)
Browse files Browse the repository at this point in the history
  • Loading branch information
knqyf263 authored Jul 10, 2021
1 parent f86e1e4 commit f728f19
Show file tree
Hide file tree
Showing 6 changed files with 200 additions and 0 deletions.
66 changes: 66 additions & 0 deletions external/config_scan.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package external

import (
"context"
"errors"

"github.com/aquasecurity/fanal/analyzer"
"github.com/aquasecurity/fanal/analyzer/config"
"github.com/aquasecurity/fanal/applier"
"github.com/aquasecurity/fanal/artifact/local"
"github.com/aquasecurity/fanal/cache"
"github.com/aquasecurity/fanal/types"
)

type ConfigScanner struct {
cache cache.FSCache
policyPaths []string
dataPaths []string
namespaces []string
}

func NewConfigScanner(cacheDir string, policyPaths, dataPaths, namespaces []string) (*ConfigScanner, error) {
// Initialize local cache
cacheClient, err := cache.NewFSCache(cacheDir)
if err != nil {
return nil, err
}

return &ConfigScanner{
cache: cacheClient,
policyPaths: policyPaths,
dataPaths: dataPaths,
namespaces: namespaces,
}, nil
}

func (s ConfigScanner) Scan(dir string) ([]types.Misconfiguration, error) {
art, err := local.NewArtifact(dir, s.cache, nil, config.ScannerOption{
PolicyPaths: s.policyPaths,
DataPaths: s.dataPaths,
Namespaces: s.namespaces,
})
if err != nil {
return nil, err
}

// Scan config files
result, err := art.Inspect(context.Background())
if err != nil {
return nil, err
}

// Merge layers
a := applier.NewApplier(s.cache)
mergedLayer, err := a.ApplyLayers(result.ID, result.BlobIDs)
if !errors.Is(err, analyzer.ErrUnknownOS) && !errors.Is(err, analyzer.ErrNoPkgsDetected) {
return nil, err
}

// Do not assert successes and layer
for i := range mergedLayer.Misconfigurations {
mergedLayer.Misconfigurations[i].Layer = types.Layer{}
}

return mergedLayer.Misconfigurations, nil
}
88 changes: 88 additions & 0 deletions external/config_scan_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package external_test

import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/aquasecurity/fanal/external"
"github.com/aquasecurity/fanal/types"
)

func TestConfigScanner_Scan(t *testing.T) {
type fields struct {
policyPaths []string
dataPaths []string
namespaces []string
}
tests := []struct {
name string
fields fields
inputDir string
want []types.Misconfiguration
}{
{
name: "deny",
fields: fields{
policyPaths: []string{"testdata/deny"},
namespaces: []string{"testdata"},
},
inputDir: "testdata/deny",
want: []types.Misconfiguration{
{
FileType: "dockerfile",
FilePath: "Dockerfile",
Failures: types.MisconfResults{
{
Namespace: "testdata.xyz_200",
Message: "Old image",
PolicyMetadata: types.PolicyMetadata{
ID: "XYZ-200",
Type: "Docker Security Check",
Title: "Old FROM",
Severity: "LOW",
},
},
},
},
},
},
{
name: "allow",
fields: fields{
policyPaths: []string{"testdata/allow"},
namespaces: []string{"testdata"},
},
inputDir: "testdata/allow",
want: []types.Misconfiguration{
{
FileType: "dockerfile",
FilePath: "Dockerfile",
Successes: types.MisconfResults{
{
Namespace: "testdata.xyz_200",
PolicyMetadata: types.PolicyMetadata{
ID: "XYZ-200",
Type: "Docker Security Check",
Title: "Old FROM",
Severity: "LOW",
},
},
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
s, err := external.NewConfigScanner(t.TempDir(),
tt.fields.policyPaths, tt.fields.dataPaths, tt.fields.namespaces)
require.NoError(t, err)

got, err := s.Scan(tt.inputDir)
require.NoError(t, err)
assert.Equal(t, tt.want, got)
})
}
}
3 changes: 3 additions & 0 deletions external/testdata/allow/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM alpine:3.14

ADD foo.txt .
20 changes: 20 additions & 0 deletions external/testdata/allow/docker.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package testdata.xyz_200

__rego_metadata__ := {
"id": "XYZ-200",
"title": "Old FROM",
"version": "v1.0.0",
"severity": "LOW",
"type": "Docker Security Check",
}

__rego_input__ := {
"combine": false,
"selector": [{"type": "dockerfile"}],
}

deny[msg] {
input.stages[from]
from == "alpine:3.10"
msg := "Old image"
}
3 changes: 3 additions & 0 deletions external/testdata/deny/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM alpine:3.10

ADD foo.txt .
20 changes: 20 additions & 0 deletions external/testdata/deny/docker.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package testdata.xyz_200

__rego_metadata__ := {
"id": "XYZ-200",
"title": "Old FROM",
"version": "v1.0.0",
"severity": "LOW",
"type": "Docker Security Check",
}

__rego_input__ := {
"combine": false,
"selector": [{"type": "dockerfile"}],
}

deny[msg] {
input.stages[from]
from == "alpine:3.10"
msg := "Old image"
}

0 comments on commit f728f19

Please sign in to comment.