From bd73a4b7956e5695ca71193e600d85ef20111a87 Mon Sep 17 00:00:00 2001 From: Lance Bragstad Date: Thu, 5 Sep 2024 15:16:23 -0500 Subject: [PATCH 1/2] CMP-2734: Detect usage of x/crypto The x/crypto module isn't compatible with FIPS. Let's write a check to see if it is in the symbols for a given binary. Ideally, this should help us find areas where we can remove x/crypto usage altogether. --- internal/types/error_map.go | 1 + internal/types/errors.go | 1 + internal/validations/validations.go | 25 +++++++++++++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/internal/types/error_map.go b/internal/types/error_map.go index 07a828db..a9916361 100644 --- a/internal/types/error_map.go +++ b/internal/types/error_map.go @@ -4,6 +4,7 @@ package types var KnownErrors = map[string]error { "ErrCertifiedDistributionsEmpty": ErrCertifiedDistributionsEmpty, + "ErrDetectedExcludedModule": ErrDetectedExcludedModule, "ErrDistributionFileMissing": ErrDistributionFileMissing, "ErrGoInvalidTag": ErrGoInvalidTag, "ErrGoMissingSymbols": ErrGoMissingSymbols, diff --git a/internal/types/errors.go b/internal/types/errors.go index 9de4780e..80a8e63c 100644 --- a/internal/types/errors.go +++ b/internal/types/errors.go @@ -21,4 +21,5 @@ var ( ErrOSNotCertified = errors.New("operating system is not FIPS certified") ErrDistributionFileMissing = errors.New("could not find distribution file") ErrCertifiedDistributionsEmpty = errors.New("certified_distributions is empty, consider using -V [VERSION] for check-payload") + ErrDetectedExcludedModule = errors.New("detected a library that is incompatible with FIPS, check to make sure it is not performing any cryptographic operations") ) diff --git a/internal/validations/validations.go b/internal/validations/validations.go index 3cb84a23..be2590ea 100644 --- a/internal/validations/validations.go +++ b/internal/validations/validations.go @@ -11,6 +11,7 @@ import ( "fmt" "io" "os" + "os/exec" "path/filepath" "regexp" "strings" @@ -67,6 +68,7 @@ var validationFns = map[string][]ValidationFn{ validateGoStatic, validateGoOpenssl, validateGoTagsAndExperiment, + validateExcludedCryptoModules, }, "exe": { validateNotStatic, @@ -288,6 +290,29 @@ func validateNotStatic(_ context.Context, _ string, baton *Baton) *types.Validat return types.NewValidationError(types.ErrNotDynLinked) } +func validateExcludedCryptoModules(ctx context.Context, path string, baton *Baton) *types.ValidationError { + var symbols bytes.Buffer + cmd := exec.CommandContext(ctx, "nm", "-j", path) + cmd.Stdout = &symbols + if err := cmd.Run(); err != nil { + return types.NewValidationError(err) + } + + // Make this more flexible by deriving the excluded modules from + // configuration. + excluded := []byte("golang.org/x/crypto") + symtable, err := golang.ReadTable(path, baton.GoBuildInfo) + if err != nil { + return types.NewValidationError(fmt.Errorf("go: could not read table for %v: %w", filepath.Base(path), err)) + } + for _, f := range symtable.Funcs { + if strings.Contains(f.Name, string(excluded)) { + return types.NewValidationError(types.ErrDetectedExcludedModule).SetWarning() + } + } + return nil +} + func isGoExecutable(path string, baton *Baton) (bool, error) { bi, err := buildinfo.ReadFile(path) if err != nil { From 7e3909ac85a9e89515be5111526015923074c606 Mon Sep 17 00:00:00 2001 From: davdhacs <105243888+davdhacs@users.noreply.github.com> Date: Thu, 31 Oct 2024 14:09:28 -0600 Subject: [PATCH 2/2] dont stop validatin' hold on --- internal/scan/scan.go | 18 ++++++++++-------- internal/types/types.go | 1 + internal/types/types_scan_result.go | 7 ++++++- internal/validations/validations.go | 7 +++++-- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/internal/scan/scan.go b/internal/scan/scan.go index 1f956b8c..2dfd9c12 100644 --- a/internal/scan/scan.go +++ b/internal/scan/scan.go @@ -457,14 +457,16 @@ func walkDirScan(ctx context.Context, cfg *types.Config, tag *v1.TagReference, c klog.V(1).InfoS("scanning success", "image", getImage(res), "path", innerPath, "status", "success") } else { status := res.Status() - klog.InfoS("scanning "+status, - "image", getImage(res), - "path", innerPath, - "error", res.Error.Error, - "component", getComponent(res), - "tag", getTag(res), - "rpm", res.RPM, - "status", status) + for _, err := range res.Errors { + klog.InfoS("scanning "+status, + "image", getImage(res), + "path", innerPath, + "error", err.Error, + "component", getComponent(res), + "tag", getTag(res), + "rpm", res.RPM, + "status", status) + } } results.Append(res) return nil diff --git a/internal/types/types.go b/internal/types/types.go index 17743830..8c32dbd9 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -75,6 +75,7 @@ type ScanResult struct { Path string Skip bool Error *ValidationError + Errors []*ValidationError } type ScanResults struct { diff --git a/internal/types/types_scan_result.go b/internal/types/types_scan_result.go index c6c8daee..f3a4ef34 100644 --- a/internal/types/types_scan_result.go +++ b/internal/types/types_scan_result.go @@ -73,7 +73,12 @@ func (r *ScanResult) SetOS(info OSInfo) *ScanResult { } func (r *ScanResult) SetValidationError(err *ValidationError) *ScanResult { - r.Error = err + if r.Error != nil { + r.Errors = append(r.Errors, err) + } else { + r.Error = err + r.Errors = append(r.Errors, err) + } return r } diff --git a/internal/validations/validations.go b/internal/validations/validations.go index be2590ea..0a930808 100644 --- a/internal/validations/validations.go +++ b/internal/validations/validations.go @@ -411,6 +411,7 @@ checks: // See if the error is to be ignored. for _, list := range errIgnores { if list.Ignore(innerPath, err.Error) { + klog.Info("ignoring %s for ", err.Error, innerPath) continue checks } } @@ -432,10 +433,12 @@ checks: } } } - return res.SetValidationError(err) + res.SetValidationError(err) } } - + if res.Error != nil { + return res + } return res.Success() }