capture extra metadata about rust crates from the Cargo.lock file

Signed-off-by: Weston Steimel <weston.steimel@gmail.com>
This commit is contained in:
Weston Steimel 2021-03-20 03:10:32 +00:00 committed by Alex Goodman
parent ba81bfe529
commit 35cc00b74a
No known key found for this signature in database
GPG key ID: 5CB45AE22BAB7EA7
8 changed files with 913 additions and 73 deletions

View file

@ -6,5 +6,5 @@ const (
// JSONSchemaVersion is the current schema version output by the JSON presenter
// This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment.
JSONSchemaVersion = "1.0.2"
JSONSchemaVersion = "1.0.3"
)

View file

@ -33,6 +33,7 @@ type metadataContainer struct {
Npm pkg.NpmPackageJSONMetadata
Python pkg.PythonPackageMetadata
Rpm pkg.RpmdbMetadata
Cargo pkg.CargoPackageMetadata
}
// nolint:funlen

View file

@ -0,0 +1,749 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"$ref": "#/definitions/Document",
"definitions": {
"ApkFileRecord": {
"required": [
"path"
],
"properties": {
"path": {
"type": "string"
},
"ownerUid": {
"type": "string"
},
"ownerGid": {
"type": "string"
},
"permissions": {
"type": "string"
},
"checksum": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object"
},
"ApkMetadata": {
"required": [
"package",
"originPackage",
"maintainer",
"version",
"license",
"architecture",
"url",
"description",
"size",
"installedSize",
"pullDependencies",
"pullChecksum",
"gitCommitOfApkPort",
"files"
],
"properties": {
"package": {
"type": "string"
},
"originPackage": {
"type": "string"
},
"maintainer": {
"type": "string"
},
"version": {
"type": "string"
},
"license": {
"type": "string"
},
"architecture": {
"type": "string"
},
"url": {
"type": "string"
},
"description": {
"type": "string"
},
"size": {
"type": "integer"
},
"installedSize": {
"type": "integer"
},
"pullDependencies": {
"type": "string"
},
"pullChecksum": {
"type": "string"
},
"gitCommitOfApkPort": {
"type": "string"
},
"files": {
"items": {
"$schema": "http://json-schema.org/draft-04/schema#",
"$ref": "#/definitions/ApkFileRecord"
},
"type": "array"
}
},
"additionalProperties": false,
"type": "object"
},
"CargoPackageMetadata": {
"required": [
"name",
"version"
],
"properties": {
"name": {
"type": "string"
},
"version": {
"type": "string"
},
"source": {
"type": "string"
},
"checksum": {
"type": "string"
},
"dependencies": {
"items": {
"type": "string"
},
"type": "array"
}
},
"additionalProperties": false,
"type": "object"
},
"Descriptor": {
"required": [
"name",
"version"
],
"properties": {
"name": {
"type": "string"
},
"version": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object"
},
"Distribution": {
"required": [
"name",
"version",
"idLike"
],
"properties": {
"name": {
"type": "string"
},
"version": {
"type": "string"
},
"idLike": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object"
},
"Document": {
"required": [
"artifacts",
"source",
"distro",
"descriptor",
"schema",
"artifactRelationships"
],
"properties": {
"artifacts": {
"items": {
"$schema": "http://json-schema.org/draft-04/schema#",
"$ref": "#/definitions/Package"
},
"type": "array"
},
"source": {
"$schema": "http://json-schema.org/draft-04/schema#",
"$ref": "#/definitions/Source"
},
"distro": {
"$schema": "http://json-schema.org/draft-04/schema#",
"$ref": "#/definitions/Distribution"
},
"descriptor": {
"$schema": "http://json-schema.org/draft-04/schema#",
"$ref": "#/definitions/Descriptor"
},
"schema": {
"$schema": "http://json-schema.org/draft-04/schema#",
"$ref": "#/definitions/Schema"
},
"artifactRelationships": {
"items": {
"$schema": "http://json-schema.org/draft-04/schema#",
"$ref": "#/definitions/Relationship"
},
"type": "array"
}
},
"additionalProperties": false,
"type": "object"
},
"DpkgFileRecord": {
"required": [
"path",
"md5"
],
"properties": {
"path": {
"type": "string"
},
"md5": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object"
},
"DpkgMetadata": {
"required": [
"package",
"source",
"version",
"sourceVersion",
"architecture",
"maintainer",
"installedSize",
"files"
],
"properties": {
"package": {
"type": "string"
},
"source": {
"type": "string"
},
"version": {
"type": "string"
},
"sourceVersion": {
"type": "string"
},
"architecture": {
"type": "string"
},
"maintainer": {
"type": "string"
},
"installedSize": {
"type": "integer"
},
"files": {
"items": {
"$schema": "http://json-schema.org/draft-04/schema#",
"$ref": "#/definitions/DpkgFileRecord"
},
"type": "array"
}
},
"additionalProperties": false,
"type": "object"
},
"GemMetadata": {
"required": [
"name",
"version"
],
"properties": {
"name": {
"type": "string"
},
"version": {
"type": "string"
},
"files": {
"items": {
"type": "string"
},
"type": "array"
},
"authors": {
"items": {
"type": "string"
},
"type": "array"
},
"licenses": {
"items": {
"type": "string"
},
"type": "array"
},
"homepage": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object"
},
"JavaManifest": {
"properties": {
"main": {
"patternProperties": {
".*": {
"type": "string"
}
},
"type": "object"
},
"namedSections": {
"patternProperties": {
".*": {
"patternProperties": {
".*": {
"type": "string"
}
},
"type": "object"
}
},
"type": "object"
}
},
"additionalProperties": false,
"type": "object"
},
"JavaMetadata": {
"required": [
"virtualPath"
],
"properties": {
"virtualPath": {
"type": "string"
},
"manifest": {
"$schema": "http://json-schema.org/draft-04/schema#",
"$ref": "#/definitions/JavaManifest"
},
"pomProperties": {
"$schema": "http://json-schema.org/draft-04/schema#",
"$ref": "#/definitions/PomProperties"
}
},
"additionalProperties": false,
"type": "object"
},
"Location": {
"required": [
"path"
],
"properties": {
"path": {
"type": "string"
},
"layerID": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object"
},
"NpmPackageJSONMetadata": {
"required": [
"author",
"licenses",
"homepage",
"description",
"url"
],
"properties": {
"files": {
"items": {
"type": "string"
},
"type": "array"
},
"author": {
"type": "string"
},
"licenses": {
"items": {
"type": "string"
},
"type": "array"
},
"homepage": {
"type": "string"
},
"description": {
"type": "string"
},
"url": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object"
},
"Package": {
"required": [
"id",
"name",
"version",
"type",
"foundBy",
"locations",
"licenses",
"language",
"cpes",
"purl",
"metadataType",
"metadata"
],
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"version": {
"type": "string"
},
"type": {
"type": "string"
},
"foundBy": {
"type": "string"
},
"locations": {
"items": {
"$schema": "http://json-schema.org/draft-04/schema#",
"$ref": "#/definitions/Location"
},
"type": "array"
},
"licenses": {
"items": {
"type": "string"
},
"type": "array"
},
"language": {
"type": "string"
},
"cpes": {
"items": {
"type": "string"
},
"type": "array"
},
"purl": {
"type": "string"
},
"metadataType": {
"type": "string"
},
"metadata": {
"anyOf": [
{
"type": "null"
},
{
"$ref": "#/definitions/ApkMetadata"
},
{
"$ref": "#/definitions/CargoPackageMetadata"
},
{
"$ref": "#/definitions/DpkgMetadata"
},
{
"$ref": "#/definitions/GemMetadata"
},
{
"$ref": "#/definitions/JavaMetadata"
},
{
"$ref": "#/definitions/NpmPackageJSONMetadata"
},
{
"$ref": "#/definitions/PythonPackageMetadata"
},
{
"$ref": "#/definitions/RpmdbMetadata"
}
]
}
},
"additionalProperties": false,
"type": "object"
},
"PomProperties": {
"required": [
"path",
"name",
"groupId",
"artifactId",
"version",
"extraFields"
],
"properties": {
"path": {
"type": "string"
},
"name": {
"type": "string"
},
"groupId": {
"type": "string"
},
"artifactId": {
"type": "string"
},
"version": {
"type": "string"
},
"extraFields": {
"patternProperties": {
".*": {
"type": "string"
}
},
"type": "object"
}
},
"additionalProperties": false,
"type": "object"
},
"PythonFileDigest": {
"required": [
"algorithm",
"value"
],
"properties": {
"algorithm": {
"type": "string"
},
"value": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object"
},
"PythonFileRecord": {
"required": [
"path"
],
"properties": {
"path": {
"type": "string"
},
"digest": {
"$schema": "http://json-schema.org/draft-04/schema#",
"$ref": "#/definitions/PythonFileDigest"
},
"size": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object"
},
"PythonPackageMetadata": {
"required": [
"name",
"version",
"license",
"author",
"authorEmail",
"platform",
"sitePackagesRootPath"
],
"properties": {
"name": {
"type": "string"
},
"version": {
"type": "string"
},
"license": {
"type": "string"
},
"author": {
"type": "string"
},
"authorEmail": {
"type": "string"
},
"platform": {
"type": "string"
},
"files": {
"items": {
"$schema": "http://json-schema.org/draft-04/schema#",
"$ref": "#/definitions/PythonFileRecord"
},
"type": "array"
},
"sitePackagesRootPath": {
"type": "string"
},
"topLevelPackages": {
"items": {
"type": "string"
},
"type": "array"
}
},
"additionalProperties": false,
"type": "object"
},
"Relationship": {
"required": [
"parent",
"child",
"type",
"metadata"
],
"properties": {
"parent": {
"type": "string"
},
"child": {
"type": "string"
},
"type": {
"type": "string"
},
"metadata": {
"additionalProperties": true
}
},
"additionalProperties": false,
"type": "object"
},
"RpmdbFileRecord": {
"required": [
"path",
"mode",
"size",
"sha256"
],
"properties": {
"path": {
"type": "string"
},
"mode": {
"type": "integer"
},
"size": {
"type": "integer"
},
"sha256": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object"
},
"RpmdbMetadata": {
"required": [
"name",
"version",
"epoch",
"architecture",
"release",
"sourceRpm",
"size",
"license",
"vendor",
"files"
],
"properties": {
"name": {
"type": "string"
},
"version": {
"type": "string"
},
"epoch": {
"type": "integer"
},
"architecture": {
"type": "string"
},
"release": {
"type": "string"
},
"sourceRpm": {
"type": "string"
},
"size": {
"type": "integer"
},
"license": {
"type": "string"
},
"vendor": {
"type": "string"
},
"files": {
"items": {
"$schema": "http://json-schema.org/draft-04/schema#",
"$ref": "#/definitions/RpmdbFileRecord"
},
"type": "array"
}
},
"additionalProperties": false,
"type": "object"
},
"Schema": {
"required": [
"version",
"url"
],
"properties": {
"version": {
"type": "string"
},
"url": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object"
},
"Source": {
"required": [
"type",
"target"
],
"properties": {
"type": {
"type": "string"
},
"target": {
"additionalProperties": true
}
},
"additionalProperties": false,
"type": "object"
}
}
}

View file

@ -3,7 +3,7 @@ package rust
import "github.com/anchore/syft/syft/pkg"
type CargoMetadata struct {
Packages []CargoMetadataPackage `toml:"package"`
Packages []pkg.CargoPackageMetadata `toml:"package"`
}
// Pkgs returns all of the packages referenced within the Cargo.lock metadata.

View file

@ -1,21 +0,0 @@
package rust
import "github.com/anchore/syft/syft/pkg"
type CargoMetadataPackage struct {
Name string `toml:"name"`
Version string `toml:"version"`
Source string `toml:"source"`
Checksum string `toml:"checksum"`
Dependencies []string `toml:"dependencies"`
}
// Pkg returns the standard `pkg.Package` representation of the package referenced within the Cargo.lock metadata.
func (p CargoMetadataPackage) Pkg() pkg.Package {
return pkg.Package{
Name: p.Name,
Version: p.Version,
Language: pkg.Rust,
Type: pkg.RustPkg,
}
}

View file

@ -11,74 +11,158 @@ import (
func TestParseCargoLock(t *testing.T) {
expected := []pkg.Package{
{
Name: "ansi_term",
Version: "0.12.1",
Language: pkg.Rust,
Type: pkg.RustPkg,
Licenses: nil,
Name: "ansi_term",
Version: "0.12.1",
Language: pkg.Rust,
Type: pkg.RustPkg,
MetadataType: pkg.RustCrateMetadataType,
Licenses: nil,
Metadata: pkg.CargoPackageMetadata{
Name: "ansi_term",
Version: "0.12.1",
Source: "registry+https://github.com/rust-lang/crates.io-index",
Checksum: "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2",
Dependencies: []string{
"winapi",
},
},
},
{
Name: "matches",
Version: "0.1.8",
Language: pkg.Rust,
Type: pkg.RustPkg,
Licenses: nil,
Name: "matches",
Version: "0.1.8",
Language: pkg.Rust,
Type: pkg.RustPkg,
MetadataType: pkg.RustCrateMetadataType,
Licenses: nil,
Metadata: pkg.CargoPackageMetadata{
Name: "matches",
Version: "0.1.8",
Source: "registry+https://github.com/rust-lang/crates.io-index",
Checksum: "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08",
},
},
{
Name: "memchr",
Version: "2.3.3",
Language: pkg.Rust,
Type: pkg.RustPkg,
Licenses: nil,
Name: "memchr",
Version: "2.3.3",
Language: pkg.Rust,
Type: pkg.RustPkg,
MetadataType: pkg.RustCrateMetadataType,
Licenses: nil,
Metadata: pkg.CargoPackageMetadata{
Name: "memchr",
Version: "2.3.3",
Source: "registry+https://github.com/rust-lang/crates.io-index",
Checksum: "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400",
},
},
{
Name: "natord",
Version: "1.0.9",
Language: pkg.Rust,
Type: pkg.RustPkg,
Licenses: nil,
Name: "natord",
Version: "1.0.9",
Language: pkg.Rust,
Type: pkg.RustPkg,
MetadataType: pkg.RustCrateMetadataType,
Licenses: nil,
Metadata: pkg.CargoPackageMetadata{
Name: "natord",
Version: "1.0.9",
Source: "registry+https://github.com/rust-lang/crates.io-index",
Checksum: "308d96db8debc727c3fd9744aac51751243420e46edf401010908da7f8d5e57c",
},
},
{
Name: "nom",
Version: "4.2.3",
Language: pkg.Rust,
Type: pkg.RustPkg,
Licenses: nil,
Name: "nom",
Version: "4.2.3",
Language: pkg.Rust,
Type: pkg.RustPkg,
MetadataType: pkg.RustCrateMetadataType,
Licenses: nil,
Metadata: pkg.CargoPackageMetadata{
Name: "nom",
Version: "4.2.3",
Source: "registry+https://github.com/rust-lang/crates.io-index",
Checksum: "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6",
Dependencies: []string{
"memchr",
"version_check",
},
},
},
{
Name: "unicode-bidi",
Version: "0.3.4",
Language: pkg.Rust,
Type: pkg.RustPkg,
Licenses: nil,
Name: "unicode-bidi",
Version: "0.3.4",
Language: pkg.Rust,
Type: pkg.RustPkg,
MetadataType: pkg.RustCrateMetadataType,
Licenses: nil,
Metadata: pkg.CargoPackageMetadata{
Name: "unicode-bidi",
Version: "0.3.4",
Source: "registry+https://github.com/rust-lang/crates.io-index",
Checksum: "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5",
Dependencies: []string{
"matches",
},
},
},
{
Name: "version_check",
Version: "0.1.5",
Language: pkg.Rust,
Type: pkg.RustPkg,
Licenses: nil,
Name: "version_check",
Version: "0.1.5",
Language: pkg.Rust,
Type: pkg.RustPkg,
MetadataType: pkg.RustCrateMetadataType,
Licenses: nil,
Metadata: pkg.CargoPackageMetadata{
Name: "version_check",
Version: "0.1.5",
Source: "registry+https://github.com/rust-lang/crates.io-index",
Checksum: "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd",
},
},
{
Name: "winapi",
Version: "0.3.9",
Language: pkg.Rust,
Type: pkg.RustPkg,
Licenses: nil,
Name: "winapi",
Version: "0.3.9",
Language: pkg.Rust,
Type: pkg.RustPkg,
MetadataType: pkg.RustCrateMetadataType,
Licenses: nil,
Metadata: pkg.CargoPackageMetadata{
Name: "winapi",
Version: "0.3.9",
Source: "registry+https://github.com/rust-lang/crates.io-index",
Checksum: "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419",
Dependencies: []string{
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
},
},
},
{
Name: "winapi-i686-pc-windows-gnu",
Version: "0.4.0",
Language: pkg.Rust,
Type: pkg.RustPkg,
Licenses: nil,
Name: "winapi-i686-pc-windows-gnu",
Version: "0.4.0",
Language: pkg.Rust,
Type: pkg.RustPkg,
MetadataType: pkg.RustCrateMetadataType,
Licenses: nil,
Metadata: pkg.CargoPackageMetadata{
Name: "winapi-i686-pc-windows-gnu",
Version: "0.4.0",
Source: "registry+https://github.com/rust-lang/crates.io-index",
Checksum: "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6",
},
},
{
Name: "winapi-x86_64-pc-windows-gnu",
Version: "0.4.0",
Language: pkg.Rust,
Type: pkg.RustPkg,
Licenses: nil,
Name: "winapi-x86_64-pc-windows-gnu",
Version: "0.4.0",
Language: pkg.Rust,
Type: pkg.RustPkg,
MetadataType: pkg.RustCrateMetadataType,
Licenses: nil,
Metadata: pkg.CargoPackageMetadata{
Name: "winapi-x86_64-pc-windows-gnu",
Version: "0.4.0",
Source: "registry+https://github.com/rust-lang/crates.io-index",
Checksum: "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f",
},
},
}

View file

@ -0,0 +1,21 @@
package pkg
type CargoPackageMetadata struct {
Name string `toml:"name" json:"name"`
Version string `toml:"version" json:"version"`
Source string `toml:"source,omitempty" json:"source,omitempty"`
Checksum string `toml:"checksum,omitempty" json:"checksum,omitempty"`
Dependencies []string `toml:"dependencies,omitempty" json:"dependencies,omitempty"`
}
// Pkg returns the standard `pkg.Package` representation of the package referenced within the Cargo.lock metadata.
func (p CargoPackageMetadata) Pkg() Package {
return Package{
Name: p.Name,
Version: p.Version,
Language: Rust,
Type: RustPkg,
MetadataType: RustCrateMetadataType,
Metadata: p,
}
}

View file

@ -165,6 +165,12 @@ func (a *Package) UnmarshalJSON(b []byte) error {
return err
}
a.Metadata = payload
case pkg.RustCrateMetadataType:
var payload pkg.CargoPackageMetadata
if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil {
return err
}
a.Metadata = payload
case "":
// there may be packages with no metadata, which is OK
default: