mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 16:33:21 +01:00
109 lines
3.0 KiB
Go
109 lines
3.0 KiB
Go
package githubactions
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/anchore/packageurl-go"
|
|
"github.com/anchore/syft/internal/log"
|
|
"github.com/anchore/syft/syft/file"
|
|
"github.com/anchore/syft/syft/pkg"
|
|
)
|
|
|
|
func newPackageFromUsageStatement(use string, location file.Location) (*pkg.Package, error) {
|
|
name, version := parseStepUsageStatement(use)
|
|
|
|
if name == "" {
|
|
log.WithFields("file", location.RealPath, "statement", use).Trace("unable to parse github action usage statement")
|
|
return nil, fmt.Errorf("unable to parse github action usage statement")
|
|
}
|
|
|
|
if strings.Contains(name, ".github/workflows/") {
|
|
return newGithubActionWorkflowPackageUsage(name, version, location), nil
|
|
}
|
|
|
|
return newGithubActionPackageUsage(name, version, location), nil
|
|
}
|
|
|
|
func newGithubActionWorkflowPackageUsage(name, version string, workflowLocation file.Location) *pkg.Package {
|
|
p := &pkg.Package{
|
|
Name: name,
|
|
Version: version,
|
|
Locations: file.NewLocationSet(workflowLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)),
|
|
PURL: packageURL(name, version),
|
|
// we have full visibility into the dependencies of a workflow file except for when using shared workflows
|
|
Dependencies: pkg.CompleteDependencies,
|
|
Type: pkg.GithubActionWorkflowPkg,
|
|
}
|
|
|
|
p.SetID()
|
|
|
|
return p
|
|
}
|
|
|
|
func newGithubActionPackageUsage(name, version string, workflowLocation file.Location) *pkg.Package {
|
|
p := &pkg.Package{
|
|
Name: name,
|
|
Version: version,
|
|
Locations: file.NewLocationSet(workflowLocation.WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation)),
|
|
PURL: packageURL(name, version),
|
|
// we cannot see what the dependencies are for a github action are locally from workflow yaml files
|
|
Dependencies: pkg.IncompleteDependencies,
|
|
Type: pkg.GithubActionPkg,
|
|
}
|
|
|
|
p.SetID()
|
|
|
|
return p
|
|
}
|
|
|
|
func parseStepUsageStatement(use string) (string, string) {
|
|
// from octo-org/another-repo/.github/workflows/workflow.yml@v1 get octo-org/another-repo/.github/workflows/workflow.yml and v1
|
|
// from ./.github/workflows/workflow-2.yml interpret as only the name
|
|
|
|
// from actions/cache@v3 get actions/cache and v3
|
|
|
|
fields := strings.Split(use, "@")
|
|
switch len(fields) {
|
|
case 1:
|
|
return use, ""
|
|
case 2:
|
|
return fields[0], fields[1]
|
|
}
|
|
return "", ""
|
|
}
|
|
|
|
func packageURL(name, version string) string {
|
|
var qualifiers packageurl.Qualifiers
|
|
var subPath string
|
|
var namespace string
|
|
|
|
fields := strings.SplitN(name, "/", 3)
|
|
switch len(fields) {
|
|
case 1:
|
|
return ""
|
|
case 2:
|
|
namespace = fields[0]
|
|
name = fields[1]
|
|
case 3:
|
|
namespace = fields[0]
|
|
name = fields[1]
|
|
subPath = fields[2]
|
|
}
|
|
if namespace == "." {
|
|
// this is a local composite action, which is unclear how to represent in a PURL without more information
|
|
return ""
|
|
}
|
|
|
|
// there isn't a github actions PURL but there is a github PURL type for referencing github repos, which is the
|
|
// next best thing until there is a supported type.
|
|
return packageurl.NewPackageURL(
|
|
packageurl.TypeGithub,
|
|
namespace,
|
|
name,
|
|
version,
|
|
qualifiers,
|
|
subPath,
|
|
).ToString()
|
|
}
|