mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-05 20:40:16 -08:00
feat(misconf): add option to pass Rego scanner to IaC scanner (#8369)
Signed-off-by: nikpivkin <nikita.pivkin@smartforce.io> Co-authored-by: simar7 <1254783+simar7@users.noreply.github.com> Co-authored-by: Simar <simar@linux.com>
This commit is contained in:
@@ -662,7 +662,7 @@ func initMisconfScannerOption(ctx context.Context, opts flag.Options) (misconf.S
|
||||
return misconf.ScannerOption{}, xerrors.Errorf("load schemas error: %w", err)
|
||||
}
|
||||
|
||||
return misconf.ScannerOption{
|
||||
misconfOpts := misconf.ScannerOption{
|
||||
Trace: opts.Trace,
|
||||
Namespaces: append(opts.CheckNamespaces, rego.BuiltinNamespaces()...),
|
||||
PolicyPaths: policyPaths,
|
||||
@@ -684,5 +684,13 @@ func initMisconfScannerOption(ctx context.Context, opts flag.Options) (misconf.S
|
||||
ConfigFileSchemas: configSchemas,
|
||||
SkipFiles: opts.SkipFiles,
|
||||
SkipDirs: opts.SkipDirs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
regoScanner, err := misconf.InitRegoScanner(misconfOpts)
|
||||
if err != nil {
|
||||
return misconf.ScannerOption{}, xerrors.Errorf("init Rego scanner: %w", err)
|
||||
}
|
||||
|
||||
misconfOpts.RegoScanner = regoScanner
|
||||
return misconfOpts, nil
|
||||
}
|
||||
|
||||
43
pkg/iac/rego/provider.go
Normal file
43
pkg/iac/rego/provider.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package rego
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"sync"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/iac/scanners/options"
|
||||
)
|
||||
|
||||
func WithRegoScanner(rs *Scanner) options.ScannerOption {
|
||||
return func(s options.ConfigurableScanner) {
|
||||
if ss, ok := s.(*RegoScannerProvider); ok {
|
||||
ss.regoScanner = rs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type RegoScannerProvider struct {
|
||||
mu sync.Mutex
|
||||
regoScanner *Scanner
|
||||
}
|
||||
|
||||
func NewRegoScannerProvider(opts ...options.ScannerOption) *RegoScannerProvider {
|
||||
s := &RegoScannerProvider{}
|
||||
for _, o := range opts {
|
||||
o(s)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *RegoScannerProvider) InitRegoScanner(fsys fs.FS, opts []options.ScannerOption) (*Scanner, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.regoScanner != nil {
|
||||
return s.regoScanner, nil
|
||||
}
|
||||
s.regoScanner = NewScanner(opts...)
|
||||
if err := s.regoScanner.LoadPolicies(fsys); err != nil {
|
||||
return nil, fmt.Errorf("load checks: %w", err)
|
||||
}
|
||||
return s.regoScanner, nil
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"sync"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/iac/adapters/arm"
|
||||
"github.com/aquasecurity/trivy/pkg/iac/rego"
|
||||
@@ -13,7 +12,6 @@ import (
|
||||
"github.com/aquasecurity/trivy/pkg/iac/scanners/azure"
|
||||
"github.com/aquasecurity/trivy/pkg/iac/scanners/azure/arm/parser"
|
||||
"github.com/aquasecurity/trivy/pkg/iac/scanners/options"
|
||||
"github.com/aquasecurity/trivy/pkg/iac/state"
|
||||
"github.com/aquasecurity/trivy/pkg/iac/types"
|
||||
"github.com/aquasecurity/trivy/pkg/log"
|
||||
)
|
||||
@@ -22,16 +20,16 @@ var _ scanners.FSScanner = (*Scanner)(nil)
|
||||
var _ options.ConfigurableScanner = (*Scanner)(nil)
|
||||
|
||||
type Scanner struct {
|
||||
mu sync.Mutex
|
||||
scannerOptions []options.ScannerOption
|
||||
logger *log.Logger
|
||||
regoScanner *rego.Scanner
|
||||
*rego.RegoScannerProvider
|
||||
opts []options.ScannerOption
|
||||
logger *log.Logger
|
||||
}
|
||||
|
||||
func New(opts ...options.ScannerOption) *Scanner {
|
||||
scanner := &Scanner{
|
||||
scannerOptions: opts,
|
||||
logger: log.WithPrefix("azure-arm"),
|
||||
RegoScannerProvider: rego.NewRegoScannerProvider(opts...),
|
||||
opts: opts,
|
||||
logger: log.WithPrefix("azure-arm"),
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(scanner)
|
||||
@@ -43,29 +41,12 @@ func (s *Scanner) Name() string {
|
||||
return "Azure ARM"
|
||||
}
|
||||
|
||||
func (s *Scanner) initRegoScanner(srcFS fs.FS) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.regoScanner != nil {
|
||||
return nil
|
||||
}
|
||||
regoScanner := rego.NewScanner(s.scannerOptions...)
|
||||
if err := regoScanner.LoadPolicies(srcFS); err != nil {
|
||||
return err
|
||||
}
|
||||
s.regoScanner = regoScanner
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Scanner) ScanFS(ctx context.Context, fsys fs.FS, dir string) (scan.Results, error) {
|
||||
p := parser.New(fsys)
|
||||
deployments, err := p.ParseFS(ctx, dir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := s.initRegoScanner(fsys); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.scanDeployments(ctx, deployments, fsys)
|
||||
}
|
||||
@@ -87,12 +68,17 @@ func (s *Scanner) scanDeployments(ctx context.Context, deployments []azure.Deplo
|
||||
}
|
||||
|
||||
func (s *Scanner) scanDeployment(ctx context.Context, deployment azure.Deployment, fsys fs.FS) (scan.Results, error) {
|
||||
deploymentState := s.adaptDeployment(ctx, deployment)
|
||||
state := arm.Adapt(ctx, deployment)
|
||||
|
||||
results, err := s.regoScanner.ScanInput(ctx, types.SourceCloud, rego.Input{
|
||||
rs, err := s.InitRegoScanner(fsys, s.opts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("init rego scanner: %w", err)
|
||||
}
|
||||
|
||||
results, err := rs.ScanInput(ctx, types.SourceCloud, rego.Input{
|
||||
Path: deployment.Metadata.Range().GetFilename(),
|
||||
FS: fsys,
|
||||
Contents: deploymentState.ToRego(),
|
||||
Contents: state.ToRego(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("rego scan error: %w", err)
|
||||
@@ -100,7 +86,3 @@ func (s *Scanner) scanDeployment(ctx context.Context, deployment azure.Deploymen
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s *Scanner) adaptDeployment(ctx context.Context, deployment azure.Deployment) *state.State {
|
||||
return arm.Adapt(ctx, deployment)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
adapter "github.com/aquasecurity/trivy/pkg/iac/adapters/cloudformation"
|
||||
"github.com/aquasecurity/trivy/pkg/iac/rego"
|
||||
@@ -45,10 +44,9 @@ var _ scanners.FSScanner = (*Scanner)(nil)
|
||||
var _ options.ConfigurableScanner = (*Scanner)(nil)
|
||||
|
||||
type Scanner struct {
|
||||
mu sync.Mutex
|
||||
*rego.RegoScannerProvider
|
||||
logger *log.Logger
|
||||
parser *parser.Parser
|
||||
regoScanner *rego.Scanner
|
||||
options []options.ScannerOption
|
||||
parserOptions []parser.Option
|
||||
}
|
||||
@@ -64,8 +62,9 @@ func (s *Scanner) Name() string {
|
||||
// New creates a new Scanner
|
||||
func New(opts ...options.ScannerOption) *Scanner {
|
||||
s := &Scanner{
|
||||
options: opts,
|
||||
logger: log.WithPrefix("cloudformation scanner"),
|
||||
RegoScannerProvider: rego.NewRegoScannerProvider(opts...),
|
||||
options: opts,
|
||||
logger: log.WithPrefix("cloudformation scanner"),
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(s)
|
||||
@@ -74,20 +73,6 @@ func New(opts ...options.ScannerOption) *Scanner {
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Scanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.regoScanner != nil {
|
||||
return s.regoScanner, nil
|
||||
}
|
||||
regoScanner := rego.NewScanner(s.options...)
|
||||
if err := regoScanner.LoadPolicies(srcFS); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.regoScanner = regoScanner
|
||||
return regoScanner, nil
|
||||
}
|
||||
|
||||
func (s *Scanner) ScanFS(ctx context.Context, fsys fs.FS, dir string) (results scan.Results, err error) {
|
||||
|
||||
contexts, err := s.parser.ParseFS(ctx, fsys, dir)
|
||||
@@ -99,16 +84,16 @@ func (s *Scanner) ScanFS(ctx context.Context, fsys fs.FS, dir string) (results s
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
regoScanner, err := s.initRegoScanner(fsys)
|
||||
rs, err := s.InitRegoScanner(fsys, s.options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("init rego scanner: %w", err)
|
||||
}
|
||||
|
||||
for _, cfCtx := range contexts {
|
||||
if cfCtx == nil {
|
||||
continue
|
||||
}
|
||||
fileResults, err := s.scanFileContext(ctx, regoScanner, cfCtx, fsys)
|
||||
fileResults, err := s.scanFileContext(ctx, rs, cfCtx, fsys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -127,12 +112,12 @@ func (s *Scanner) ScanFile(ctx context.Context, fsys fs.FS, path string) (scan.R
|
||||
return nil, err
|
||||
}
|
||||
|
||||
regoScanner, err := s.initRegoScanner(fsys)
|
||||
rs, err := s.InitRegoScanner(fsys, s.options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("init rego scanner: %w", err)
|
||||
}
|
||||
|
||||
results, err := s.scanFileContext(ctx, regoScanner, cfCtx, fsys)
|
||||
results, err := s.scanFileContext(ctx, rs, cfCtx, fsys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -572,7 +572,7 @@ COPY --from=dep /binary /`
|
||||
|
||||
results, err := scanner.ScanFS(t.Context(), fsys, "code")
|
||||
if tc.expectedError != "" && err != nil {
|
||||
require.Equal(t, tc.expectedError, err.Error(), tc.name)
|
||||
require.ErrorContainsf(t, err, tc.expectedError, tc.name)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.Len(t, results.GetFailed(), 1)
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"io/fs"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/samber/lo"
|
||||
@@ -41,12 +40,11 @@ type configParser interface {
|
||||
|
||||
// GenericScanner is a scanner that scans a file as is without processing it
|
||||
type GenericScanner struct {
|
||||
mu sync.Mutex
|
||||
name string
|
||||
source types.Source
|
||||
logger *log.Logger
|
||||
options []options.ScannerOption
|
||||
regoScanner *rego.Scanner
|
||||
*rego.RegoScannerProvider
|
||||
name string
|
||||
source types.Source
|
||||
logger *log.Logger
|
||||
options []options.ScannerOption
|
||||
|
||||
parser configParser
|
||||
}
|
||||
@@ -59,11 +57,12 @@ func (f ParseFunc) Parse(ctx context.Context, r io.Reader, path string) (any, er
|
||||
|
||||
func NewScanner(name string, source types.Source, parser configParser, opts ...options.ScannerOption) *GenericScanner {
|
||||
s := &GenericScanner{
|
||||
name: name,
|
||||
options: opts,
|
||||
source: source,
|
||||
logger: log.WithPrefix(fmt.Sprintf("%s scanner", source)),
|
||||
parser: parser,
|
||||
RegoScannerProvider: rego.NewRegoScannerProvider(opts...),
|
||||
name: name,
|
||||
options: opts,
|
||||
source: source,
|
||||
logger: log.WithPrefix(fmt.Sprintf("%s scanner", source)),
|
||||
parser: parser,
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
@@ -113,13 +112,13 @@ func (s *GenericScanner) ScanFS(ctx context.Context, fsys fs.FS, dir string) (sc
|
||||
}
|
||||
}
|
||||
|
||||
regoScanner, err := s.initRegoScanner(fsys)
|
||||
rs, err := s.InitRegoScanner(fsys, s.options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("init rego scanner: %w", err)
|
||||
}
|
||||
|
||||
s.logger.Debug("Scanning files...", log.Int("count", len(inputs)))
|
||||
results, err := regoScanner.ScanInput(ctx, s.source, inputs...)
|
||||
results, err := rs.ScanInput(ctx, s.source, inputs...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -170,20 +169,6 @@ func (s *GenericScanner) parseFS(ctx context.Context, fsys fs.FS, path string) (
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func (s *GenericScanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.regoScanner != nil {
|
||||
return s.regoScanner, nil
|
||||
}
|
||||
regoScanner := rego.NewScanner(s.options...)
|
||||
if err := regoScanner.LoadPolicies(srcFS); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.regoScanner = regoScanner
|
||||
return regoScanner, nil
|
||||
}
|
||||
|
||||
func (s *GenericScanner) applyIgnoreRules(fsys fs.FS, results scan.Results) error {
|
||||
if !s.supportsIgnoreRules() {
|
||||
return nil
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/liamg/memoryfs"
|
||||
"helm.sh/helm/v3/pkg/chartutil"
|
||||
@@ -29,18 +28,18 @@ var _ scanners.FSScanner = (*Scanner)(nil)
|
||||
var _ options.ConfigurableScanner = (*Scanner)(nil)
|
||||
|
||||
type Scanner struct {
|
||||
mu sync.Mutex
|
||||
*rego.RegoScannerProvider
|
||||
logger *log.Logger
|
||||
options []options.ScannerOption
|
||||
parserOptions []parser.Option
|
||||
regoScanner *rego.Scanner
|
||||
}
|
||||
|
||||
// New creates a new Scanner
|
||||
func New(opts ...options.ScannerOption) *Scanner {
|
||||
s := &Scanner{
|
||||
options: opts,
|
||||
logger: log.WithPrefix("helm scanner"),
|
||||
RegoScannerProvider: rego.NewRegoScannerProvider(opts...),
|
||||
options: opts,
|
||||
logger: log.WithPrefix("helm scanner"),
|
||||
}
|
||||
|
||||
for _, option := range opts {
|
||||
@@ -58,11 +57,6 @@ func (s *Scanner) Name() string {
|
||||
}
|
||||
|
||||
func (s *Scanner) ScanFS(ctx context.Context, fsys fs.FS, dir string) (scan.Results, error) {
|
||||
|
||||
if err := s.initRegoScanner(fsys); err != nil {
|
||||
return nil, fmt.Errorf("failed to init rego scanner: %w", err)
|
||||
}
|
||||
|
||||
var results []scan.Result
|
||||
if err := fs.WalkDir(fsys, dir, func(filePath string, d fs.DirEntry, err error) error {
|
||||
select {
|
||||
@@ -122,6 +116,11 @@ func (s *Scanner) getScanResults(path string, ctx context.Context, target fs.FS)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
rs, err := s.InitRegoScanner(target, s.options)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("init rego scanner: %w", err)
|
||||
}
|
||||
|
||||
for _, file := range chartFiles {
|
||||
file := file
|
||||
s.logger.Debug("Processing rendered chart file", log.FilePath(file.TemplateFilePath))
|
||||
@@ -132,7 +131,7 @@ func (s *Scanner) getScanResults(path string, ctx context.Context, target fs.FS)
|
||||
return nil, fmt.Errorf("unmarshal yaml: %w", err)
|
||||
}
|
||||
for _, manifest := range manifests {
|
||||
fileResults, err := s.regoScanner.ScanInput(ctx, types.SourceKubernetes, rego.Input{
|
||||
fileResults, err := rs.ScanInput(ctx, types.SourceKubernetes, rego.Input{
|
||||
Path: file.TemplateFilePath,
|
||||
Contents: manifest,
|
||||
FS: target,
|
||||
@@ -161,17 +160,3 @@ func (s *Scanner) getScanResults(path string, ctx context.Context, target fs.FS)
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s *Scanner) initRegoScanner(srcFS fs.FS) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.regoScanner != nil {
|
||||
return nil
|
||||
}
|
||||
regoScanner := rego.NewScanner(s.options...)
|
||||
if err := regoScanner.LoadPolicies(srcFS); err != nil {
|
||||
return err
|
||||
}
|
||||
s.regoScanner = regoScanner
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,15 +3,10 @@ package scanners
|
||||
import (
|
||||
"context"
|
||||
"io/fs"
|
||||
"os"
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/iac/scan"
|
||||
)
|
||||
|
||||
type WriteFileFS interface {
|
||||
WriteFile(name string, data []byte, perm os.FileMode) error
|
||||
}
|
||||
|
||||
type FSScanner interface {
|
||||
// Name provides the human-readable name of the scanner e.g. "CloudFormation"
|
||||
Name() string
|
||||
|
||||
@@ -26,14 +26,13 @@ var _ options.ConfigurableScanner = (*Scanner)(nil)
|
||||
var _ ConfigurableTerraformScanner = (*Scanner)(nil)
|
||||
|
||||
type Scanner struct {
|
||||
mu sync.Mutex
|
||||
*rego.RegoScannerProvider
|
||||
logger *log.Logger
|
||||
options []options.ScannerOption
|
||||
parserOpt []parser.Option
|
||||
executorOpt []executor.Option
|
||||
dirs set.Set[string]
|
||||
forceAllDirs bool
|
||||
regoScanner *rego.Scanner
|
||||
execLock sync.RWMutex
|
||||
}
|
||||
|
||||
@@ -55,9 +54,10 @@ func (s *Scanner) AddExecutorOptions(opts ...executor.Option) {
|
||||
|
||||
func New(opts ...options.ScannerOption) *Scanner {
|
||||
s := &Scanner{
|
||||
dirs: set.New[string](),
|
||||
options: opts,
|
||||
logger: log.WithPrefix("terraform scanner"),
|
||||
RegoScannerProvider: rego.NewRegoScannerProvider(opts...),
|
||||
dirs: set.New[string](),
|
||||
options: opts,
|
||||
logger: log.WithPrefix("terraform scanner"),
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(s)
|
||||
@@ -65,20 +65,6 @@ func New(opts ...options.ScannerOption) *Scanner {
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Scanner) initRegoScanner(srcFS fs.FS) (*rego.Scanner, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.regoScanner != nil {
|
||||
return s.regoScanner, nil
|
||||
}
|
||||
regoScanner := rego.NewScanner(s.options...)
|
||||
if err := regoScanner.LoadPolicies(srcFS); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.regoScanner = regoScanner
|
||||
return regoScanner, nil
|
||||
}
|
||||
|
||||
// terraformRootModule represents the module to be used as the root module for Terraform deployment.
|
||||
type terraformRootModule struct {
|
||||
rootPath string
|
||||
@@ -99,13 +85,13 @@ func (s *Scanner) ScanFS(ctx context.Context, target fs.FS, dir string) (scan.Re
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
regoScanner, err := s.initRegoScanner(target)
|
||||
rs, err := s.InitRegoScanner(target, s.options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("init rego scanner: %w", err)
|
||||
}
|
||||
|
||||
s.execLock.Lock()
|
||||
s.executorOpt = append(s.executorOpt, executor.OptionWithRegoScanner(regoScanner))
|
||||
s.executorOpt = append(s.executorOpt, executor.OptionWithRegoScanner(rs))
|
||||
s.execLock.Unlock()
|
||||
|
||||
var allResults scan.Results
|
||||
|
||||
@@ -9,12 +9,12 @@ import (
|
||||
|
||||
"github.com/aquasecurity/trivy/pkg/iac/scan"
|
||||
"github.com/aquasecurity/trivy/pkg/iac/scanners/options"
|
||||
terraformScanner "github.com/aquasecurity/trivy/pkg/iac/scanners/terraform"
|
||||
tfscanner "github.com/aquasecurity/trivy/pkg/iac/scanners/terraform"
|
||||
tfparser "github.com/aquasecurity/trivy/pkg/iac/scanners/terraform/parser"
|
||||
)
|
||||
|
||||
type Scanner struct {
|
||||
inner *terraformScanner.Scanner
|
||||
inner *tfscanner.Scanner
|
||||
}
|
||||
|
||||
func (s *Scanner) Name() string {
|
||||
@@ -23,7 +23,7 @@ func (s *Scanner) Name() string {
|
||||
|
||||
func New(opts ...options.ScannerOption) *Scanner {
|
||||
scanner := &Scanner{
|
||||
inner: terraformScanner.New(opts...),
|
||||
inner: tfscanner.New(opts...),
|
||||
}
|
||||
return scanner
|
||||
}
|
||||
|
||||
@@ -14,10 +14,10 @@ import (
|
||||
)
|
||||
|
||||
type Scanner struct {
|
||||
parser *parser.Parser
|
||||
logger *log.Logger
|
||||
options []options.ScannerOption
|
||||
tfScanner *terraform.Scanner
|
||||
inner *terraform.Scanner
|
||||
parser *parser.Parser
|
||||
logger *log.Logger
|
||||
options []options.ScannerOption
|
||||
}
|
||||
|
||||
func (s *Scanner) Name() string {
|
||||
@@ -55,10 +55,10 @@ func (s *Scanner) ScanFS(ctx context.Context, fsys fs.FS, dir string) (scan.Resu
|
||||
|
||||
func New(opts ...options.ScannerOption) *Scanner {
|
||||
scanner := &Scanner{
|
||||
options: opts,
|
||||
logger: log.WithPrefix("tfjson scanner"),
|
||||
parser: parser.New(),
|
||||
tfScanner: terraform.New(opts...),
|
||||
inner: terraform.New(opts...),
|
||||
parser: parser.New(),
|
||||
logger: log.WithPrefix("tfjson scanner"),
|
||||
options: opts,
|
||||
}
|
||||
|
||||
return scanner
|
||||
@@ -87,5 +87,5 @@ func (s *Scanner) Scan(reader io.Reader) (scan.Results, error) {
|
||||
return nil, fmt.Errorf("failed to convert plan to FS: %w", err)
|
||||
}
|
||||
|
||||
return s.tfScanner.ScanFS(context.TODO(), planFS, ".")
|
||||
return s.inner.ScanFS(context.TODO(), planFS, ".")
|
||||
}
|
||||
|
||||
@@ -82,6 +82,8 @@ type ScannerOption struct {
|
||||
DisabledChecks []DisabledCheck
|
||||
SkipFiles []string
|
||||
SkipDirs []string
|
||||
|
||||
RegoScanner *rego.Scanner
|
||||
}
|
||||
|
||||
func (o *ScannerOption) Sort() {
|
||||
@@ -216,7 +218,21 @@ func (s *Scanner) filterFS(fsys fs.FS) (fs.FS, error) {
|
||||
return newfs, nil
|
||||
}
|
||||
|
||||
func scannerOptions(t detection.FileType, opt ScannerOption) ([]options.ScannerOption, error) {
|
||||
func InitRegoScanner(opt ScannerOption) (*rego.Scanner, error) {
|
||||
regoOpts, err := initRegoOptions(opt)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("init rego options: %w", err)
|
||||
}
|
||||
regoScanner := rego.NewScanner(regoOpts...)
|
||||
// note: it is safe to pass nil as fsys, since checks and data files will be loaded
|
||||
// from the filesystems passed through the options.
|
||||
if err := regoScanner.LoadPolicies(nil); err != nil {
|
||||
return nil, xerrors.Errorf("load checks: %w", err)
|
||||
}
|
||||
return regoScanner, nil
|
||||
}
|
||||
|
||||
func initRegoOptions(opt ScannerOption) ([]options.ScannerOption, error) {
|
||||
disabledCheckIDs := lo.Map(opt.DisabledChecks, func(check DisabledCheck, _ int) string {
|
||||
log.Info("Check disabled", log.Prefix(log.PrefixMisconfiguration), log.String("ID", check.ID),
|
||||
log.String("scanner", check.Scanner), log.String("reason", check.Reason))
|
||||
@@ -268,6 +284,23 @@ func scannerOptions(t detection.FileType, opt ScannerOption) ([]options.ScannerO
|
||||
if len(opt.Namespaces) > 0 {
|
||||
opts = append(opts, rego.WithPolicyNamespaces(opt.Namespaces...))
|
||||
}
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
func scannerOptions(t detection.FileType, opt ScannerOption) ([]options.ScannerOption, error) {
|
||||
var opts []options.ScannerOption
|
||||
|
||||
if opt.RegoScanner != nil {
|
||||
opts = append(opts, rego.WithRegoScanner(opt.RegoScanner))
|
||||
} else {
|
||||
// If RegoScanner is not provided, pass the Rego options to IaC scanners
|
||||
// so that they can initialize the Rego scanner themselves
|
||||
regoOpts, err := initRegoOptions(opt)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("init rego opts: %w", err)
|
||||
}
|
||||
opts = append(opts, regoOpts...)
|
||||
}
|
||||
|
||||
switch t {
|
||||
case detection.FileTypeHelm:
|
||||
|
||||
Reference in New Issue
Block a user