feat: update syft license concept to complex struct (#1743)

this PR makes the following changes to update the underlying license model to have more expressive capabilities
it also provides some guarantee's surrounding the license values themselves

- Licenses are updated from string -> pkg.LicenseSet which contain pkg.License with the following fields:
- original `Value` read by syft
- If it's possible to construct licenses will always have a valid SPDX expression for downstream consumption
- the above is run against a generated list of SPDX license ID to try and find the correct ID
- SPDX concluded vs declared is added to the new struct
- URL source for license is added to the new struct
- Location source is added to the new struct to show where the expression was pulled from
This commit is contained in:
Christopher Angelo Phillips
2023-05-15 16:23:39 -04:00
committed by GitHub
parent 8046f09562
commit 42fa9e4965
126 changed files with 5165 additions and 1503 deletions
+53 -18
View File
@@ -13,24 +13,42 @@ import (
"github.com/stretchr/testify/require"
"github.com/anchore/syft/internal"
"github.com/anchore/syft/syft/license"
"github.com/anchore/syft/syft/pkg"
"github.com/anchore/syft/syft/source"
)
func Test_LocalLicenseSearch(t *testing.T) {
loc1 := source.NewLocation("github.com/someorg/somename@v0.3.2/LICENSE")
loc2 := source.NewLocation("github.com/!cap!o!r!g/!cap!project@v4.111.5/LICENSE.txt")
tests := []struct {
name string
version string
expected string
expected pkg.License
}{
{
name: "github.com/someorg/somename",
version: "v0.3.2",
expected: "Apache-2.0",
name: "github.com/someorg/somename",
version: "v0.3.2",
expected: pkg.License{
Value: "Apache-2.0",
SPDXExpression: "Apache-2.0",
Type: license.Concluded,
Location: source.NewLocationSet(loc1),
URL: internal.NewStringSet(),
},
},
{
name: "github.com/CapORG/CapProject",
version: "v4.111.5",
expected: "MIT",
name: "github.com/CapORG/CapProject",
version: "v4.111.5",
expected: pkg.License{
Value: "MIT",
SPDXExpression: "MIT",
Type: license.Concluded,
Location: source.NewLocationSet(loc2),
URL: internal.NewStringSet(),
},
},
}
@@ -39,10 +57,12 @@ func Test_LocalLicenseSearch(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
l := newGoLicenses(GoCatalogerOpts{
searchLocalModCacheLicenses: true,
localModCacheDir: path.Join(wd, "test-fixtures", "licenses", "pkg", "mod"),
})
l := newGoLicenses(
GoCatalogerOpts{
searchLocalModCacheLicenses: true,
localModCacheDir: path.Join(wd, "test-fixtures", "licenses", "pkg", "mod"),
},
)
licenses, err := l.getLicenses(source.EmptyResolver{}, test.name, test.version)
require.NoError(t, err)
@@ -54,6 +74,9 @@ func Test_LocalLicenseSearch(t *testing.T) {
}
func Test_RemoteProxyLicenseSearch(t *testing.T) {
loc1 := source.NewLocation("github.com/someorg/somename@v0.3.2/LICENSE")
loc2 := source.NewLocation("github.com/!cap!o!r!g/!cap!project@v4.111.5/LICENSE.txt")
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
buf := &bytes.Buffer{}
uri := strings.TrimPrefix(strings.TrimSuffix(r.RequestURI, ".zip"), "/")
@@ -94,17 +117,29 @@ func Test_RemoteProxyLicenseSearch(t *testing.T) {
tests := []struct {
name string
version string
expected string
expected pkg.License
}{
{
name: "github.com/someorg/somename",
version: "v0.3.2",
expected: "Apache-2.0",
name: "github.com/someorg/somename",
version: "v0.3.2",
expected: pkg.License{
Value: "Apache-2.0",
SPDXExpression: "Apache-2.0",
Type: license.Concluded,
Location: source.NewLocationSet(loc1),
URL: internal.NewStringSet(),
},
},
{
name: "github.com/CapORG/CapProject",
version: "v4.111.5",
expected: "MIT",
name: "github.com/CapORG/CapProject",
version: "v4.111.5",
expected: pkg.License{
Value: "MIT",
SPDXExpression: "MIT",
Type: license.Concluded,
Location: source.NewLocationSet(loc2),
URL: internal.NewStringSet(),
},
},
}