diff --git a/internal/constants.go b/internal/constants.go index faddcf2ec..5cb49659a 100644 --- a/internal/constants.go +++ b/internal/constants.go @@ -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" ) diff --git a/schema/json/generate.go b/schema/json/generate.go index 82021823c..4896e1924 100644 --- a/schema/json/generate.go +++ b/schema/json/generate.go @@ -33,6 +33,7 @@ type metadataContainer struct { Npm pkg.NpmPackageJSONMetadata Python pkg.PythonPackageMetadata Rpm pkg.RpmdbMetadata + Cargo pkg.CargoPackageMetadata } // nolint:funlen diff --git a/schema/json/schema-1.0.3.json b/schema/json/schema-1.0.3.json new file mode 100644 index 000000000..ccffab7a5 --- /dev/null +++ b/schema/json/schema-1.0.3.json @@ -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" + } + } +} diff --git a/syft/cataloger/rust/cargo_metadata.go b/syft/cataloger/rust/cargo_metadata.go index 23c85c8ba..d4c4eb69d 100644 --- a/syft/cataloger/rust/cargo_metadata.go +++ b/syft/cataloger/rust/cargo_metadata.go @@ -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. diff --git a/syft/cataloger/rust/cargo_metadata_package.go b/syft/cataloger/rust/cargo_metadata_package.go deleted file mode 100644 index b3410f35b..000000000 --- a/syft/cataloger/rust/cargo_metadata_package.go +++ /dev/null @@ -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, - } -} diff --git a/syft/cataloger/rust/parse_cargo_lock_test.go b/syft/cataloger/rust/parse_cargo_lock_test.go index 284660169..733882d0e 100644 --- a/syft/cataloger/rust/parse_cargo_lock_test.go +++ b/syft/cataloger/rust/parse_cargo_lock_test.go @@ -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", + }, }, } diff --git a/syft/pkg/cargo_package_metadata.go b/syft/pkg/cargo_package_metadata.go new file mode 100644 index 000000000..643f462d1 --- /dev/null +++ b/syft/pkg/cargo_package_metadata.go @@ -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, + } +} diff --git a/syft/presenter/json/package.go b/syft/presenter/json/package.go index e0e995a6a..269c3d9bf 100644 --- a/syft/presenter/json/package.go +++ b/syft/presenter/json/package.go @@ -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: