Add GitLab cataloger

Signed-off-by: Ryan <ryanhopk@protonmail.com>
This commit is contained in:
Ryan 2024-04-16 23:46:08 -04:00
parent 21eaa5c82b
commit 094130a034
No known key found for this signature in database
GPG key ID: A938D2225B62F830
4 changed files with 156 additions and 0 deletions

View file

@ -0,0 +1,15 @@
package gitlab
import (
"github.com/anchore/syft/syft/pkg/cataloger/generic"
)
const (
catalogerName = "gitlab-cataloger"
versionManifestGlob = "**/opt/gitlab/version-manifest.json"
)
func NewGitLabCataloger() *generic.Cataloger {
return generic.NewCataloger(catalogerName).
WithParserByGlobs(parseVersionManifest, versionManifestGlob)
}

View file

@ -0,0 +1,96 @@
package gitlab
import (
"context"
"encoding/json"
"fmt"
"io"
"strings"
"github.com/anchore/packageurl-go"
"github.com/anchore/syft/syft/artifact"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/pkg/cataloger/generic"
)
type versionManifest struct {
ManifestFormat int `json:"manifest_format"`
Software map[string]manifestPackage `json:"software"`
BuildVersion string `json:"build_version"`
BuildGitRevision string `json:"build_git_revision"`
License string `json:"license"`
}
type manifestPackage struct {
LockedVersion *string `json:"locked_version"`
LockedSource *lockedSource `json:"locked_source"`
SourceType *string `json:"url"`
DescribedVersion *string `json:"described_version"`
DisplayVersion *string `json:"display_version"`
Vendor *string `json:"vendor"`
License *string `json:"license"`
}
type lockedSource struct {
Git string `json:"git"`
URL string `json:"url"`
Sha256 string `json:"sha256"`
}
func parseVersionManifest(_ context.Context, _ file.Resolver, _ *generic.Environment, reader file.LocationReadCloser) ([]pkg.Package, []artifact.Relationship, error) {
bytes, err := io.ReadAll(reader)
if err != nil {
return nil, nil, fmt.Errorf("failed to load version-manifest.json file: %w", err)
}
var pkgs []pkg.Package
var manifest versionManifest
err = json.Unmarshal(bytes, &manifest)
if err != nil {
return nil, nil, fmt.Errorf("failed to parse version-manifest.json file: %w", err)
}
for pkgName, pkgData := range manifest.Software {
p := pkg.Package{
Name: pkgName,
Locations: file.NewLocationSet(reader.Location),
}
if pkgData.DisplayVersion != nil {
p.Version = *pkgData.DisplayVersion
}
if pkgData.License != nil {
p.Licenses = pkg.NewLicenseSet(pkg.NewLicense(*pkgData.License))
}
if pkgData.LockedSource != nil && (*pkgData.SourceType == "git" || *pkgData.SourceType == "url") {
var purl packageurl.PackageURL
if *pkgData.SourceType == "git" {
purl.Type = "gitlab"
gitUrlComponents := strings.Split(pkgData.LockedSource.Git, "/")
// Namespace is the user or organization
purl.Namespace = strings.Split(gitUrlComponents[0], ":")[1]
// Name is the repository name (with .git sliced out)
purl.Name = gitUrlComponents[1][:len(gitUrlComponents[1])-4]
} else {
purl.Type = "generic"
purl.Qualifiers = append(
purl.Qualifiers,
packageurl.Qualifier{
Key: "download_url",
Value: pkgData.LockedSource.URL,
},
packageurl.Qualifier{
Key: "checksum",
Value: pkgData.LockedSource.Sha256,
})
}
}
pkgs = append(pkgs, p)
}
pkg.Sort(pkgs)
return pkgs, nil, nil
}

View file

@ -0,0 +1,26 @@
package gitlab
import (
"testing"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/pkg/cataloger/internal/pkgtest"
)
func TestParseVersionManifestFile(t *testing.T) {
fixture := "test-fixtures/glob-paths/opt/gitlab/version-manifest.json"
locations := file.NewLocationSet(file.NewLocation(fixture))
var expectedPkg = pkg.Package{
Name: "openssl",
Version: "1.1.1q",
Locations: locations,
Licenses: pkg.NewLicenseSet(
pkg.NewLicenseFromLocations("OpenSSL"),
),
PURL: "pkg:gitlab/omnibus-mirror/openssl",
}
pkgtest.TestFileParser(t, fixture, parseVersionManifest, []pkg.Package{expectedPkg}, nil)
}

View file

@ -0,0 +1,19 @@
{
"manifest_format": 2,
"software": {
"openssl": {
"locked_version": "29708a562a1887a91de0fa6ca668c71871accde9",
"locked_source": {
"git": "git@dev.gitlab.org:omnibus-mirror/openssl.git"
},
"source_type": "git",
"described_version": "OpenSSL_1_1_1q",
"display_version": "1.1.1q",
"vendor": "openssl",
"license": "OpenSSL"
}
},
"build_version": "15.6.1",
"build_git_revision": "e3d1cd74ef1abe2b9514d8aa64c065b434becd3a",
"license": "MIT"
}