github.com/nextlinux/gosbom@v0.81.1-0.20230627115839-1ff50c281391/cmd/gosbom/cli/eventloop/tasks.go (about)

     1  package eventloop
     2  
     3  import (
     4  	"crypto"
     5  	"fmt"
     6  
     7  	"github.com/nextlinux/gosbom/gosbom"
     8  	"github.com/nextlinux/gosbom/gosbom/artifact"
     9  	"github.com/nextlinux/gosbom/gosbom/file"
    10  	"github.com/nextlinux/gosbom/gosbom/file/cataloger/filecontent"
    11  	"github.com/nextlinux/gosbom/gosbom/file/cataloger/filedigest"
    12  	"github.com/nextlinux/gosbom/gosbom/file/cataloger/filemetadata"
    13  	"github.com/nextlinux/gosbom/gosbom/file/cataloger/secrets"
    14  	"github.com/nextlinux/gosbom/gosbom/sbom"
    15  	"github.com/nextlinux/gosbom/gosbom/source"
    16  	"github.com/nextlinux/gosbom/internal/config"
    17  )
    18  
    19  type Task func(*sbom.Artifacts, *source.Source) ([]artifact.Relationship, error)
    20  
    21  func Tasks(app *config.Application) ([]Task, error) {
    22  	var tasks []Task
    23  
    24  	generators := []func(app *config.Application) (Task, error){
    25  		generateCatalogPackagesTask,
    26  		generateCatalogFileMetadataTask,
    27  		generateCatalogFileDigestsTask,
    28  		generateCatalogSecretsTask,
    29  		generateCatalogContentsTask,
    30  	}
    31  
    32  	for _, generator := range generators {
    33  		task, err := generator(app)
    34  		if err != nil {
    35  			return nil, err
    36  		}
    37  
    38  		if task != nil {
    39  			tasks = append(tasks, task)
    40  		}
    41  	}
    42  
    43  	return tasks, nil
    44  }
    45  
    46  func generateCatalogPackagesTask(app *config.Application) (Task, error) {
    47  	if !app.Package.Cataloger.Enabled {
    48  		return nil, nil
    49  	}
    50  
    51  	task := func(results *sbom.Artifacts, src *source.Source) ([]artifact.Relationship, error) {
    52  		packageCatalog, relationships, theDistro, err := gosbom.CatalogPackages(src, app.ToCatalogerConfig())
    53  
    54  		results.Packages = packageCatalog
    55  		results.LinuxDistribution = theDistro
    56  
    57  		return relationships, err
    58  	}
    59  
    60  	return task, nil
    61  }
    62  
    63  func generateCatalogFileMetadataTask(app *config.Application) (Task, error) {
    64  	if !app.FileMetadata.Cataloger.Enabled {
    65  		return nil, nil
    66  	}
    67  
    68  	metadataCataloger := filemetadata.NewCataloger()
    69  
    70  	task := func(results *sbom.Artifacts, src *source.Source) ([]artifact.Relationship, error) {
    71  		resolver, err := src.FileResolver(app.FileMetadata.Cataloger.ScopeOpt)
    72  		if err != nil {
    73  			return nil, err
    74  		}
    75  
    76  		result, err := metadataCataloger.Catalog(resolver)
    77  		if err != nil {
    78  			return nil, err
    79  		}
    80  		results.FileMetadata = result
    81  		return nil, nil
    82  	}
    83  
    84  	return task, nil
    85  }
    86  
    87  func generateCatalogFileDigestsTask(app *config.Application) (Task, error) {
    88  	if !app.FileMetadata.Cataloger.Enabled {
    89  		return nil, nil
    90  	}
    91  
    92  	supportedHashAlgorithms := make(map[string]crypto.Hash)
    93  	for _, h := range []crypto.Hash{
    94  		crypto.MD5,
    95  		crypto.SHA1,
    96  		crypto.SHA256,
    97  	} {
    98  		supportedHashAlgorithms[file.DigestAlgorithmName(h)] = h
    99  	}
   100  
   101  	var hashes []crypto.Hash
   102  	for _, hashStr := range app.FileMetadata.Digests {
   103  		name := file.CleanDigestAlgorithmName(hashStr)
   104  		hashObj, ok := supportedHashAlgorithms[name]
   105  		if !ok {
   106  			return nil, fmt.Errorf("unsupported hash algorithm: %s", hashStr)
   107  		}
   108  		hashes = append(hashes, hashObj)
   109  	}
   110  
   111  	digestsCataloger := filedigest.NewCataloger(hashes)
   112  
   113  	task := func(results *sbom.Artifacts, src *source.Source) ([]artifact.Relationship, error) {
   114  		resolver, err := src.FileResolver(app.FileMetadata.Cataloger.ScopeOpt)
   115  		if err != nil {
   116  			return nil, err
   117  		}
   118  
   119  		result, err := digestsCataloger.Catalog(resolver)
   120  		if err != nil {
   121  			return nil, err
   122  		}
   123  		results.FileDigests = result
   124  		return nil, nil
   125  	}
   126  
   127  	return task, nil
   128  }
   129  
   130  func generateCatalogSecretsTask(app *config.Application) (Task, error) {
   131  	if !app.Secrets.Cataloger.Enabled {
   132  		return nil, nil
   133  	}
   134  
   135  	patterns, err := secrets.GenerateSearchPatterns(secrets.DefaultSecretsPatterns, app.Secrets.AdditionalPatterns, app.Secrets.ExcludePatternNames)
   136  	if err != nil {
   137  		return nil, err
   138  	}
   139  
   140  	secretsCataloger, err := secrets.NewCataloger(patterns, app.Secrets.RevealValues, app.Secrets.SkipFilesAboveSize) //nolint:staticcheck
   141  	if err != nil {
   142  		return nil, err
   143  	}
   144  
   145  	task := func(results *sbom.Artifacts, src *source.Source) ([]artifact.Relationship, error) {
   146  		resolver, err := src.FileResolver(app.Secrets.Cataloger.ScopeOpt)
   147  		if err != nil {
   148  			return nil, err
   149  		}
   150  
   151  		result, err := secretsCataloger.Catalog(resolver)
   152  		if err != nil {
   153  			return nil, err
   154  		}
   155  		results.Secrets = result
   156  		return nil, nil
   157  	}
   158  
   159  	return task, nil
   160  }
   161  
   162  func generateCatalogContentsTask(app *config.Application) (Task, error) {
   163  	if !app.FileContents.Cataloger.Enabled {
   164  		return nil, nil
   165  	}
   166  
   167  	contentsCataloger, err := filecontent.NewCataloger(app.FileContents.Globs, app.FileContents.SkipFilesAboveSize) //nolint:staticcheck
   168  	if err != nil {
   169  		return nil, err
   170  	}
   171  
   172  	task := func(results *sbom.Artifacts, src *source.Source) ([]artifact.Relationship, error) {
   173  		resolver, err := src.FileResolver(app.FileContents.Cataloger.ScopeOpt)
   174  		if err != nil {
   175  			return nil, err
   176  		}
   177  
   178  		result, err := contentsCataloger.Catalog(resolver)
   179  		if err != nil {
   180  			return nil, err
   181  		}
   182  		results.FileContents = result
   183  		return nil, nil
   184  	}
   185  
   186  	return task, nil
   187  }
   188  
   189  func RunTask(t Task, a *sbom.Artifacts, src *source.Source, c chan<- artifact.Relationship, errs chan<- error) {
   190  	defer close(c)
   191  
   192  	relationships, err := t(a, src)
   193  	if err != nil {
   194  		errs <- err
   195  		return
   196  	}
   197  
   198  	for _, relationship := range relationships {
   199  		c <- relationship
   200  	}
   201  }