diff --git a/pkg/parser/parser.go b/pkg/parser/parser.go index 05debf4..fcfe7cb 100644 --- a/pkg/parser/parser.go +++ b/pkg/parser/parser.go @@ -85,12 +85,12 @@ type dependencyGraphParser func(lockfilePath string, config *ParserConfig) (*mod // Maintain a map of lockfileAs to dependencyGraphParser var dependencyGraphParsers map[string]dependencyGraphParser = map[string]dependencyGraphParser{ - customParserTerraform: parseTerraformLockfile, "package-lock.json": parseNpmPackageLockAsGraph, customParserCycloneDXSBOM: parseSbomCycloneDxAsGraph, customParserTypeJavaArchive: parseJavaArchiveAsGraph, customParserTypeJavaWebAppArchive: parseJavaArchiveAsGraph, customParserGitHubActions: parseGithubActionWorkflowAsGraph, + customParserTerraform: parseTerraformLockfile, } // Maintain a map of extension to lockfileAs @@ -100,6 +100,13 @@ var lockfileAsMapByExtension map[string]string = map[string]string{ "war": customParserTypeJavaWebAppArchive, } +// Maintain a map of standard filenames to a custom parser. This has +// higher precendence that lockfile package. Graph parsers discover +// reference to this map to resolve the lockfileAs from base filename +var lockfileAsMapByPath map[string]string = map[string]string{ + ".terraform.lock.hcl": customParserTerraform, +} + func FindLockFileAsByExtension(extension string) (string, error) { if lockfileAs, ok := lockfileAsMapByExtension[extension]; ok { return lockfileAs, nil @@ -185,6 +192,9 @@ func findGraphParser(lockfilePath, lockfileAs string) (dependencyGraphParser, st parseAs := lockfileAs if lockfileAs == "" { parseAs = filepath.Base(lockfilePath) + if _, ok := lockfileAsMapByPath[parseAs]; ok { + parseAs = lockfileAsMapByPath[parseAs] + } } if _, ok := dependencyGraphParsers[parseAs]; ok { diff --git a/pkg/parser/terraform.go b/pkg/parser/terraform.go index 60fcea5..bf165ac 100644 --- a/pkg/parser/terraform.go +++ b/pkg/parser/terraform.go @@ -2,13 +2,14 @@ package parser import ( "fmt" + "github.com/hashicorp/hcl/v2/hclparse" "github.com/hashicorp/hcl/v2/hclsyntax" + "github.com/safedep/vet/pkg/common/logger" "github.com/safedep/vet/pkg/models" ) func parseTerraformLockfile(path string, config *ParserConfig) (*models.PackageManifest, error) { - // Parse the file using the HCL parser parser := hclparse.NewParser() hclFile, diags := parser.ParseHCLFile(path) if diags.HasErrors() { @@ -19,12 +20,18 @@ func parseTerraformLockfile(path string, config *ParserConfig) (*models.PackageM if !ok { return nil, fmt.Errorf("failed to assert body as hclsyntax.Body") } - manifest := models.NewPackageManifestFromLocal(path, models.EcosystemTerraform) + manifest := models.NewPackageManifestFromLocal(path, models.EcosystemTerraform) for _, block := range body.Blocks { if block.Type != "provider" { continue } + + if len(block.Labels) == 0 { + logger.Warnf("Terraform parser: provider block has no labels") + continue + } + providerName := block.Labels[0] // The provider name is the first label providerVersion := "0.0.0" if versionAttr, exists := block.Body.Attributes["version"]; exists { @@ -32,13 +39,16 @@ func parseTerraformLockfile(path string, config *ParserConfig) (*models.PackageM if diags.HasErrors() { return nil, fmt.Errorf("failed to extract version: %v", diags) } + providerVersion = versionVal.AsString() } + pkgdetails := models.NewPackageDetail(models.EcosystemTerraform, providerName, providerVersion) packageModel := models.Package{ PackageDetails: pkgdetails, Depth: 0, } + manifest.AddPackage(&packageModel) }