command-runner/pkg/features/sbom_detector.go (72 lines of code) (raw):

package features import ( "context" "encoding/json" "io/fs" "os" "path/filepath" "strings" "github.com/aws/codecatalyst-runner-cli/command-runner/pkg/common" "github.com/aws/codecatalyst-runner-cli/command-runner/pkg/runner" "github.com/rs/zerolog/log" ) const maxSBOMSize = 10 * 1024 // 10 KB // SBOMDetector is an [ExecutionFeature] to detect SBOMs created by actions. // The content of the detected SBOM is loaded into the sbom provided. func SBOMDetector(directory string, sbom *SBOM) runner.Feature { return func(ctx context.Context, plan runner.Plan, e runner.PlanExecutor) error { log.Ctx(ctx).Debug().Msg("ENTER SBOMDetector") if err := e(ctx); err != nil { return err } err := newSBOMDetector(directory, sbom)(ctx) log.Ctx(ctx).Debug().Msg("EXIT SBOMDetector") return err } } func newSBOMDetector(reportDir string, sbom *SBOM) common.Executor { return func(ctx context.Context) error { return filepath.WalkDir(reportDir, func(path string, d fs.DirEntry, err error) error { if err != nil { return err } if d.IsDir() { return nil } info, err := d.Info() if err != nil { return err } if info.Size() > maxSBOMSize { log.Ctx(ctx).Debug().Msgf("Skipping potential SBOM '%s'- too large. %d > %d, path", path, info.Size(), maxSBOMSize) return nil } content, err := os.ReadFile(path) if err != nil { log.Ctx(ctx).Warn().Msgf("Unable to read potential SBOM '%s': %s", path, err.Error()) return nil } data := make(map[string]interface{}) err = json.Unmarshal(content, &data) if err != nil { log.Ctx(ctx).Debug().Msgf("Unable to unmarshal potential SBOM '%s': %s", path, err.Error()) return nil } for key := range data { if strings.EqualFold(key, "spdxVersion") || strings.EqualFold(key, "SPDXID") { log.Ctx(ctx).Debug().Msgf("Found SBOM '%s' with type %s", path, sbom.Type) sbom.Content = content sbom.Type = SBOMTypeSPDX break } } return nil }) } } // SBOMType - Currently only SPDX is supported type SBOMType string const ( // SBOMTypeSPDX is the SPDX SBOM type SBOMTypeSPDX SBOMType = "https://spdx.dev/Document" ) // SBOM represents a detected SBOM (Software Bill of Materials) type SBOM struct { Type SBOMType // type of SBOM Content []byte // content of the SBOM }