/
githubmirror
/
trivy
Обзор
Документация
Войти
/
githubmirror
/
trivy
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
pkg/iac/scanners/cloudformation/parser/parser.go
204 строки
4 KB
Nikita Pivkin
feat(cloudformation): add support for Fn::ForEach (#9508)
11 дек 2025, 21:53
Не верифицирован
11 дек 2025, 21:53
d65b504
Код
Авторство
О чём код?
package parser import ( "context" "fmt" "io" "io/fs" "path" "path/filepath" "strings" "github.com/hashicorp/go-multierror" "gopkg.in/yaml.v3" "github.com/aquasecurity/trivy/pkg/iac/ignore" "github.com/aquasecurity/trivy/pkg/log" xjson "github.com/aquasecurity/trivy/pkg/x/json" ) type Parser struct { logger *log.Logger parameterFiles []string parameters map[string]any overridedParameters Parameters configsFS fs.FS } type Option func(*Parser) func WithParameters(params map[string]any) Option { return func(p *Parser) { p.parameters = params } } func WithParameterFiles(files ...string) Option { return func(p *Parser) { p.parameterFiles = files } } func WithConfigsFS(fsys fs.FS) Option { return func(p *Parser) { p.configsFS = fsys } } func New(opts ...Option) *Parser { p := &Parser{ logger: log.WithPrefix("cloudformation parser"), } for _, option := range opts { option(p) } return p } func (p *Parser) ParseFS(ctx context.Context, fsys fs.FS, dir string) (FileContexts, error) { var contexts FileContexts if err := fs.WalkDir(fsys, filepath.ToSlash(dir), func(path string, entry fs.DirEntry, err error) error { select { case <-ctx.Done(): return ctx.Err() default: } if err != nil { return err } if entry.IsDir() { return nil } c, err := p.ParseFile(ctx, fsys, path) if err != nil { p.logger.Error("Error parsing file", log.FilePath(path), log.Err(err)) return nil } contexts = append(contexts, c) return nil }); err != nil { return nil, err } return contexts, nil } func (p *Parser) ParseFile(ctx context.Context, fsys fs.FS, filePath string) (fctx *FileContext, err error) { defer func() { if e := recover(); e != nil { err = fmt.Errorf("panic during parse: %s", e) } }() select { case <-ctx.Done(): return nil, ctx.Err() default: } if p.configsFS == nil { p.configsFS = fsys } if err := p.parseParams(); err != nil { return nil, fmt.Errorf("failed to parse parameters file: %w", err) } sourceFmt := YamlSourceFormat if path.Ext(filePath) == ".json" { sourceFmt = JsonSourceFormat } f, err := fsys.Open(filePath) if err != nil { return nil, err } defer f.Close() content, err := io.ReadAll(f) if err != nil { return nil, err } lines := strings.Split(string(content), "\n") fctx = &FileContext{ filepath: filePath, lines: lines, SourceFormat: sourceFmt, } switch sourceFmt { case YamlSourceFormat: if err := yaml.Unmarshal(content, fctx); err != nil { return nil, NewErrInvalidContent(filePath, err) } fctx.Ignores = ignore.Parse(string(content), filePath, "") case JsonSourceFormat: if err := xjson.Unmarshal(content, fctx); err != nil { return nil, NewErrInvalidContent(filePath, err) } } fctx.stripNullProperties() fctx.overrideParameters(p.overridedParameters) if params := fctx.missingParameterValues(); len(params) > 0 { p.logger.Warn("Missing parameter values", log.FilePath(filePath), log.String("parameters", strings.Join(params, ", "))) } fctx.lines = lines fctx.SourceFormat = sourceFmt fctx.filepath = filePath p.logger.Debug("Context loaded from source", log.FilePath(filePath)) // the context must be set to conditions before resources for _, c := range fctx.Conditions { c.setContext(fctx) } for name, r := range fctx.Resources { r.configureResource(name, fsys, filePath, fctx) } if err := fctx.expandTransforms(); err != nil { return nil, err } return fctx, nil } func (p *Parser) parseParams() error { if p.overridedParameters != nil { // parameters have already been parsed return nil } params := make(Parameters) var errs error for _, path := range p.parameterFiles { f, err := p.configsFS.Open(path) if err != nil { errs = multierror.Append(errs, fmt.Errorf("open file: %w", err)) continue } if parameters, err := ParseParameters(f); err != nil { errs = multierror.Append(errs, err) } else { params.Merge(parameters) } _ = f.Close() } if errs != nil { return errs } params.Merge(p.parameters) p.overridedParameters = params return nil }