diff --git a/pkg/assembler/helpers/purl.go b/pkg/assembler/helpers/purl.go index b935425058..140b0b2936 100644 --- a/pkg/assembler/helpers/purl.go +++ b/pkg/assembler/helpers/purl.go @@ -159,7 +159,7 @@ func purlConvert(p purl.PackageURL) (*model.PkgInputSpec, error) { // so that they can be referenced with higher specificity in GUAC // // PURL types not defined in purl library handled generically - case "alpine", "alpm", "apk", "huggingface", "githubactions", "mlflow", "qpkg", "pub", "swid", PurlTypeGuac: + case "alpine", "githubactions", PurlTypeGuac: fallthrough // PURL types defined in purl library handled generically case purl.TypeBitbucket, purl.TypeCocoapods, purl.TypeCargo, @@ -167,8 +167,9 @@ func purlConvert(p purl.PackageURL) (*model.PkgInputSpec, error) { purl.TypeDebian, purl.TypeGem, purl.TypeGithub, purl.TypeGolang, purl.TypeHackage, purl.TypeHex, purl.TypeMaven, purl.TypeNPM, purl.TypeNuget, purl.TypePyPi, purl.TypeRPM, purl.TypeSwift, - purl.TypeGeneric, purl.TypeYocto, purl.TypeCpan: - // some code + purl.TypeGeneric, purl.TypeYocto, purl.TypeCpan, + purl.TypeAlpm, purl.TypeApk, purl.TypeBitnami, purl.TypeHuggingface, + purl.TypeMLFlow, purl.TypePub, purl.TypeQpkg, purl.TypeSWID: r := pkg(p.Type, p.Namespace, p.Name, p.Version, p.Subpath, p.Qualifiers.Map()) return r, nil @@ -223,9 +224,13 @@ func purlConvert(p purl.PackageURL) (*model.PkgInputSpec, error) { return r, nil default: - // unhandled types should throw an error so we can make sure to review the - // implementation of newly introduced PURL types. - return nil, fmt.Errorf("unhandled PURL type: %s", p.Type) + if _, ok := purl.KnownTypes[p.Type]; ok { + return nil, fmt.Errorf("unhandled known PURL type: %q. Please report at https://github.com/guacsec/guac/issues/new", p.Type) + } + if _, ok := purl.CandidateTypes[p.Type]; ok { + return nil, fmt.Errorf("unhandled candidate PURL type: %q. Please report at https://github.com/guacsec/guac/issues/new", p.Type) + } + return nil, fmt.Errorf("unsupported PURL type: %q", p.Type) } } diff --git a/pkg/assembler/helpers/purl_test.go b/pkg/assembler/helpers/purl_test.go index cff4c24f5e..0f3bd2b146 100644 --- a/pkg/assembler/helpers/purl_test.go +++ b/pkg/assembler/helpers/purl_test.go @@ -17,6 +17,7 @@ package helpers import ( "fmt" + "strings" "testing" "github.com/google/go-cmp/cmp" @@ -216,6 +217,9 @@ func TestPurlConvert(t *testing.T) { }, { purlUri: "pkg:cpan/Pod-Perldoc@3.20", expected: pkg("cpan", "", "Pod-Perldoc", "3.20", "", map[string]string{}), + }, { + purlUri: "pkg:bitnami/apache@2.4.57", + expected: pkg("bitnami", "", "apache", "2.4.57", "", map[string]string{}), }, } @@ -234,6 +238,38 @@ func TestPurlConvert(t *testing.T) { } } +func TestPurlConvertUnhandledTypes(t *testing.T) { + testCases := []struct { + name string + purlUri string + expectedErr string + }{ + { + name: "unhandled candidate purl type", + purlUri: "pkg:helm/prometheus@14.0.0", + expectedErr: "unhandled candidate PURL type", + }, + { + name: "unsupported unknown purl type", + purlUri: "pkg:customtype/mynamespace/mypackage@1.0.0", + expectedErr: "unsupported PURL type", + }, + } + + for _, tt := range testCases { + t.Run(tt.name, func(t *testing.T) { + _, err := PurlToPkg(tt.purlUri) + if err == nil { + t.Errorf("expected error for purl %s, got nil", tt.purlUri) + return + } + if !strings.Contains(err.Error(), tt.expectedErr) { + t.Errorf("expected error containing %q, got: %v", tt.expectedErr, err) + } + }) + } +} + func TestPkgInputSpecToPurl(t *testing.T) { testCases := []struct { expectedPurlUri string