mirror of
https://github.com/anchore/syft.git
synced 2025-11-18 00:43:20 +01:00
Merge pull request #265 from anchore/package-json-license-objects
Improve package.json license parsing
This commit is contained in:
commit
a5b72405dd
@ -101,7 +101,7 @@ func initLogging() {
|
|||||||
logWrapper := logger.NewLogrusLogger(cfg)
|
logWrapper := logger.NewLogrusLogger(cfg)
|
||||||
syft.SetLogger(logWrapper)
|
syft.SetLogger(logWrapper)
|
||||||
stereoscope.SetLogger(&logger.LogrusNestedLogger{
|
stereoscope.SetLogger(&logger.LogrusNestedLogger{
|
||||||
Logger: logWrapper.Logger.WithField("from-lib", "steroscope"),
|
Logger: logWrapper.Logger.WithField("from-lib", "stereoscope"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package javascript
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"regexp"
|
"regexp"
|
||||||
@ -22,7 +23,8 @@ type PackageJSON struct {
|
|||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
Latest []string `json:"latest"`
|
Latest []string `json:"latest"`
|
||||||
Author Author `json:"author"`
|
Author Author `json:"author"`
|
||||||
License string `json:"license"`
|
License json.RawMessage `json:"license"`
|
||||||
|
Licenses []license `json:"licenses,omitempty"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Homepage string `json:"homepage"`
|
Homepage string `json:"homepage"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
@ -107,6 +109,56 @@ func (r *Repository) UnmarshalJSON(b []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type license struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func licenseFromJSON(b []byte) (string, error) {
|
||||||
|
// first try as string
|
||||||
|
var licenseString string
|
||||||
|
err := json.Unmarshal(b, &licenseString)
|
||||||
|
if err == nil {
|
||||||
|
return licenseString, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// then try as object (this format is deprecated)
|
||||||
|
var licenseObject license
|
||||||
|
err = json.Unmarshal(b, &licenseObject)
|
||||||
|
if err == nil {
|
||||||
|
return licenseObject.Type, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", errors.New("unable to unmarshal license field as either string or object")
|
||||||
|
}
|
||||||
|
|
||||||
|
func licensesFromJSON(p PackageJSON) ([]string, error) {
|
||||||
|
if p.License == nil && p.Licenses == nil {
|
||||||
|
// This package.json doesn't specify any licenses whatsoever
|
||||||
|
return []string{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
singleLicense, err := licenseFromJSON(p.License)
|
||||||
|
if err == nil {
|
||||||
|
return []string{singleLicense}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// The "licenses" field is deprecated. It should be inspected as a last resort.
|
||||||
|
if p.Licenses != nil {
|
||||||
|
mapLicenses := func(licenses []license) []string {
|
||||||
|
mappedLicenses := make([]string, len(licenses))
|
||||||
|
for i, l := range licenses {
|
||||||
|
mappedLicenses[i] = l.Type
|
||||||
|
}
|
||||||
|
return mappedLicenses
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapLicenses(p.Licenses), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("unable to parse license field: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// parsePackageJson parses a package.json and returns the discovered JavaScript packages.
|
// parsePackageJson parses a package.json and returns the discovered JavaScript packages.
|
||||||
func parsePackageJSON(_ string, reader io.Reader) ([]pkg.Package, error) {
|
func parsePackageJSON(_ string, reader io.Reader) ([]pkg.Package, error) {
|
||||||
packages := make([]pkg.Package, 0)
|
packages := make([]pkg.Package, 0)
|
||||||
@ -120,10 +172,15 @@ func parsePackageJSON(_ string, reader io.Reader) ([]pkg.Package, error) {
|
|||||||
return nil, fmt.Errorf("failed to parse package.json file: %w", err)
|
return nil, fmt.Errorf("failed to parse package.json file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
licenses, err := licensesFromJSON(p)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse package.json file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
packages = append(packages, pkg.Package{
|
packages = append(packages, pkg.Package{
|
||||||
Name: p.Name,
|
Name: p.Name,
|
||||||
Version: p.Version,
|
Version: p.Version,
|
||||||
Licenses: []string{p.License},
|
Licenses: licenses,
|
||||||
Language: pkg.JavaScript,
|
Language: pkg.JavaScript,
|
||||||
Type: pkg.NpmPkg,
|
Type: pkg.NpmPkg,
|
||||||
MetadataType: pkg.NpmPackageJSONMetadataType,
|
MetadataType: pkg.NpmPackageJSONMetadataType,
|
||||||
@ -131,7 +188,7 @@ func parsePackageJSON(_ string, reader io.Reader) ([]pkg.Package, error) {
|
|||||||
Author: p.Author.AuthorString(),
|
Author: p.Author.AuthorString(),
|
||||||
Homepage: p.Homepage,
|
Homepage: p.Homepage,
|
||||||
URL: p.Repository.URL,
|
URL: p.Repository.URL,
|
||||||
Licenses: []string{p.License},
|
Licenses: licenses,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,6 +30,57 @@ func TestParsePackageJSON(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Fixture: "test-fixtures/pkg-json/package-license-object.json",
|
||||||
|
ExpectedPkg: pkg.Package{
|
||||||
|
Name: "npm",
|
||||||
|
Version: "6.14.6",
|
||||||
|
Type: pkg.NpmPkg,
|
||||||
|
Licenses: []string{"ISC"},
|
||||||
|
Language: pkg.JavaScript,
|
||||||
|
MetadataType: pkg.NpmPackageJSONMetadataType,
|
||||||
|
Metadata: pkg.NpmPackageJSONMetadata{
|
||||||
|
Author: "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me)",
|
||||||
|
Homepage: "https://docs.npmjs.com/",
|
||||||
|
URL: "https://github.com/npm/cli",
|
||||||
|
Licenses: []string{"ISC"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Fixture: "test-fixtures/pkg-json/package-license-objects.json",
|
||||||
|
ExpectedPkg: pkg.Package{
|
||||||
|
Name: "npm",
|
||||||
|
Version: "6.14.6",
|
||||||
|
Type: pkg.NpmPkg,
|
||||||
|
Licenses: []string{"MIT", "Apache-2.0"},
|
||||||
|
Language: pkg.JavaScript,
|
||||||
|
MetadataType: pkg.NpmPackageJSONMetadataType,
|
||||||
|
Metadata: pkg.NpmPackageJSONMetadata{
|
||||||
|
Author: "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me)",
|
||||||
|
Homepage: "https://docs.npmjs.com/",
|
||||||
|
URL: "https://github.com/npm/cli",
|
||||||
|
Licenses: []string{"MIT", "Apache-2.0"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Fixture: "test-fixtures/pkg-json/package-no-license.json",
|
||||||
|
ExpectedPkg: pkg.Package{
|
||||||
|
Name: "npm",
|
||||||
|
Version: "6.14.6",
|
||||||
|
Type: pkg.NpmPkg,
|
||||||
|
Licenses: []string{},
|
||||||
|
Language: pkg.JavaScript,
|
||||||
|
MetadataType: pkg.NpmPackageJSONMetadataType,
|
||||||
|
Metadata: pkg.NpmPackageJSONMetadata{
|
||||||
|
Author: "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me)",
|
||||||
|
Homepage: "https://docs.npmjs.com/",
|
||||||
|
URL: "https://github.com/npm/cli",
|
||||||
|
Licenses: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Fixture: "test-fixtures/pkg-json/package-nested-author.json",
|
Fixture: "test-fixtures/pkg-json/package-nested-author.json",
|
||||||
ExpectedPkg: pkg.Package{
|
ExpectedPkg: pkg.Package{
|
||||||
@ -73,7 +124,7 @@ func TestParsePackageJSON(t *testing.T) {
|
|||||||
t.Fatalf("failed to open fixture: %+v", err)
|
t.Fatalf("failed to open fixture: %+v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
actual, err := parsePackageJSON(fixture.Name(), fixture)
|
actual, err := parsePackageJSON("", fixture)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to parse package-lock.json: %+v", err)
|
t.Fatalf("failed to parse package-lock.json: %+v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"version": "6.14.6",
|
||||||
|
"name": "npm",
|
||||||
|
"description": "a package manager for JavaScript",
|
||||||
|
"homepage": "https://docs.npmjs.com/",
|
||||||
|
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me)",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/npm/cli"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://npm.community/c/bugs"
|
||||||
|
},
|
||||||
|
"main": "./lib/npm.js",
|
||||||
|
"license": {
|
||||||
|
"type" : "ISC",
|
||||||
|
"url" : "https://opensource.org/licenses/ISC"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "6 >=6.2.0 || 8 || >=9.3.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"version": "6.14.6",
|
||||||
|
"name": "npm",
|
||||||
|
"description": "a package manager for JavaScript",
|
||||||
|
"homepage": "https://docs.npmjs.com/",
|
||||||
|
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me)",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/npm/cli"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://npm.community/c/bugs"
|
||||||
|
},
|
||||||
|
"main": "./lib/npm.js",
|
||||||
|
"licenses": [
|
||||||
|
{ "type": "MIT",
|
||||||
|
"url": "https://www.opensource.org/licenses/mit-license.php"
|
||||||
|
},
|
||||||
|
{ "type": "Apache-2.0",
|
||||||
|
"url": "https://opensource.org/licenses/apache2.0.php"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "6 >=6.2.0 || 8 || >=9.3.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"version": "6.14.6",
|
||||||
|
"name": "npm",
|
||||||
|
"description": "a package manager for JavaScript",
|
||||||
|
"homepage": "https://docs.npmjs.com/",
|
||||||
|
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me)",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/npm/cli"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://npm.community/c/bugs"
|
||||||
|
},
|
||||||
|
"main": "./lib/npm.js",
|
||||||
|
"engines": {
|
||||||
|
"node": "6 >=6.2.0 || 8 || >=9.3.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user