github.com/google/osv-scalibr@v0.4.1/plugin/list/list.go (about)

     1  // Copyright 2025 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package list provides a functions for accessing SCALIBR-specific plugins from their respective type-specific lists.
    16  package list
    17  
    18  import (
    19  	"fmt"
    20  
    21  	"github.com/google/osv-scalibr/annotator"
    22  	al "github.com/google/osv-scalibr/annotator/list"
    23  	"github.com/google/osv-scalibr/detector"
    24  	dl "github.com/google/osv-scalibr/detector/list"
    25  	"github.com/google/osv-scalibr/enricher"
    26  	el "github.com/google/osv-scalibr/enricher/enricherlist"
    27  	"github.com/google/osv-scalibr/extractor/filesystem"
    28  	fl "github.com/google/osv-scalibr/extractor/filesystem/list"
    29  	"github.com/google/osv-scalibr/extractor/standalone"
    30  	sl "github.com/google/osv-scalibr/extractor/standalone/list"
    31  	"github.com/google/osv-scalibr/plugin"
    32  
    33  	cpb "github.com/google/osv-scalibr/binary/proto/config_go_proto"
    34  )
    35  
    36  // FromCapabilities returns all plugins that can run under the specified
    37  // capabilities (OS, direct filesystem access, network access, etc.) of the
    38  // scanning environment.
    39  func FromCapabilities(capabs *plugin.Capabilities, cfg *cpb.PluginConfig) []plugin.Plugin {
    40  	return plugin.FilterByCapabilities(All(cfg), capabs)
    41  }
    42  
    43  // FromNames returns a deduplicated list of plugins from a list of names.
    44  func FromNames(names []string, cfg *cpb.PluginConfig) ([]plugin.Plugin, error) {
    45  	if cfg == nil {
    46  		// Do the nil check here instead of in individual plugin initers.
    47  		cfg = &cpb.PluginConfig{}
    48  	}
    49  	resultMap := make(map[string]plugin.Plugin)
    50  	for _, name := range names {
    51  		fsex, ferr := fl.ExtractorsFromName(name, cfg)
    52  		stex, serr := sl.ExtractorsFromName(name, cfg)
    53  		det, derr := dl.DetectorsFromName(name, cfg)
    54  		ann, aerr := al.AnnotatorsFromName(name, cfg)
    55  		enr, eerr := el.EnrichersFromName(name, cfg)
    56  
    57  		// Report an error if none of the type-specific lists were able to resolve the name.
    58  		if ferr != nil && serr != nil && derr != nil && aerr != nil && eerr != nil {
    59  			return nil, fmt.Errorf("unknown plugin %q", name)
    60  		}
    61  
    62  		for _, p := range fsex {
    63  			resultMap[p.Name()] = p
    64  		}
    65  		for _, p := range stex {
    66  			resultMap[p.Name()] = p
    67  		}
    68  		for _, p := range det {
    69  			resultMap[p.Name()] = p
    70  		}
    71  		for _, p := range ann {
    72  			resultMap[p.Name()] = p
    73  		}
    74  		for _, p := range enr {
    75  			resultMap[p.Name()] = p
    76  		}
    77  	}
    78  
    79  	result := make([]plugin.Plugin, 0, len(resultMap))
    80  	for _, e := range resultMap {
    81  		result = append(result, e)
    82  	}
    83  	return result, nil
    84  }
    85  
    86  // FromName returns a single plugin based on its exact name.
    87  func FromName(name string, cfg *cpb.PluginConfig) (plugin.Plugin, error) {
    88  	plugins, err := FromNames([]string{name}, cfg)
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  	if len(plugins) != 1 {
    93  		return nil, fmt.Errorf("not an exact name for a plugin: %q", name)
    94  	}
    95  	return plugins[0], nil
    96  }
    97  
    98  // All returns all plugins defined in their type-specific list files.
    99  // Note that these plugins have different capability Requirements and can't all
   100  // be run on the same host (e.g. some are Linux-only while others are Windows-only)
   101  // Prefer using FromCapabilities instead.
   102  func All(cfg *cpb.PluginConfig) []plugin.Plugin {
   103  	if cfg == nil {
   104  		// Do the nil check here instead of in individual plugin initers.
   105  		cfg = &cpb.PluginConfig{}
   106  	}
   107  	all := []plugin.Plugin{}
   108  	for _, initers := range fl.All {
   109  		for _, initer := range initers {
   110  			all = append(all, initer(cfg))
   111  		}
   112  	}
   113  	for _, initers := range sl.All {
   114  		for _, initer := range initers {
   115  			all = append(all, initer(cfg))
   116  		}
   117  	}
   118  	for _, initers := range dl.All {
   119  		for _, initer := range initers {
   120  			all = append(all, initer(cfg))
   121  		}
   122  	}
   123  	for _, initers := range al.All {
   124  		for _, initer := range initers {
   125  			all = append(all, initer(cfg))
   126  		}
   127  	}
   128  	for _, initers := range el.All {
   129  		for _, initer := range initers {
   130  			all = append(all, initer(cfg))
   131  		}
   132  	}
   133  	return all
   134  }
   135  
   136  // FilesystemExtractors returns the plugins from a list which are filesystem Extractors.
   137  func FilesystemExtractors(plugins []plugin.Plugin) []filesystem.Extractor {
   138  	result := []filesystem.Extractor{}
   139  	for _, p := range plugins {
   140  		if p, ok := p.(filesystem.Extractor); ok {
   141  			result = append(result, p)
   142  		}
   143  	}
   144  	return result
   145  }
   146  
   147  // StandaloneExtractors returns the plugins from a list which are standalone Extractors.
   148  func StandaloneExtractors(plugins []plugin.Plugin) []standalone.Extractor {
   149  	result := []standalone.Extractor{}
   150  	for _, p := range plugins {
   151  		if p, ok := p.(standalone.Extractor); ok {
   152  			result = append(result, p)
   153  		}
   154  	}
   155  	return result
   156  }
   157  
   158  // Detectors returns the plugins from a list which are Detectors.
   159  func Detectors(plugins []plugin.Plugin) []detector.Detector {
   160  	result := []detector.Detector{}
   161  	for _, p := range plugins {
   162  		if p, ok := p.(detector.Detector); ok {
   163  			result = append(result, p)
   164  		}
   165  	}
   166  	return result
   167  }
   168  
   169  // Annotators returns the plugins from a list which are Annotators.
   170  func Annotators(plugins []plugin.Plugin) []annotator.Annotator {
   171  	result := []annotator.Annotator{}
   172  	for _, p := range plugins {
   173  		if p, ok := p.(annotator.Annotator); ok {
   174  			result = append(result, p)
   175  		}
   176  	}
   177  	return result
   178  }
   179  
   180  // Enrichers returns the plugins from a list which are Enrichers.
   181  func Enrichers(plugins []plugin.Plugin) []enricher.Enricher {
   182  	result := []enricher.Enricher{}
   183  	for _, p := range plugins {
   184  		if p, ok := p.(enricher.Enricher); ok {
   185  			result = append(result, p)
   186  		}
   187  	}
   188  	return result
   189  }